bigywater.tech
Docker · 75

docker stats:数字是从哪个 cgroup 文件读来的

docker stats 里的 CPU%、内存、网络和磁盘数字到底怎么算的?为什么 CPU 能超过 100%?为什么写了一大堆文件内存却没涨?这篇和 cgroup、内核计数器对照着验证。

198.98%
两个满负荷进程在 docker stats 里的 CPUPerc(10 个 CPU 的虚拟机里上限是 1000%)
214.0 vs 6.1 MiB
写 200 MiB 文件后,cgroup 的 memory.current 与 docker stats 的 MemUsage
22.1kB / 21kB
docker stats 的 NetIO,与 eth0 的内核累计计数一致

CPU

实测 · 本机执行输出
  一行 JSON 的字段:['BlockIO', 'CPUPerc', 'Container', 'ID', 'MemPerc', 'MemUsage', 'Name', 'NetIO', 'PIDs']
  2 个满负荷进程:CPUPerc=198.98% MemUsage=13.41MiB / 7.748GiB MemPerc=0.17% NetIO=1.17kB / 126B BlockIO=3.47MB / 971kB PIDs=3
  自己从 cgroup 的 cpu.stat 算:200% (CPU 时间增量 ÷ 墙钟时间;满 1 个 CPU = 100%)
  虚拟机 CPU 数 = 10:docker stats 的 CPUPerc 可以超过 100% (每个核 100%)

CPUPerc 以一个 CPU 核为 100%,两个忙等进程大约 200%;我用 cgroup 的 cpu.stat 的 usage_usec 增量算出 200%,与 stats 的 198.98% 吻合。

内存

实测 · 本机执行输出
  docker stats 的 MemUsage:写 200 MiB 文件前 544KiB / 512MiB,写完 6.102MiB / 512MiB
  写完之后从 cgroup 读(这次读本身用了一个 docker exec 进程,会多出几 MiB):memory.current=214.0 MiB,其中 anon=6.2 MiB、inactive_file=200.0 MiB
  对比:cgroup 的 memory.current 增加了约 200 MiB(页缓存),而 docker stats 只增加了 6.102MiB / 512MiB,所以 MemUsage 不含页缓存

MemUsage 不包含页缓存(inactive_file)。写大文件会让 cgroup 的 memory.current 涨很多,但 docker stats 看不出来。判断容器会不会因为内存被杀,要看 cgroup 的实际限制行为,而不只是这个数字(页缓存在内存紧张时可回收,我没有在这里测)。

网络与磁盘

实测 · 本机执行输出
  eth0 的 rx/tx 增量:21406 / 20924 字节;启动以来累计 rx=22096 tx=21008;docker stats NetIO = 22.1kB / 21kB
  写 50 MiB(oflag=direct)后 docker stats BlockIO = 0B / 52.4MB

NetIO 是容器 eth0 的累计收发字节,和 /sys/class/net/eth0/statistics 一致;BlockIO 是块设备读写累计,direct I/O 写 50 MiB 后写入是 52.4MB。

分步演示

docker stats
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。docker stats 用 --no-stream --format json;cgroup 值从容器里读 /sys/fs/cgroup(通过 docker exec,exec 出来的进程自己会占用几 MiB);CPU 用 2 个 Python 忙等进程;每种情形运行一次;实验后已删除容器
    • 没有验证:docker stats 内存的精确计算公式(我只确认了不含页缓存)、多容器时的 CPU 汇总、Windows 容器、docker stats 的采样间隔与平滑、cgroup v1 的差别、NetIO 在多网卡容器里的汇总方式
    京ICP备2026067502号-1京公网安备11010502063487号