在容器化部署成为主流的今天,单个宿主机上往往运行着几十甚至上百个容器。一旦某个业务模块出现内存泄漏或死循环,就会迅速拖垮整台机器。Docker 引擎提供了原生的统计接口,通过 docker stats 命令即可实时拉取每个容器的资源消耗情况,不需要借助 Prometheus 或第三方 Agent 就能完成基础巡检。

docker stats 的基础用法与输出字段解析
最直接的使用方式是在终端输入 docker stats,此时命令会持续刷新,列出当前所有处于运行状态的容器。默认展示的字段包括容器 ID、名称、CPU 占用百分比、内存用量与限制、内存百分比、网络接收与发送速率、以及块设备读写。这些数据每秒更新一次,方便用户动态观察趋势。
很多人第一次看输出时会困惑为什么 CPU 百分比能超过 100%。这是因为 Docker 默认按单核基准计算,如果宿主机是四核,某个容器跑满了两个核心,就会显示约为 200%。内存那一列则同时给出了绝对用量和上限值,当限制列显示为 0 或具体数值时,可以直观判断容器是否设置了硬性约束。网络与磁盘 IO 以人类可读单位呈现,例如 MB 或 GB,便于快速评估流量异常。
如果只想看某几个容器,可以在命令后追加容器名或 ID,例如 docker stats web_app redis_db。这样输出就只会包含指定对象,避免信息过载。配合 --no-stream 参数还能只打印一次当前快照,适合写进脚本做定时采集。下面是一段典型的单次采样代码:
# 获取一次 web 容器资源快照 docker stats --no-stream web_app # 输出示例 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O a1b2c3d4e5f6 web_app 12.34% 180MiB / 512MiB 35.15% 1.2MB / 800kB 0B / 0B
底层原理与 cgroups 数据来源
docker stats 并不是凭空估算数字,而是读取 Linux 的 cgroups(控制组)虚拟文件系统。每个容器在创建时,Docker 都会为其建立独立的 cgroup 目录,例如 /sys/fs/cgroup/cpu/docker/<容器ID>/ 与 /sys/fs/cgroup/memory/docker/<容器ID>/。命令通过 Docker daemon 调用 libcontainer 或 runc 接口,周期性地打开这些文件并解析其中的累计计数器。
以 CPU 为例,内核记录的是容器在所有 CPU 上的累计占用纳秒数。Docker 在计算百分比时,取相邻两次采样的差值除以采样间隔,再除以逻辑 CPU 总数,从而得到相对占用率。内存部分则直接读取 memory.usage_in_bytes 与 memory.limit_in_bytes,两者相除即内存使用率。网络数据来源于 /sys/class/net/<veth>/statistics/ 中的收发字节数,块设备则来自 cgroups 的 blkio 控制器。
了解原理后就能明白,为什么在容器停止后 docker stats 看不到它,以及为什么某些老版本内核下网络速率可能为零。如果宿主机使用了非 systemd 的 cgroup 驱动,路径会稍有差异,但 daemon 已经封装了这些细节。下面的 Go 风格伪代码展示了 daemon 侧的大致逻辑:
// 伪代码:读取某容器 CPU 使用纳秒
func readCpuUsage(cgroupPath string) (uint64, error) {
data, err := ioutil.ReadFile(cgroupPath + "/cpuacct.usage")
if err != nil {
return 0, err
}
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
}
// 两次采样求差得到使用量
delta := currentUsage - lastUsage
percent := float64(delta) / float64(intervalNs) / float64(cpuNum) * 100
实战中的过滤技巧与自动化监控方案
在生产环境中,我们通常不会一直盯着终端,而是把 docker stats 接入定时任务或监控管道。例如通过 --format 参数自定义输出模板,只提取关心的列,再使用 awk 或 jq 做阈值判断。自定义格式依赖 Go 的模板语法,可以引用 .Name、.CPUPerc 等字段,避免冗余信息干扰。
假设需要每五秒记录一次内存超过 80% 的容器,可以写一个简单的 shell 循环,将 --no-stream 的结果重定向到日志,并由外部程序告警。对于多节点集群,单机 docker stats 显然不够,此时可将其作为边车脚本,把数据推送到中央收集器。但它依然是排查单机异常时最快捷的手段,比登录网页控制台更实时。
另一个常见需求是排除系统容器只盯业务容器。可以结合 docker ps --filter 先拿到列表,再传给 docker stats。下面示例展示如何用格式化输出生成 CSV,方便 Excel 打开分析:
# 生成 CSV 格式统计并追加到文件
docker stats --no-stream
--format "{{.Name}},{{.CPUPerc}},{{.MemPerc}},{{.NetIO}}"
>> stats_$(date +%F).csv
# 配合过滤只统计带 app 标签的容器
docker stats --no-stream
$(docker ps -q --filter label=type=app)
--format "table {{.Name}}t{{.MemUsage}}"
通过上述方式,团队可以在不引入重量级监控栈的前提下,建立起基础的资源可视能力。当业务规模扩大后,再平滑迁移到更完整的观测系统,而日常排障时 docker stats 始终是工程师手边那把最快的扳手。
docker_stats容器监控资源占用修改时间:2026-08-15 09:15:46