Docker 监控体系:cAdvisor + Prometheus + Grafana 完整部署与核心指标
系统讲解 Docker 容器监控体系的完整搭建:cAdvisor 采集容器 CPU/内存/网络/磁盘 IO 指标原理、Prometheus 抓取配置与 Docker Daemon 指标启用、Grafana 仪表板配置(推荐 Dashboard ID)、核心告警规则(OOM/容器异常退出/资源使用率过高),以及生产环境的监控数据保留与存储优化方案。
容器运行后,如何知道它是否健康、资源是否充足、哪个容器消耗最多 CPU?没有监控的容器等于盲飞。本文搭建以 cAdvisor + Prometheus + Grafana 为核心的 Docker 监控体系,这也是业界最主流的方案。
监控体系架构
数据采集层:
cAdvisor → 容器级指标(CPU/内存/网络/IO)
node-exporter → 宿主机级指标(磁盘/CPU/内存/网络)
Docker Daemon → Docker 引擎指标(镜像/容器/volume 数量)
数据存储层:
Prometheus → 时序数据库(抓取、存储、查询)
可视化/告警层:
Grafana → 仪表板(图形化展示)
Alertmanager → 告警路由(邮件/钉钉/Slack)
数据流向:
cAdvisor ─┐
node-exporter ─┤→ Prometheus → Grafana
Docker Daemon ─┘ ↓
Alertmanager → 通知
一、cAdvisor 部署
cAdvisor(Container Advisor)是 Google 开源的容器指标采集器,通过读取 cgroup 和 /proc 获取每个容器的资源使用情况。
# docker-compose.yml(监控栈)
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
container_name: cadvisor
restart: unless-stopped
privileged: true # 需要访问 cgroup 和设备信息
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
devices:
- /dev/kmsg
command:
- --housekeeping_interval=10s # 采集间隔
- --max_housekeeping_interval=15s
- --event_storage_event_limit=default=0
- --event_storage_age_limit=default=0
- --disable_metrics=percpu,sched,tcp,udp,disk,diskIO,hugetlb,referenced_memory,cpu_topology,resctrl
# 禁用不需要的指标,减少 Prometheus 存储压力
networks:
- monitoring
cAdvisor 核心指标:
# CPU 使用率(%)
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100
# 内存使用量(字节)
container_memory_usage_bytes{name!=""}
# 内存使用率(%)
container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""} * 100
# 网络接收速率(bytes/s)
rate(container_network_receive_bytes_total{name!=""}[5m])
# 网络发送速率(bytes/s)
rate(container_network_transmit_bytes_total{name!=""}[5m])
# 磁盘读速率(bytes/s)
rate(container_fs_reads_bytes_total{name!=""}[5m])
# 磁盘写速率(bytes/s)
rate(container_fs_writes_bytes_total{name!=""}[5m])
# 容器重启次数
container_start_time_seconds{name!=""}
二、Docker Daemon 指标启用
Docker 19.03+ 支持直接暴露 Prometheus 指标。
// /etc/docker/daemon.json
{
"metrics-addr": "0.0.0.0:9323",
"experimental": true
}
systemctl restart docker
# 验证
curl http://localhost:9323/metrics | grep engine_daemon
# engine_daemon_container_states_containers{state="running"} 12
# engine_daemon_container_states_containers{state="stopped"} 3
# engine_daemon_image_actions_seconds_count{action="pull"} 47
Docker Daemon 核心指标:
# 运行中的容器数
engine_daemon_container_states_containers{state="running"}
# 停止的容器数
engine_daemon_container_states_containers{state="stopped"}
# 镜像总数
engine_daemon_images_total
# pull 操作耗时(p99)
histogram_quantile(0.99, rate(engine_daemon_image_actions_seconds_bucket{action="pull"}[5m]))
三、Prometheus 配置
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.yml
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
scrape_configs:
# Prometheus 自身
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# cAdvisor — 容器指标
- job_name: 'cadvisor'
scrape_interval: 10s
static_configs:
- targets: ['cadvisor:8080']
metric_relabel_configs:
# 只保留有容器名的指标(过滤掉宿主机层的数据)
- source_labels: [container_label_com_docker_compose_service]
target_label: service
# 丢弃无用标签,减少存储
- regex: 'container_label_.*'
action: labeldrop
# node-exporter — 宿主机指标
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
# Docker Daemon 指标
- job_name: 'docker-daemon'
static_configs:
- targets: ['172.17.0.1:9323'] # docker0 网关 IP
# docker-compose.yml(接上)
prometheus:
image: prom/prometheus:v2.54.0
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/rules:/etc/prometheus/rules:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d' # 保留 30 天数据
- '--storage.tsdb.retention.size=20GB' # 最多 20GB
- '--web.enable-lifecycle' # 允许热重载配置
networks:
- monitoring
node-exporter:
image: prom/node-exporter:v1.8.2
container_name: node-exporter
restart: unless-stopped
network_mode: host # host 模式采集宿主机指标
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
四、Grafana 配置
# docker-compose.yml(接上)
grafana:
image: grafana/grafana:11.2.0
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=Admin@123
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_ROOT_URL=https://grafana.company.com
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
# grafana/provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
推荐 Grafana Dashboard(直接导入 ID):
Dashboard ID 名称 说明
────────────────────────────────────────────────────────
193 Docker & System Dashboard 容器+宿主机综合视图
3662 Prometheus 2.0 Overview Prometheus 自身监控
1860 Node Exporter Full 宿主机详细指标
14282 Docker Containers 容器资源对比
# 导入方式:Grafana UI → + → Import → 输入 Dashboard ID → Load
五、告警规则
# prometheus/rules/docker-alerts.yml
groups:
- name: docker-container-alerts
interval: 30s
rules:
# 容器 OOM 被杀(最高优先级)
- alert: ContainerOOMKilled
expr: |
kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} == 1
OR
container_oom_events_total > 0
for: 0m # 立即告警
labels:
severity: critical
annotations:
summary: "容器 OOM 被杀:{{ $labels.name }}"
description: "容器 {{ $labels.name }} 因内存超限被 OOM Kill,请检查内存使用情况"
# 容器不断重启
- alert: ContainerRestarting
expr: |
rate(container_start_time_seconds{name!=""}[15m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "容器频繁重启:{{ $labels.name }}"
description: "容器 {{ $labels.name }} 在过去 15 分钟内频繁重启"
# CPU 使用率超过 80%
- alert: ContainerCpuHigh
expr: |
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 > 80
for: 10m
labels:
severity: warning
annotations:
summary: "容器 CPU 使用率高:{{ $labels.name }}"
description: "容器 {{ $labels.name }} CPU 使用率 {{ $value | printf \"%.1f\" }}%,持续 10 分钟"
# 内存使用率超过 85%
- alert: ContainerMemoryHigh
expr: |
container_memory_usage_bytes{name!=""}
/ container_spec_memory_limit_bytes{name!=""}
* 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "容器内存使用率高:{{ $labels.name }}"
description: "容器 {{ $labels.name }} 内存使用率 {{ $value | printf \"%.1f\" }}%"
# 容器停止运行
- alert: ContainerDown
expr: |
absent(container_last_seen{name="nginx-prod"})
OR
(time() - container_last_seen{name="nginx-prod"}) > 60
for: 1m
labels:
severity: critical
annotations:
summary: "关键容器停止:{{ $labels.name }}"
- name: docker-host-alerts
rules:
# 宿主机磁盘使用率超过 85%
- alert: HostDiskUsageHigh
expr: |
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"})
/ node_filesystem_size_bytes{mountpoint="/"} * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "宿主机磁盘使用率高:{{ $value | printf \"%.1f\" }}%"
# Docker 数据目录磁盘使用率
- alert: DockerStorageLow
expr: |
(node_filesystem_size_bytes{mountpoint="/var/lib/docker"} - node_filesystem_free_bytes{mountpoint="/var/lib/docker"})
/ node_filesystem_size_bytes{mountpoint="/var/lib/docker"} * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "Docker 存储空间不足,使用率 {{ $value | printf \"%.1f\" }}%"
六、Alertmanager 配置(钉钉告警)
# alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'dingtalk'
routes:
- match:
severity: critical
receiver: 'dingtalk-critical'
repeat_interval: 30m # 严重告警每 30 分钟重复
receivers:
- name: 'dingtalk'
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/ops_general/send'
send_resolved: true
- name: 'dingtalk-critical'
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/ops_critical/send'
send_resolved: true
七、监控运维常用查询
# Top 5 CPU 消耗最高的容器
topk(5,
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100
)
# Top 5 内存消耗最高的容器
topk(5, container_memory_usage_bytes{name!=""})
# 容器网络流量排行
topk(5,
rate(container_network_receive_bytes_total{name!=""}[5m])
+ rate(container_network_transmit_bytes_total{name!=""}[5m])
)
# 最近 1 小时内曾经重启过的容器
changes(container_start_time_seconds{name!=""}[1h]) > 0
# 容器资源使用率(CPU 超过 limit 的 70%)
rate(container_cpu_usage_seconds_total{name!=""}[5m])
/ (container_spec_cpu_quota{name!=""} / container_spec_cpu_period{name!=""})
* 100 > 70
# 内存接近 limit(超过 90%)
container_memory_usage_bytes{name!=""}
/ container_spec_memory_limit_bytes{name!=""} * 100 > 90
小结
Docker 监控三件套的职责分工:cAdvisor 负责从 cgroup 读取容器资源数据(每 10 秒),Prometheus 负责抓取和存储时序指标(保留 30 天),Grafana 负责可视化和告警展示。
生产中最重要的四个告警:OOM Kill(容器内存超限被杀)、容器频繁重启、CPU/内存使用率持续过高、磁盘空间不足。这四个问题如果没有监控,往往在造成业务中断后才被发现。
