WIUNIX ACADEMY
آموزش مانیتورینگ با Prometheus، Grafana و Docker Compose
صفحهٔ 2 از 6؛ مراحل قبلی و پیشنیازها را پیش از ادامه مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
آیپی، دامنه یا پورت مثالها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای بهروزشده را کپی کن.
تنظیم مقادیر برای محیط من11 مقدار قابلتغییر
قدم بعدی
Engine و افزونهٔ Compose را نصب کنید
بستههای رسمی را نصب کنید؛ دستور قدیمی docker-compose مبتنی بر Python مسیر این آموزش نیست. نسخهٔ پایدار بررسیشدهٔ Compose در ۲۰ اکتبر ۲۰۲۶ برابر 5.6.0 است؛ نسخهٔ بستهٔ APT میتواند بین توزیعها متفاوت باشد. نصب از candidate پشتیبانیشدهٔ همان مخزن انجام میشود و نسخهٔ واقعی ثبت میشود؛ pin مشترک و ناموجود برای همهٔ توزیعها فرض نشده است. Engine نگهداریشده و حداقل 28 و Compose جدید لازم است. عضویت ساده در گروه docker پیشنهاد نمیشود، چون عملاً اختیار root میدهد. عملیات daemon در ادامه با sudo انجام میشود.
سرور اختصاصی لینوکس؛ پوستهٔ Bash
sudo apt-get install --no-install-recommends docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl is-active docker
sudo docker version
sudo docker compose version
dpkg-query -W docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo docker network ls
sudo docker network inspect $(sudo docker network ls -q)
داکر فعال است، نسخههای واقعی ثبت شدهاند و شبکهٔ انتخابی با route و شبکههای موجود تداخل ندارد.
قدم بعدی
فقط پوشههای تازه و اختصاصی بسازید
این guard مسیر موجود و تودرتو را رد میکند، اما ایمنی symlink والد را ثابت نمیکند؛ والدها را پیشتر بررسی کنید. تنظیمات با root مدیریت میشود؛ دادهٔ پرومتئوس متعلق به UID/GID برابر 65534 و دادهٔ گرافانا متعلق به UID 472 و GID 0 است که در Compose صریح آمدهاند. برای رفع مجوز، 777 یا اجرای سرویس با root به کار نبرید. دیسک محلی POSIX لازم است؛ TSDB پرومتئوس را روی NFS نگذارید.
سرور اختصاصی لینوکس؛ پوستهٔ Bash
sudo bash -eu <<'SETUP'
paths=('/srv/academy-monitor' '/srv/academy-monitor-backups')
[[ 'academy-monitor' =~ ^[a-z0-9][a-z0-9_-]*$ ]]
for a in "${paths[@]}"; do
[[ "$a" = /* && "$a" != / && ! -e "$a" && ! -L "$a" ]]
for b in "${paths[@]}"; do
[[ "$a" = "$b" ]] && continue
case "$a/" in "$b/"*) exit 1;; esac
done
done
install -d -m 0755 '/srv/academy-monitor' '/srv/academy-monitor/config' '/srv/academy-monitor/config/targets' '/srv/academy-monitor/config/datasources' '/srv/academy-monitor/config/dashboards' '/srv/academy-monitor/dashboards'
install -d -m 0700 '/srv/academy-monitor/secrets' '/srv/academy-monitor-backups'
install -d -m 0750 -o 65534 -g 65534 '/srv/academy-monitor/prometheus-data'
install -d -m 0750 -o 472 -g 0 '/srv/academy-monitor/grafana-data'
SETUP
پوشههای تازه با مالکیت مشخص ساخته شدهاند و دادهٔ نامرتبط ندارند.
قدم بعدی
ایمیج رسمی را با digest ثابت کنید
digestهای زیر فهرست چندمعماری نسخهٔ مشخص Prometheus 3.15.0 و Grafana OSS 13.2.4 را ثابت میکنند. مسیر OSS گرافانا اکنون grafana/grafana است و مخزن grafana-oss بهروزرسانی نمیشود. tag نام خواناست؛ digest فایل واقعی را تعیین میکند. پیش از استفادهٔ بعدی، معماری و هشدارهای امنیتی سازنده را دوباره ببینید. HTTPS و digest، امضای مستقل یا تضمین نبود آسیبپذیری نیستند. مسیر آموزش فقط amd64 و arm64 لینوکس است و emulation پنهانی ندارد. دریافت ایمیج با خروجی شبکهٔ daemon انجام میشود، نه شبکهٔ داخلی سرویسها.
سرور اختصاصی لینوکس؛ پوستهٔ Bash
sudo docker buildx imagetools inspect prom/prometheus:v3.15.0@sha256:efd719c99d83b060d9daefdcf00360461adf279f45ef5391f8d111892118753e
sudo docker buildx imagetools inspect grafana/grafana:13.2.4@sha256:dbbc38ea21103cefb50396340cd88afec779c7e070b0a7bf5a75b4ce46651d3f
digest و معماری بومی لینوکس با فهرست بررسیشده یکساناند.
قدم بعدی
رمز اولیه را فقط در ویرایشگر محافظتشده وارد کنید
رمز قوی، یکتا و تازهٔ مدیر گرافانا را در یک خط در ویرایشگر محافظتشده بنویسید. رمز نباید در آرگومان دستور، فایل env، فیلد آموزش، Git، اسکرینشات یا لاگ ترمینال اشتراکی باشد. فایل فقط به گرافانا mount میشود. secret در Compose معمولی یک bind mount فایل محلی است و ذخیرهٔ رمزنگاریشدهٔ Swarm نیست؛ مجوز میزبان اهمیت دارد. remap کردن uid/gid/mode برای secret فایلمحور انجام نمیشود. مالک root و گروه 0 با مجوز 0440 به گرافانای UID472/GID0 اجازهٔ خواندن فایل mountشده میدهد؛ والد 0700 منبع میزبان را محافظت میکند. این رمز فقط دیتابیس تازه را مقداردهی اولیه میکند و تغییر فایل، رمز مدیر موجود را عوض نمیکند.
سرور اختصاصی لینوکس؛ پوستهٔ Bash
sudo install -m 0600 /dev/null '/srv/academy-monitor/secrets/grafana-admin'
sudo nano '/srv/academy-monitor/secrets/grafana-admin'
sudo chown root:0 '/srv/academy-monitor/secrets/grafana-admin'
sudo chmod 0440 '/srv/academy-monitor/secrets/grafana-admin'
sudo test -s '/srv/academy-monitor/secrets/grafana-admin'
فایل رمز خالی نیست و بدون نمایش رمز، محافظت شده است.
قدم بعدی
فایل Compose را باز کنید
فایل تازه را باز کنید و پنل کامل بعدی را در آن بگذارید. فایلهای bind باید پیش از اجرا واقعاً موجود باشند؛ نبودن فایل را با ساخت خودکار یک پوشه جایگزین نکنید.
سرور اختصاصی لینوکس؛ پوستهٔ Bash
sudo nano '/srv/academy-monitor/compose.yaml'
ویرایشگر برای فایل کامل YAML آماده است.
Compose؛ هویت، ذخیرهسازی و جداسازی
فایل را کامل ذخیره کنید. شبکهٔ internal خروجی عادی اینترنت را میبندد؛ دریافت پلاگین، دیتاسورس خارجی، ایمیل و OAuth در این تمرین نداریم. این محدودیت، root میزبان یا همسایهٔ شبکه را حذف نمیکند. bind mount مسیر بکاپ همان میزبان را روشن میکند؛ volume نامدار هم راه رسمی است، اما بازیابی متناسب با خودش را لازم دارد. سقف منابع رزرو ظرفیت نیست. سرویسها مستقل شروع میشوند و readiness را در بخش بعد جداگانه ثابت میکنیم. restart policy برای فرایند خارجشده است و بهتنهایی سرویس هنگکرده را تشخیص نمیدهد.
name: academy-monitor
services:
prometheus:
image: prom/prometheus:v3.15.0@sha256:efd719c99d83b060d9daefdcf00360461adf279f45ef5391f8d111892118753e
user: "65534:65534"
restart: unless-stopped
read_only: true
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
mem_limit: 1536m
cpus: 1.0
pids_limit: 128
tmpfs: [/tmp:size=64m,mode=1777]
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention.time=15d
- --storage.tsdb.retention.size=5GB
- --web.listen-address=0.0.0.0:9090
ports: ["127.0.0.1:19090:9090"]
volumes:
- type: bind
source: /srv/academy-monitor/config/prometheus.yml
target: /etc/prometheus/prometheus.yml
read_only: true
bind: {create_host_path: false}
- type: bind
source: /srv/academy-monitor/config/targets
target: /etc/prometheus/targets
read_only: true
bind: {create_host_path: false}
- type: bind
source: /srv/academy-monitor/prometheus-data
target: /prometheus
bind: {create_host_path: false}
networks: [monitor]
logging:
driver: json-file
options: {max-size: "10m", max-file: "3"}
grafana:
image: grafana/grafana:13.2.4@sha256:dbbc38ea21103cefb50396340cd88afec779c7e070b0a7bf5a75b4ce46651d3f
user: "472:0"
restart: unless-stopped
read_only: true
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
mem_limit: 768m
cpus: 1.0
pids_limit: 256
tmpfs: [/tmp:size=64m,mode=1777]
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin
GF_AUTH_ANONYMOUS_ENABLED: "false"
GF_USERS_ALLOW_SIGN_UP: "false"
GF_METRICS_ENABLED: "true"
GF_ANALYTICS_REPORTING_ENABLED: "false"
GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: "false"
GF_PLUGINS_PREINSTALL_DISABLED: "true"
ports: ["127.0.0.1:13000:3000"]
secrets: [grafana_admin]
volumes:
- type: bind
source: /srv/academy-monitor/grafana-data
target: /var/lib/grafana
bind: {create_host_path: false}
- type: bind
source: /srv/academy-monitor/config/datasources
target: /etc/grafana/provisioning/datasources
read_only: true
bind: {create_host_path: false}
- type: bind
source: /srv/academy-monitor/config/dashboards
target: /etc/grafana/provisioning/dashboards
read_only: true
bind: {create_host_path: false}
- type: bind
source: /srv/academy-monitor/dashboards
target: /var/lib/grafana/dashboards
read_only: true
bind: {create_host_path: false}
networks: [monitor]
logging:
driver: json-file
options: {max-size: "10m", max-file: "3"}
networks:
monitor:
internal: true
ipam:
config: [{subnet: "172.30.71.0/24"}]
secrets:
grafana_admin:
file: /srv/academy-monitor/secrets/grafana-admin