跳到主要内容

Docker 监控与调试

有效的监控和调试是保障容器化应用稳定运行的关键。本章将介绍 Docker 的监控工具、日志管理和故障排除技术。

监控概述

为什么需要监控?

容器化环境的监控与传统应用有所不同:

监控维度传统应用容器化应用
资源粒度虚拟机/物理机容器级别
生命周期长期运行动态创建销毁
网络模型固定 IP动态网络
日志收集文件系统标准输出

监控指标层次

监控可以分为三个层次:

  • 应用指标:请求量、响应时间、错误率、业务指标
  • 容器指标:CPU、内存、网络、磁盘 IO
  • 主机指标:节点资源、内核状态、存储容量

容器监控的核心是了解每个容器的资源使用情况,以便及时发现性能瓶颈和异常行为。

内置监控命令

docker stats - 容器资源统计

docker stats 是最常用的资源监控命令,可以实时查看容器的资源使用情况:

# 实时查看所有容器资源使用
docker stats

# 查看特定容器
docker stats nginx redis

# 不实时刷新(只显示一次)
docker stats --no-stream

# 自定义输出格式
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# JSON 格式输出(便于程序处理)
docker stats --format json --no-stream

输出示例:

CONTAINER ID   NAME      CPU %   MEM USAGE / LIMIT   MEM %   NET I/O     BLOCK I/O   PIDS
a1b2c3d4e5f6 nginx 0.50% 10MiB / 1GiB 1.00% 1.2kB / 0B 0B / 0B 5
b2c3d4e5f6g7 redis 0.25% 5MiB / 1GiB 0.50% 500B / 0B 0B / 0B 4

指标说明

指标说明
CPU %CPU 使用百分比
MEM USAGE / LIMIT内存使用量 / 限制
MEM %内存使用百分比
NET I/O网络接收/发送字节
BLOCK I/O磁盘读写字节
PIDS进程数

docker top - 查看容器进程

# 查看容器内进程
docker top nginx

# 显示完整命令
docker top nginx aux

# 显示特定信息
docker top nginx -o pid,comm

输出示例:

UID    PID    PPID   C    STIME   TTY    TIME       CMD
root 1234 567 0 10:00 ? 00:00:01 nginx: master process
101 1235 1234 0 10:00 ? 00:00:00 nginx: worker process

docker events - 监听 Docker 事件

# 实时监听 Docker 事件
docker events

# 过滤特定事件类型
docker events --filter type=container

# 过滤特定容器
docker events --filter container=nginx

# 过滤事件动作
docker events --filter event=start --filter event=stop --filter event=die

# 时间范围过滤
docker events --since 1h
docker events --since "2024-01-01" --until "2024-01-02"

# 格式化输出
docker events --format '{{.Time}} {{.Type}} {{.Action}} {{.Actor.ID}}'

docker inspect - 查看容器详情

# 查看完整配置
docker inspect nginx

# 查看特定信息
docker inspect --format='{{.State.Status}}' nginx
docker inspect --format='{{.State.Health.Status}}' nginx
docker inspect --format='{{.NetworkSettings.IPAddress}}' nginx
docker inspect --format='{{.HostConfig.Memory}}' nginx

# 查看所有容器的 IP
docker inspect --format='{{.Name}} {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)

控制组 (cgroups) 指标

Docker 使用 Linux 控制组 (cgroups) 来跟踪和限制容器的资源使用。你可以直接从 cgroups 文件系统获取详细的指标。

查找容器的 cgroup 路径

根据 cgroup 版本和驱动,路径有所不同:

cgroup v1

  • cgroupfs 驱动:/sys/fs/cgroup/memory/docker/<container_id>/
  • systemd 驱动:/sys/fs/cgroup/memory/system.slice/docker-<container_id>.scope/

cgroup v2

  • cgroupfs 驱动:/sys/fs/cgroup/docker/<container_id>/
  • systemd 驱动:/sys/fs/cgroup/system.slice/docker-<container_id>.scope/

内存指标

内存指标位于 memory.stat 文件中:

# 查看内存统计
cat /sys/fs/cgroup/memory/docker/<container_id>/memory.stat

关键指标说明:

指标说明
cache页缓存大小
rss驻留内存集(不含缓存)
mapped_file映射文件大小
swap交换空间使用量
pgfault页错误次数
pgmajfault主要页错误次数
active_anon活跃匿名内存
inactive_anon非活跃匿名内存

CPU 指标

CPU 指标位于 cpuacct.stat 文件中:

# 查看 CPU 统计
cat /sys/fs/cgroup/cpuacct/docker/<container_id>/cpuacct.stat

输出示例:

user 1234
system 567
  • user:用户态 CPU 时间(1/100 秒为单位)
  • system:内核态 CPU 时间

网络指标

网络指标需要从网络命名空间获取:

# 获取容器 PID
PID=$(docker inspect --format '{{.State.Pid}}' nginx)

# 查看网络接口统计
cat /proc/$PID/net/dev

日志管理

查看容器日志

# 查看日志
docker logs nginx

# 实时跟踪日志
docker logs -f nginx

# 显示最后 100 行
docker logs --tail 100 nginx

# 显示时间戳
docker logs -t nginx

# 时间范围过滤
docker logs --since 2024-01-01 nginx
docker logs --since 2h nginx
docker logs --until 1h nginx

# 组合使用
docker logs -f --tail 100 --since 1h nginx

日志驱动

Docker 支持多种日志驱动:

驱动说明适用场景
json-file默认,JSON 格式存储单机开发
local优化的本地日志生产环境
journald发送到 systemd journalsystemd 系统
syslog发送到 syslog 守护进程集中式日志
fluentd发送到 Fluentd日志聚合
awslogs发送到 AWS CloudWatchAWS 环境
none禁用日志安全敏感场景

配置日志驱动

运行时指定日志驱动

# 使用 local 驱动(推荐)
docker run -d --log-driver=local nginx

# 使用 syslog
docker run -d --log-driver=syslog \
--log-opt syslog-address=tcp://192.168.1.1:514 \
nginx

# 禁用日志
docker run -d --log-driver=none nginx

# json-file 带限制
docker run -d \
--log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx

Docker Daemon 全局配置

编辑 /etc/docker/daemon.json

{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}

重启 Docker 使配置生效:

sudo systemctl restart docker

Docker Compose 配置

services:
app:
image: myapp
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

日志传递模式

Docker 提供两种日志传递模式:

  • blocking(默认):直接阻塞式传递,可能影响应用性能
  • non-blocking:使用中间缓冲区,避免阻塞
# 使用非阻塞模式
docker run -d \
--log-opt mode=non-blocking \
--log-opt max-buffer-size=4m \
nginx

日志聚合方案

使用 ELK Stack

services:
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data

logstash:
image: logstash:8.11.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5000:5000"
depends_on:
- elasticsearch

kibana:
image: kibana:8.11.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch

app:
image: myapp
logging:
driver: "syslog"
options:
syslog-address: "tcp://logstash:5000"
tag: "myapp"

volumes:
es-data:

使用 Loki + Grafana

services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml

promtail:
image: grafana/promtail:latest
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml

grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
volumes:
- grafana-data:/var/lib/grafana

volumes:
grafana-data:

Prometheus 监控

部署 Prometheus 监控栈

services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'

grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana

cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro

node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro

volumes:
prometheus-data:
grafana-data:

Prometheus 配置 (prometheus.yml)

global:
scrape_interval: 15s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['prometheus:9090']

- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']

- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']

cAdvisor 主要指标

cAdvisor 提供的容器监控指标:

指标说明
container_cpu_usage_seconds_totalCPU 使用时间
container_memory_usage_bytes内存使用量
container_network_receive_bytes_total网络接收字节
container_network_transmit_bytes_total网络发送字节
container_fs_usage_bytes文件系统使用量
container_last_seen容器最后可见时间

常用 PromQL 查询

# 容器 CPU 使用率
rate(container_cpu_usage_seconds_total{name!="",image!=""}[5m]) * 100

# 容器内存使用
container_memory_usage_bytes{name!="",image!=""}

# 容器网络流量
rate(container_network_receive_bytes_total[5m])
rate(container_network_transmit_bytes_total[5m])

# 按容器名汇总 CPU
sum(rate(container_cpu_usage_seconds_total{name!="",image!=""}[5m])) by (name)

# 内存使用率最高的 5 个容器
topk(5, container_memory_usage_bytes{name!=""})

# 容器数量
count(container_last_seen)

故障排除

容器启动失败

检查容器状态

# 查看所有容器(包括已停止的)
docker ps -a

# 查看容器退出原因
docker inspect --format='{{.State.ExitCode}}' nginx
docker inspect --format='{{.State.Error}}' nginx
docker inspect --format='{{.State.OOMKilled}}' nginx

# 查看容器日志
docker logs nginx

常见退出码

退出码说明
0正常退出
1应用错误
137被 SIGKILL 杀死(可能是 OOM)
139段错误(Segmentation Fault)
143被 SIGTERM 终止

进入容器调试

# 执行单个命令
docker exec nginx ls /app

# 进入交互终端
docker exec -it nginx bash

# 使用 sh(如果没有 bash)
docker exec -it nginx sh

# 以 root 用户进入
docker exec -it -u root nginx bash

# 指定工作目录
docker exec -it -w /app nginx bash

# 传递环境变量
docker exec -it -e DEBUG=true nginx bash

网络调试

# 查看容器网络配置
docker network inspect bridge

# 查看容器端口映射
docker port nginx

# 进入容器测试网络
docker exec -it nginx sh
# 在容器内执行
ping db
curl http://api:3000/health

# 使用专用网络调试容器
docker run --rm -it --network container:nginx nicolaka/netshoot
# 在调试容器中可以使用各种网络工具
dig db
curl -v http://localhost:80
tcpdump -i eth0

存储调试

# 查看容器挂载
docker inspect --format='{{json .Mounts}}' nginx | jq

# 查看数据卷
docker volume ls
docker volume inspect my-volume

# 查看容器磁盘使用
docker system df

# 查看容器文件系统变更
docker diff nginx

# 从容器复制文件出来
docker cp nginx:/app/logs ./logs

性能调试

# 实时监控资源
docker stats nginx

# 查看容器进程
docker top nginx

# 使用 perf 分析(需要特权)
docker run --rm -it --privileged --pid=container:nginx \
-v /lib/modules:/lib/modules \
nicolaka/netshoot perf top

# 使用 strace 跟踪系统调用
docker run --rm -it --privileged --pid=container:nginx \
nicolaka/netshoot strace -p 1

健康检查调试

# 查看健康检查状态
docker inspect --format='{{json .State.Health}}' nginx | jq

# 查看健康检查日志
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' nginx

# 手动执行健康检查命令
docker exec nginx curl -f http://localhost/health

实用调试工具

网络调试容器

nicolaka/netshoot 是一个包含丰富网络工具的调试镜像:

# 创建包含各种网络工具的容器
docker run --rm -it --network my-network nicolaka/netshoot

# 常用命令
dig db # DNS 查询
curl -v http://api:3000 # HTTP 请求
nc -zv db 3306 # 端口测试
tcpdump -i eth0 # 抓包
ss -tuln # 查看端口
ip addr # 网络接口

存储调试容器

# 挂载数据卷进行调试
docker run --rm -it -v my-volume:/data alpine sh
# 在容器中查看数据
ls -la /data
cat /data/config.yml

容器资源限制调试

# 检查容器资源限制
docker inspect --format='Memory: {{.HostConfig.Memory}}, CPU: {{.HostConfig.NanoCpus}}' nginx

# 测试内存限制
docker run --rm -it --memory="100m" progrium/stress --vm 1 --vm-bytes 150M

# 测试 CPU 限制
docker run --rm -it --cpus="0.5" progrium/stress --cpu 4

监控告警

Prometheus 告警规则

# alert.rules.yml
groups:
- name: docker_alerts
rules:
- alert: ContainerDown
expr: absent(container_last_seen{name=~".+"})
for: 5m
labels:
severity: critical
annotations:
summary: "Container {{ $labels.name }} is down"

- alert: HighMemoryUsage
expr: container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""} * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "Container {{ $labels.name }} memory usage > 90%"

- alert: HighCPUUsage
expr: rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "Container {{ $labels.name }} CPU usage > 80%"

Alertmanager 配置

# alertmanager.yml
global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: '[email protected]'
smtp_auth_username: '[email protected]'
smtp_auth_password: 'password'

route:
receiver: 'team-email'
group_wait: 30s
group_interval: 5m
repeat_interval: 1h

receivers:
- name: 'team-email'
email_configs:
- to: '[email protected]'

Grafana 可视化

推荐 Dashboard

Dashboard ID说明
179Docker Host and Container Monitoring
11600Docker Container
893Docker and system monitoring
11467Docker Swarm monitoring

自定义面板示例

容器 CPU 使用率面板

# Query
sum(rate(container_cpu_usage_seconds_total{name=~"$container"}[5m])) by (name) * 100

# Legend
{{ name }}

容器内存使用面板

# Query
container_memory_usage_bytes{name=~"$container"}

# Legend
{{ name }}

故障排除清单

容器无法启动

# 1. 检查日志
docker logs <container>

# 2. 检查状态
docker inspect <container>

# 3. 检查镜像
docker images
docker history <image>

# 4. 尝试交互运行
docker run -it --entrypoint sh <image>

# 5. 检查资源限制
docker stats --no-stream

容器性能问题

# 1. 查看资源使用
docker stats <container>

# 2. 检查进程
docker top <container>

# 3. 检查日志
docker logs --tail 1000 <container>

# 4. 进入容器检查
docker exec -it <container> sh

# 5. 使用性能工具
docker run --rm -it --pid=container:<container> nicolaka/netshoot top

网络连接问题

# 1. 检查网络配置
docker network inspect <network>

# 2. 检查容器 IP
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>

# 3. 测试连通性
docker exec <container> ping <target>

# 4. 检查端口
docker port <container>
docker exec <container> ss -tuln

# 5. 检查 DNS
docker exec <container> nslookup <hostname>

Docker Scout 镜像扫描

Docker Scout 是 Docker 官方提供的镜像安全分析工具,可以检测镜像中的漏洞并提供修复建议。它集成在 Docker CLI 中,使用方便。

快速扫描

快速扫描提供镜像安全状态的概览:

# 扫描本地镜像
docker scout quickview myapp:latest

# 扫描远程镜像
docker scout quickview nginx:latest

# 输出示例
# Target: nginx:latest
# Base image: nginx:1.25.3
# Updated base image: nginx:1.27.0
# Vulnerabilities: 12 critical, 45 high, 100 medium

CVE 详细报告

查看镜像中的具体漏洞详情:

# 查看所有 CVE
docker scout cves nginx:latest

# 只显示严重和高危漏洞
docker scout cves --only-severe nginx:latest

# 输出为 SARIF 格式(用于 CI/CD 集成)
docker scout cves --format sarif --output results.sarif nginx:latest

修复建议

获取更新镜像的建议:

# 查看修复建议
docker scout recommendations myapp:latest

# 查看基础镜像更新
docker scout recommendations --output-format markdown myapp:latest

输出内容包括更新的基础镜像版本、修复漏洞需要的版本、依赖包更新建议。

镜像比较

比较两个镜像的安全状态:

# 比较两个版本
docker scout compare myapp:v1 myapp:v2

# 比较不同基础镜像
docker scout compare --to nginx:alpine nginx:debian

持续监控

监控镜像更新和漏洞变化:

# 实时监控模式
docker scout watch myapp:latest

Docker Debug 调试工具

Docker Debug 是一个强大的调试工具,可以在不修改镜像的情况下进入任何容器或镜像进行调试。它特别适合调试精简镜像(如 distroless 或 scratch 基础镜像),这些镜像通常没有 shell 或调试工具。

基本用法

# 调试运行中的容器
docker debug my-container

# 调试镜像(即使没有 shell)
docker debug nginx:alpine

# 调试已停止的容器
docker debug stopped-container

安装额外工具

Docker Debug 自带常用工具(vim、curl、htop 等),也可以安装额外工具:

# 进入调试模式
docker debug my-container

# 安装 nmap 工具
install nmap

# 工具会保留在工具箱中,下次调试其他容器也可用

查看 Entrypoint

使用内置的 entrypoint 命令查看容器的入口点配置:

docker debug nginx:latest
entrypoint --print
# 输出:/docker-entrypoint.sh nginx -g "daemon off;"

# 测试运行入口点
entrypoint --run

非交互模式

直接执行命令而不进入交互模式:

# 执行单条命令
docker debug -c "cat /etc/nginx/nginx.conf" nginx:latest

# 指定 shell
docker debug --shell zsh my-container

CI/CD 集成示例

GitHub Actions 安全扫描

name: Security Scan
on: [push]

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build image
run: docker build -t myapp:${{ github.sha }} .

- name: Run Docker Scout
run: |
docker scout quickview myapp:${{ github.sha }}
docker scout cves --only-severe --format sarif --output results.sarif myapp:${{ github.sha }}

- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif

小结

Docker 监控与调试的核心内容:

  • 内置监控命令docker stats 实时资源统计、docker top 进程查看、docker events 事件监听
  • cgroups 指标:从 /sys/fs/cgroup 文件系统获取详细的资源使用数据
  • 日志管理:多种日志驱动配置、日志聚合方案(ELK、Loki)
  • Prometheus 监控:cAdvisor 收集指标、Prometheus 存储、Grafana 可视化
  • 镜像扫描:Docker Scout 检测漏洞、查看 CVE、获取修复建议
  • 故障排除:容器启动失败、网络问题、存储问题、性能瓶颈排查
  • 调试工具:Docker Debug 进入容器调试、nicolaka/netshoot 网络调试
  • 告警配置:Prometheus 告警规则、Alertmanager 通知

练习

  1. 使用 docker stats 监控容器资源使用
  2. 配置日志驱动限制日志大小
  3. 部署 Prometheus + Grafana 监控栈
  4. 创建 Grafana 面板展示容器 CPU 和内存使用率
  5. 配置 Prometheus 告警规则,当容器内存使用超过 90% 时告警

参考资源