Đến lúc bắt tay thực hành. Bài này dựng một stack giám sát hoàn chỉnh bằng Docker Compose: Grafana để trực quan hoá, Prometheus để thu thập & lưu metrics, và Node Exporter để phát metrics của máy. Toàn bộ cấu hình dưới đây là thật, copy-paste chạy được ngay — kể cả phần provisioning để Grafana tự động có sẵn data source khi khởi động. Yêu cầu: đã cài Docker Desktop (hoặc Docker Engine) có Docker Compose v2.
Ba container chạy trên cùng một Docker network (Compose tự tạo). Trong network đó, mỗi service gọi nhau qua tên service (DNS nội bộ), còn ta truy cập từ máy host qua cổng đã publish:
| Service | Image | Cổng (host:container) | Vai trò |
|---|---|---|---|
| Grafana | grafana/grafana | 3000:3000 | Giao diện web, dashboard. Query Prometheus. |
| Prometheus | prom/prometheus | 9090:9090 | Thu thập & lưu metrics. Scrape node-exporter. |
| Node Exporter | prom/node-exporter | 9100:9100 | Phát metrics phần cứng/OS (CPU, RAM, disk...). |
Luồng dữ liệu đi theo hướng:
:9100/metrics (CPU, RAM, filesystem, network của máy host).node-exporter:9100/metrics, và cả chính nó localhost:9090, rồi lưu vào TSDB nội bộ.http://prometheus:9090 mỗi khi render panel, rồi vẽ lên dashboard.http://localhost:3000 để xem.prometheus.yml ta khai báo target là những địa chỉ Prometheus cần đến kéo.Tạo một thư mục grafana-lab với bố cục sau. Việc tách file provisioning giúp Grafana tự cấu hình khi khởi động, không cần bấm tay:
Tạo nhanh khung thư mục bằng lệnh (chạy trong thư mục cha):
# Linux / macOS / Git Bash
mkdir -p grafana-lab/prometheus
mkdir -p grafana-lab/grafana/provisioning/datasources
mkdir -p grafana-lab/grafana/provisioning/dashboards
# Windows PowerShell
New-Item -ItemType Directory -Force grafana-lab\prometheus
New-Item -ItemType Directory -Force grafana-lab\grafana\provisioning\datasources
New-Item -ItemType Directory -Force grafana-lab\grafana\provisioning\dashboards
Đây là file trung tâm. Lưu vào grafana-lab/docker-compose.yml:
services: prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - "9090:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.enable-lifecycle' networks: - monitoring node-exporter: image: prom/node-exporter:latest container_name: node-exporter restart: unless-stopped ports: - "9100:9100" command: - '--path.rootfs=/host' volumes: - /:/host:ro,rslave networks: - monitoring grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false volumes: - grafana-storage:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning:ro depends_on: - prometheus networks: - monitoring volumes: prometheus-data: grafana-storage: networks: monitoring: driver: bridge
node-exporter mount /:/host:ro và dùng --path.rootfs=/host để đọc được metrics thật của máy host (không phải của container). --web.enable-lifecycle cho phép reload cấu hình Prometheus qua HTTP mà không cần restart. Hai volumes ở cuối giữ dữ liệu tồn tại qua các lần restart.Prometheus cần biết kéo metrics từ đâu và bao lâu một lần. Lưu vào grafana-lab/prometheus/prometheus.yml:
global: scrape_interval: 15s # mặc định kéo mỗi 15 giây evaluation_interval: 15s # đánh giá rule mỗi 15 giây scrape_configs: # 1) Prometheus tự giám sát chính nó - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] # 2) Node Exporter — gọi qua tên service trong Docker network - job_name: 'node-exporter' static_configs: - targets: ['node-exporter:9100']
node-exporter:9100 chứ không phải localhost:9100. Trong container Prometheus, localhost là chính nó — nó phải gọi node-exporter qua tên service (DNS của Docker network). Đây là lỗi kinh điển của người mới.Data source. Thay vì vào UI bấm tay, ta khai báo Prometheus bằng file YAML để Grafana tự nạp khi khởi động. Lưu vào grafana-lab/grafana/provisioning/datasources/datasource.yml:
apiVersion: 1 datasources: - name: Prometheus type: prometheus access: proxy url: http://prometheus:9090 isDefault: true editable: true
Chú ý url là http://prometheus:9090 — dùng tên service, vì Grafana container gọi Prometheus container qua DNS nội bộ của Docker network, không phải qua localhost của máy host.
Dashboard provider. File này bảo Grafana quét một thư mục và tự nạp mọi file dashboard .json trong đó. Lưu vào grafana-lab/grafana/provisioning/dashboards/dashboard.yml:
apiVersion: 1 providers: - name: 'default' orgId: 1 folder: '' type: file disableDeletion: false updateIntervalSeconds: 30 allowUiUpdates: true options: path: /etc/grafana/provisioning/dashboards
grafana/provisioning/dashboards/ — Grafana sẽ tự import theo provider trên. Ở lab này ta sẽ import qua UI cho trực quan (mục tiếp theo), cách nào cũng được.grafana-lab, chạy:
docker compose up -dDocker sẽ tải image và bật cả 3 container ở chế độ nền. Kiểm tra bằng
docker compose ps — cả ba phải ở trạng thái Up.http://localhost:9090 → menu Status → Targets. Cả prometheus và node-exporter phải hiện UP. Nếu node-exporter DOWN, xem lại tên target trong prometheus.yml.http://localhost:3000.admin / admin (theo biến môi trường đã đặt trong compose).1860, bấm Load, chọn data source Prometheus, rồi Import. Bạn sẽ thấy ngay dashboard đầy đủ CPU, RAM, disk, network của máy.Grafana cấu hình rất tốt qua biến môi trường, theo quy tắc GF_<SECTION>_<KEY>. Vài biến hữu ích:
| Biến | Tác dụng |
|---|---|
GF_SECURITY_ADMIN_PASSWORD | Đặt mật khẩu admin ban đầu (thay cho admin mặc định). |
GF_SECURITY_ADMIN_USER | Đổi tên tài khoản admin. |
GF_USERS_ALLOW_SIGN_UP | false để tắt tự đăng ký tài khoản. |
GF_AUTH_ANONYMOUS_ENABLED | true để cho xem dashboard mà không cần đăng nhập. |
GF_AUTH_ANONYMOUS_ORG_ROLE | Quyền của khách ẩn danh: Viewer (chỉ xem) là an toàn nhất. |
environment của service grafana:
- GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer
grafana-storage mount vào /var/lib/grafana giữ lại toàn bộ user, dashboard tự tạo, cấu hình... qua các lần restart. Nếu không khai báo volume này, mọi thứ tạo qua UI sẽ mất khi container bị xoá. Tương tự, prometheus-data giữ lịch sử metrics của Prometheus.Dừng và dọn dẹp lab:
# Dừng nhưng GIỮ dữ liệu (volume còn nguyên) docker compose down # Dừng và XOÁ luôn dữ liệu (volume bị xoá) docker compose down -v
http://localhost:9090 thay vì http://prometheus:9090. Trong container Grafana, localhost trỏ về chính Grafana, không phải máy host. Phải dùng tên service Docker (prometheus). Sửa lại datasource.yml hoặc ô URL trong UI."3001:3000" rồi mở localhost:3001; hoặc tắt tiến trình đang chiếm cổng đó. Kiểm tra bằng docker ps hoặc netstat.Vài lệnh chẩn đoán nhanh:
# Xem trạng thái các container docker compose ps # Xem log của một service (theo dõi realtime) docker compose logs -f grafana docker compose logs -f prometheus # Vào trong container Prometheus để test kết nối tới node-exporter docker compose exec prometheus wget -qO- http://node-exporter:9100/metrics | head
http://localhost:9090/targets. Nếu báo lỗi kết nối, kiểm tra: (1) target đúng là node-exporter:9100, (2) cả hai service cùng network monitoring, (3) container node-exporter đang Up (docker compose ps).