容器"跑起来了"不代表"跑得好"。Docker 自带的 docker stats 只能看实时状态,生产环境需要完整监控:用 cgroups 给容器设资源上限、用 cAdvisor + Prometheus 采集指标、用日志驱动统一收集日志并轮转。本指南把 Docker 的"监控 + 日志"从命令级提升到可告警、可排障的生产体系。
关键概念:容器资源限制靠 Linux cgroups(CPU/内存/IO 限额),采集靠 cAdvisor(容器指标 exporter),日志靠 logging driver(从
docker logs到统一后端)。三者组合起来,容器才有"可观测性"。
1. cgroups:给容器设资源上限
1.1 为什么必须设限制
不设限制的后果:
- 一个容器吃光所有 CPU → 影响其他容器与宿主机
- 内存泄漏 → 触发 OOM,可能拖垮节点
- 磁盘 IO 打满 → 整机卡顿
cgroups 让 Docker 能按容器隔离并限制资源:
- CPU:--cpus(核数)、--cpu-shares(权重)
- 内存:--memory、--memory-swap、--memory-reservation
- IO:--device-read-bps、--device-write-bps
1.2 常用限制示例
# 限制为 2 核、内存 1G、交换 512M
docker run \
--cpus=2 \
--memory=1g \
--memory-swap=1.5g \
--name api \
myapp:1.0
# compose 中同样配置
# deploy.resources.limits.cpus / limits.memory
为什么合理设置很重要:
- 给足资源但留上限 → 防"单容器拖垮全机"
- 设置内存上限 → 内存泄漏有边界(重启优于蔓延)
- 关键服务预留 → 用 cpu-shares 给重要容器更高权重
2. 实时监控:docker stats 与自建采集
2.1 docker stats:秒级实时
docker stats # 所有运行容器
docker stats api db # 指定容器
# 显示:CPU%、内存用量/上限、网络 IO、磁盘 IO、PID
# 带格式化输出方便脚本
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
2.2 采集到 Prometheus:cAdvisor
cAdvisor(Google 开源,现已并入 cadvisor):
作为容器运行,暴露 /metrics(Prometheus 格式)
采集每个容器的 CPU/内存/网络/磁盘指标
部署(compose):
cAdvisor 容器挂载 /var/lib/docker 与 cgroups,暴露 8080
→ Prometheus 用 kubernetes_sd/file_sd/static_config 抓取
→ Grafana 用官方 cadvisor 仪表盘展示
# 运行 cAdvisor(简化版)
docker run -d \
--name cadvisor \
--privileged \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /:/rootfs:ro \
-v /var/lib/docker/:/var/lib/docker:ro \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-p 8080:8080 \
gcr.io/cadvisor/cadvisor:latest
ℹ️ 核心:
docker stats适合当场排障;cAdvisor → Prometheus → Grafana + 告警才是长期监控。容器级指标、节点级指标一起采,才能定位"是容器还是宿主"。
3. 日志驱动:把 docker logs 送到统一后端
3.1 logging driver 是什么
Docker 的容器日志默认 json-file(存在节点磁盘)
→ docker logs 能看到,但:
- 文件无限增长会撑爆磁盘
- 多节点不便集中查看/检索
logging driver 把容器 stdout/stderr 转送到统一后端:
- json-file(默认,本地)
- syslog / journald(系统日志)
- fluentd / fluent-bit(Fluent 生态)
- gelf(Graylog)
- loki(Grafana Loki)
- awslogs / gcp / splunk 等云服务
3.2 配置与日志轮转
# 全局配置(daemon.json)
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m", # 单文件上限
"max-file": "5" # 保留轮转文件数
}
}
# 或单容器指定
docker run --log-driver=json-file \
--log-opt max-size=10m --log-opt max-file=3 myapp
日志轮转是必做项:
不轮转 → 日志文件无上限增长 → 磁盘被日志写满
设置 max-size + max-file 是防"日志撑爆磁盘"的第一道闸
3.3 Loki / Fluentd 集中收集
Loki 方案(轻量,与 Grafana 一体):
promtail 或 docker 的 loki logging driver 收集
→ Loki 存储、Grafana 查询(LogQL)
Fluentd 方案(生态广):
docker 的 fluentd driver 把日志送到 fluentd 集群
→ 可再转 Elasticsearch/Kafka 等
生产建议:
中小规模 → Loki(简单、便宜)
已有 ELK/EFK → 直接接 fluentd/fluent-bit
日志量大 → 采样 + 分级(错误全量、INFO 采样)
4. 健康检查与自动重启
4.1 HEALTHCHECK
# Dockerfile 里定义健康检查
FROM myapp
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -fsS http://localhost:8080/health || exit 1
# 或运行时/compose 指定
docker run --health-cmd="curl -fsS http://localhost/health" \
--health-interval=30s --health-timeout=5s \
--health-retries=3 myapp
4.2 重启策略
# --restart 策略控制崩溃后行为
docker run --restart=unless-stopped myapp
# no / always / on-failure[:N] / unless-stopped
# Swarm/K8s 层面:失败自动重建到期望副本数
# 本地 compose:restart: unless-stopped
健康检查 + 重启策略的组合:
探活失败 → 标记 unhealthy → 编排/重启拉起
单机 docker:on-failure 重启,配日志定位根因
5. 告警与容量规划
告警维度(容器级):
- 内存使用率 > 90% 持续 5m
- CPU 长时间打满
- 容器频繁重启(restart 计数)
- 日志增长异常 / 错误日志激增
容量规划:
- 记录容器峰值资源 → 定合理 limits
- 节点可用资源 vs 所有容器 requests 之和
- 预留余量,避免"容器全挤一个节点"
工具:Prometheus 规则 + Alertmanager 告警到 IM/邮件
# Prometheus 告警示例:容器内存持续超限
- alert: ContainerMemoryHigh
expr: (container_memory_usage_bytes / container_spec_memory_limit_bytes) > 0.9
for: 5m
annotations:
summary: "容器内存使用率超过 90%"
6. 常见避坑
| 坑 | 现象 | 对策 |
|---|---|---|
| 不设资源限制 | 一个容器拖垮全机 | 设 cpus/memory limits |
| 日志不轮转 | 磁盘被写满 | max-size + max-file |
| 只看 docker stats | 无历史、无法告警 | cAdvisor + Prometheus |
| 日志全堆节点磁盘 | 排障难、易丢 | logging driver 集中收集 |
| 无健康检查 | 服务挂了自己不知道 | HEALTHCHECK + 告警 |
| 重启策略 no | 崩溃后不再起来 | restart=unless-stopped |
7. 最佳实践清单
□ 所有容器设 cpus/memory limits(防单容器拖垮)
□ 关键服务用 cpu-shares 保证权重
□ docker stats 只用于当场排障,长期用 cAdvisor+Prometheus
□ Grafana 建容器看板(CPU/内存/网络/磁盘)
□ 日志驱动选 Loki 或 fluentd,接集中后端
□ 配 max-size/max-file 日志轮转
□ HEALTHCHECK + restart 策略 + 告警
□ 记录峰值,做容量规划
□ Alertmanager 告警进 IM/邮件
一句话原则
Docker 可观测性 = cgroups 设边界 + cAdvisor 采指标 + 日志驱动集中收,
三者齐了,容器才算"看得清、防得住、查得了"。
小结
Docker 监控与日志的工程化,本质是给容器"装上仪表盘和安全带":cgroups 限制 CPU/内存/IO 防止失控、cAdvisor + Prometheus + Grafana 建立长期可告警的指标体系、logging driver 把分散日志集中起来并轮转。落地记住五件事:容器必须设资源上限、docker stats 只排障用而 cAdvisor 才是长期采集、日志必配 max-size/max-file 防撑爆、HEALTHCHECK + 重启策略 + 告警闭环、记录峰值做容量规划。当每个容器的资源、状态、日志都清晰可见并自动告警,Docker 环境才从"能跑"升级为"可运营"。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。