强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

系统监控工具指南 / 第11章:Docker容器监控

第11章:Docker容器监控

11.1 概述

为什么需要容器监控

  1. 资源隔离 - 容器资源独立,需要单独监控
  2. 动态性 - 容器频繁创建销毁,传统工具难以覆盖
  3. 密度 - 单机运行多个容器,资源竞争
  4. 微服务 - 服务分散在多个容器中

容器监控的挑战

挑战说明
动态性容器生命周期短,IP变化
密度单机数百容器,监控开销大
隔离性容器内外视角不同
编排Kubernetes等编排系统的复杂性

容器监控工具

工具类型特点
docker statsDocker内置基础、实时
cAdvisorGoogle开源容器专用、Web界面
Prometheus + Grafana监控栈企业级、可视化
DatadogSaaS服务全托管、功能丰富
Sysdig安全+监控深度洞察

11.2 Docker内置监控

11.2.1 docker stats

基本用法

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

# 查看指定容器
docker stats container_name

# 查看多个容器
docker stats container1 container2

# 单次输出(不持续刷新)
docker stats --no-stream

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

输出解读

CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
a1b2c3d4e5f6   nginx     0.50%     65.43MiB / 16GiB      0.40%     1.23MB / 456KB    12.3MB / 0B       7
f6e5d4c3b2a1   mysql     3.20%     234.5MiB / 16GiB      1.43%     45.6MB / 12.3MB   56.7MB / 8.9MB    45

字段说明

字段含义
CPU %CPU使用率
MEM USAGE / LIMIT内存使用 / 内存限制
MEM %内存使用率
NET I/O网络输入/输出
BLOCK I/O块设备输入/输出
PIDS进程数

11.2.2 docker stats格式化

自定义输出格式

# 简化输出
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# JSON格式
docker stats --format '{"name":"{{.Name}}","cpu":"{{.CPUPerc}}","mem":"{{.MemUsage}}"}'

# 只显示特定容器
docker stats --format "{{.Name}}: {{.CPUPerc}}" container1 container2

可用变量

变量说明
.Container容器ID
.Name容器名称
.ID容器ID
.CPUPercCPU使用率
.MemUsage内存使用
.MemPerc内存使用率
.NetIO网络IO
.BlockIO块IO
.PIDs进程数

11.2.3 docker top

# 查看容器进程
docker top container_name

# 自定义ps选项
docker top container_name -o pid,user,%cpu,%mem,command

# 查看所有线程
docker top container_name -eLf

11.2.4 docker inspect

# 查看容器详细信息
docker inspect container_name

# 获取特定信息
docker inspect --format='{{.State.Pid}}' container_name
docker inspect --format='{{.HostConfig.Memory}}' container_name
docker inspect --format='{{.HostConfig.CpuShares}}' container_name

# 查看资源限制
docker inspect --format='{{json .HostConfig}}' container_name | jq

11.2.5 docker system df

# 查看Docker磁盘使用
docker system df

# 输出示例
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          10        5         2.5GB     1.2GB (48%)
Containers      8         3         500MB     300MB (60%)
Local Volumes   15        10        1GB       500MB (50%)
Build Cache     0         0         0B        0B

# 详细信息
docker system df -v

11.2.6 docker events

# 实时监控Docker事件
docker events

# 过滤事件
docker events --filter type=container
docker events --filter event=start
docker events --filter container=nginx

# JSON格式
docker events --format '{{json .}}'

# 监控指定时间段
docker events --since 2026-05-10T14:00:00
docker events --until 2026-05-10T16:00:00

11.3 cAdvisor详解

11.3.1 什么是cAdvisor

cAdvisor(Container Advisor)是Google开源的容器监控工具,提供:

  • 容器资源使用统计
  • 性能数据分析
  • Web界面展示
  • API接口

11.3.2 安装部署

Docker方式部署

# 基本部署
docker run \
  --name=cadvisor \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \
  --privileged \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor:latest

# 指定版本
docker run \
  --name=cadvisor \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  gcr.io/cadvisor/cadvisor:v0.47.0

docker-compose方式

# docker-compose.yml
version: '3.8'

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    restart: unless-stopped
    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
    privileged: true
    devices:
      - /dev/kmsg:/dev/kmsg
# 启动
docker-compose up -d

# 查看状态
docker-compose ps

11.3.3 Web界面

访问cAdvisor

# 本地访问
http://localhost:8080

# 远程访问
http://server_ip:8080

界面功能

页面功能
/主页,系统概览
/docker/Docker容器列表
/containers/所有容器
/system/系统信息

容器详情页面

  • CPU使用率图表
  • 内存使用图表
  • 网络IO图表
  • 磁盘IO图表
  • 进程列表

11.3.4 API接口

获取容器信息

# 获取所有容器
curl http://localhost:8080/api/v1.0/containers

# 获取指定容器
curl http://localhost:8080/api/v1.0/containers/<container_name>

# 获取Docker容器
curl http://localhost:8080/api/v1.0/docker/<container_id>

API响应示例

{
  "name": "/docker/nginx",
  "aliases": ["nginx", "a1b2c3d4e5f6"],
  "namespace": "docker",
  "spec": {
    "container_name": "nginx",
    "image": "nginx:latest"
  },
  "stats": [
    {
      "timestamp": "2026-05-10T14:32:15Z",
      "cpu": {
        "usage": {
          "total": 123456789,
          "per_cpu_usage": [12345678, 23456789, ...]
        }
      },
      "memory": {
        "usage": 67108864,
        "cache": 12345678,
        "rss": 54321098
      },
      "network": {
        "interfaces": [
          {
            "name": "eth0",
            "rx_bytes": 1234567,
            "tx_bytes": 2345678
          }
        ]
      }
    }
  ]
}

API查询参数

# 指定时间范围
curl "http://localhost:8080/api/v1.0/containers/nginx?start=2026-05-10T14:00:00Z&end=2026-05-10T15:00:00Z"

# 指定采样数
curl "http://localhost:8080/api/v1.0/containers/nginx?num_stats=60"

11.3.5 监控脚本

Python示例

import requests
import json

class CadvisorClient:
    def __init__(self, host='localhost', port=8080):
        self.base_url = f"http://{host}:{port}/api/v1.0"
    
    def get_containers(self):
        """获取所有容器"""
        resp = requests.get(f"{self.base_url}/containers")
        return resp.json()
    
    def get_container_stats(self, container_name):
        """获取容器统计"""
        resp = requests.get(f"{self.base_url}/containers/{container_name}")
        data = resp.json()
        
        if data.get('stats'):
            latest = data['stats'][-1]
            return {
                'cpu_usage': latest['cpu']['usage']['total'],
                'memory_usage': latest['memory']['usage'],
                'network_rx': latest['network']['interfaces'][0]['rx_bytes'],
                'network_tx': latest['network']['interfaces'][0]['tx_bytes']
            }
        return None

# 使用示例
client = CadvisorClient()
containers = client.get_containers()
for name in containers:
    stats = client.get_container_stats(name)
    if stats:
        print(f"{name}: CPU={stats['cpu_usage']}, MEM={stats['memory_usage']}")

Shell脚本示例

#!/bin/bash
# cadvisor_monitor.sh

CADVISOR_URL="http://localhost:8080"

# 获取容器列表
get_containers() {
    curl -s $CADVISOR_URL/api/v1.0/containers | jq -r 'keys[]'
}

# 获取容器CPU使用率
get_cpu_usage() {
    local container=$1
    curl -s $CADVISOR_URL/api/v1.0/containers/$container | \
        jq '.stats[-1].cpu.usage.total'
}

# 获取容器内存使用
get_memory_usage() {
    local container=$1
    curl -s $CADVISOR_URL/api/v1.0/containers/$container | \
        jq '.stats[-1].memory.usage'
}

# 监控所有容器
for container in $(get_containers); do
    cpu=$(get_cpu_usage $container)
    mem=$(get_memory_usage $container)
    echo "$container: CPU=$cpu, MEM=$mem"
done

11.4 Prometheus + Grafana

11.4.1 架构概述

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Docker     │───>│  cAdvisor   │───>│  Prometheus │
│  Containers │    │  (Metrics)  │    │  (Storage)  │
└─────────────┘    └─────────────┘    └─────────────┘
                                              │
                                              ▼
                                       ┌─────────────┐
                                       │   Grafana   │
                                       │ (Dashboard) │
                                       └─────────────┘

11.4.2 Docker Compose部署

# docker-compose-monitoring.yml
version: '3.8'

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    privileged: true
    devices:
      - /dev/kmsg:/dev/kmsg

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

volumes:
  prometheus_data:
  grafana_data:

Prometheus配置

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

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

启动服务

# 启动所有服务
docker-compose -f docker-compose-monitoring.yml up -d

# 查看状态
docker-compose -f docker-compose-monitoring.yml ps

# 查看日志
docker-compose -f docker-compose-monitoring.yml logs -f

11.4.3 Grafana配置

添加数据源

  1. 访问 http://localhost:3000
  2. 登录(admin/admin)
  3. Configuration → Data Sources → Add data source
  4. 选择Prometheus
  5. URL: http://prometheus:9090
  6. Save & Test

导入Dashboard

  1. Dashboards → Import
  2. 输入Dashboard ID(如 11600 - Docker and system monitoring)
  3. Load
  4. 选择Prometheus数据源
  5. Import

推荐Dashboard

Dashboard ID名称说明
11600Docker and system monitoringDocker和系统监控
893Docker containersDocker容器监控
10619Docker container & host metrics容器和主机指标
14282cAdvisor ExportercAdvisor监控

11.4.4 常用PromQL查询

CPU使用率

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

# 按容器分组
sum(rate(container_cpu_usage_seconds_total{image!=""}[5m])) by (name) * 100

内存使用

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

# 内存使用率
container_memory_usage_bytes{image!=""} / container_spec_memory_limit_bytes{image!=""} * 100

网络流量

# 接收速率
rate(container_network_receive_bytes_total{image!=""}[5m])

# 发送速率
rate(container_network_transmit_bytes_total{image!=""}[5m])

磁盘IO

# 读取速率
rate(container_fs_reads_bytes_total{image!=""}[5m])

# 写入速率
rate(container_fs_writes_bytes_total{image!=""}[5m])

11.5 容器资源管理

11.5.1 资源限制

CPU限制

# 限制CPU使用率为50%
docker run --cpus=0.5 nginx

# 限制CPU份额(相对权重)
docker run --cpu-shares=512 nginx

# 绑定到特定CPU核心
docker run --cpuset-cpus="0,1" nginx

内存限制

# 限制内存为512MB
docker run --memory=512m nginx

# 限制内存和Swap
docker run --memory=512m --memory-swap=1g nginx

# 内存软限制
docker run --memory=512m --memory-reservation=256m nginx

IO限制

# 限制块IO
docker run --device-read-bps=/dev/sda:1mb nginx
docker run --device-write-bps=/dev/sda:1mb nginx

# 限制IOPS
docker run --device-read-iops=/dev/sda:1000 nginx
docker run --device-write-iops=/dev/sda:1000 nginx

11.5.2 资源监控

查看资源限制

# 查看容器资源限制
docker inspect --format='{{.HostConfig.Memory}}' container_name
docker inspect --format='{{.HostConfig.CpuShares}}' container_name

# 查看资源使用
docker stats container_name

动态调整资源

# 动态调整CPU份额
docker update --cpu-shares=1024 container_name

# 动态调整内存限制
docker update --memory=1g container_name

# 批量更新
docker update --cpu-shares=512 container1 container2

11.5.3 资源告警

Prometheus告警规则

# alerts.yml
groups:
  - name: container_alerts
    rules:
      - alert: ContainerHighCPU
        expr: rate(container_cpu_usage_seconds_total{image!=""}[5m]) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "容器CPU使用率过高"
          description: "容器 {{ $labels.name }} CPU使用率超过80%"

      - alert: ContainerHighMemory
        expr: container_memory_usage_bytes{image!=""} / container_spec_memory_limit_bytes{image!=""} * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "容器内存使用率过高"
          description: "容器 {{ $labels.name }} 内存使用率超过80%"

      - alert: ContainerRestarting
        expr: increase(container_restart_count[1h]) > 3
        labels:
          severity: critical
        annotations:
          summary: "容器频繁重启"
          description: "容器 {{ $labels.name }} 在过去1小时内重启超过3次"

11.6 Kubernetes监控

11.6.1 Metrics Server

安装Metrics Server

# 安装
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 验证
kubectl get pods -n kube-system | grep metrics-server

使用kubectl top

# 查看节点资源使用
kubectl top nodes

# 查看Pod资源使用
kubectl top pods

# 查看指定命名空间
kubectl top pods -n kube-system

# 查看Pod中容器资源使用
kubectl top pods --containers

11.6.2 Prometheus Operator

安装

# 使用Helm安装
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace

组件

组件功能
Prometheus Operator管理Prometheus实例
Prometheus时序数据库
Alertmanager告警管理
Grafana可视化
kube-state-metricsKubernetes指标

11.6.3 常用监控指标

Pod指标

# Pod CPU使用率
sum(rate(container_cpu_usage_seconds_total{namespace="default"}[5m])) by (pod) * 100

# Pod内存使用
sum(container_memory_usage_bytes{namespace="default"}) by (pod)

# Pod重启次数
sum(kube_pod_container_status_restarts_total{namespace="default"}) by (pod)

节点指标

# 节点CPU使用率
(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100

# 节点内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 节点磁盘使用率
(1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100

11.7 日志监控

11.7.1 Docker日志

查看容器日志

# 查看日志
docker logs container_name

# 实时跟踪
docker logs -f container_name

# 最近100行
docker logs --tail 100 container_name

# 指定时间范围
docker logs --since 2026-05-10T14:00:00 container_name
docker logs --until 2026-05-10T15:00:00 container_name

# 带时间戳
docker logs -t container_name

日志驱动配置

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

11.7.2 ELK Stack

Docker Compose部署

# docker-compose-elk.yml
version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.7.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:8.7.0
    container_name: logstash
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.7.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  elasticsearch_data:

11.8 实战场景

场景1:容器资源监控

需求:监控所有容器的资源使用

# 实时监控
docker stats

# 导出到文件
docker stats --no-stream > /tmp/docker_stats_$(date +%Y%m%d_%H%M%S).txt

# 使用cAdvisor
docker run -d --name cadvisor \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  gcr.io/cadvisor/cadvisor:latest

场景2:容器性能问题排查

问题:容器响应缓慢

# 1. 检查容器资源使用
docker stats container_name

# 2. 检查容器进程
docker top container_name

# 3. 检查容器日志
docker logs --tail 100 container_name

# 4. 进入容器排查
docker exec -it container_name bash

# 5. 检查资源限制
docker inspect --format='{{json .HostConfig}}' container_name | jq

场景3:容器密度优化

需求:优化单机容器密度

# 1. 查看当前资源使用
docker stats --no-stream

# 2. 分析资源分配
docker inspect --format='{{.Name}}: CPU={{.HostConfig.CpuShares}}, MEM={{.HostConfig.Memory}}' $(docker ps -q)

# 3. 调整资源限制
docker update --cpu-shares=256 --memory=256m container_name

# 4. 监控调整效果
docker stats

场景4:容器网络监控

需求:监控容器网络流量

# 1. 使用docker stats
docker stats --format "table {{.Name}}\t{{.NetIO}}"

# 2. 使用cAdvisor
curl http://localhost:8080/api/v1.0/containers/nginx | jq '.stats[-1].network'

# 3. 使用iftop(需要进入容器)
docker exec -it container_name iftop

场景5:容器存储监控

需求:监控容器存储使用

# 1. 查看容器文件系统
docker exec -it container_name df -h

# 2. 查看容器层大小
docker system df

# 3. 查看卷使用
docker volume ls
docker system df -v

# 4. 清理未使用资源
docker system prune

11.9 最佳实践

11.9.1 监控策略

层次监控内容工具
容器层CPU、内存、网络、IOdocker stats, cAdvisor
应用层响应时间、错误率Prometheus + 应用指标
编排层Pod状态、节点健康Kubernetes Metrics
日志层应用日志、错误日志ELK Stack

11.9.2 告警设置

关键告警

指标阈值级别
CPU使用率>80%Warning
内存使用率>85%Warning
容器重启>3次/小时Critical
磁盘使用率>90%Critical
网络错误>0Warning

11.9.3 容量规划

监控数据收集

# 每天收集资源使用
docker stats --no-stream > /tmp/stats_$(date +%Y%m%d).txt

# 分析趋势
# CPU平均使用率
# 内存峰值使用率
# 网络流量趋势

11.10 故障排查

问题1:cAdvisor无法启动

# 检查日志
docker logs cadvisor

# 检查挂载
ls -la /var/run/docker.sock

# 权限问题
docker run --privileged ...

问题2:Prometheus无法抓取数据

# 检查cAdvisor是否运行
docker ps | grep cadvisor

# 检查Prometheus配置
cat prometheus.yml

# 手动测试
curl http://cadvisor:8080/metrics

问题3:容器资源监控不准

# 检查cgroup版本
cat /proc/self/cgroup

# 检查Docker版本
docker version

# 更新cAdvisor
docker pull gcr.io/cadvisor/cadvisor:latest

11.11 扩展阅读

11.12 快速参考

Docker监控命令

# 基本监控
docker stats                    # 所有容器
docker stats container_name     # 指定容器
docker stats --no-stream        # 单次输出

# 进程监控
docker top container_name       # 容器进程

# 事件监控
docker events                   # 实时事件

# 资源使用
docker system df                # 磁盘使用

cAdvisor命令

# 启动cAdvisor
docker run -d --name cadvisor \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  gcr.io/cadvisor/cadvisor:latest

# API调用
curl http://localhost:8080/api/v1.0/containers
curl http://localhost:8080/api/v1.0/containers/nginx

资源限制命令

# CPU限制
docker run --cpus=0.5 nginx
docker run --cpu-shares=512 nginx

# 内存限制
docker run --memory=512m nginx
docker run --memory=512m --memory-swap=1g nginx

# 动态调整
docker update --cpu-shares=1024 container_name
docker update --memory=1g container_name

11.13 本章小结

本章详细介绍了Docker容器监控:

  1. Docker内置监控

    • docker stats:实时资源监控
    • docker top:进程监控
    • docker inspect:详细信息
    • docker events:事件监控
  2. cAdvisor

    • 容器专用监控工具
    • Web界面和API
    • 与Prometheus集成
  3. Prometheus + Grafana

    • 企业级监控方案
    • 丰富的Dashboard
    • 告警功能
  4. Kubernetes监控

    • Metrics Server
    • Prometheus Operator
    • kubectl top
  5. 最佳实践

    • 分层监控策略
    • 合理设置告警
    • 容量规划

容器监控需要结合多种工具,从不同层次全面掌握容器运行状态。


上一章: 第10章:dstat与nmon 下一章: 第12章:监控最佳实践