docker stats 显示容器累计 BLOCK I/O(如1.23GB / 456MB),但不直接提供实时带宽;需通过--no-stream定时采样差值计算MB/s,或用dstat查看设备级IO速率、IOPS及延迟,并结合blkio限速验证压测真实性。

直接用 docker stats 可以看到容器的实时 IO 吞吐量(读/写字节数),但它默认不显示带宽速率(如 MB/s),也不支持自动聚合或压测时段统计。要在持续压测下有效观察 IO 读写带宽表现,需结合参数优化、输出解析和辅助工具。
docker stats 能显示哪些 IO 相关字段
运行 docker stats 时,终端会持续刷新以下 IO 相关列:
-
BLOCK I/O:格式为
X.XYGB / Z.ZZGB,表示该容器自启动以来累计读取和写入的总块设备数据量(即/sys/fs/cgroup/blkio/.../blkio.io_service_bytes_recursive的汇总) - 注意:它不直接显示每秒读写速率(B/s),但可通过两次采样差值手动计算带宽
获取稳定、可分析的 IO 带宽数据
推荐使用 --no-stream + 定时轮询方式,避免滚动干扰,便于压测中记录趋势:
# 每2秒采集一次,输出时间戳 + BLOCK I/O + 内存/CPU,保存到日志
while true; do
echo "$(date '+%H:%M:%S') $(docker stats --no-stream --format '{{.Name}}\t{{.BlockIO}}\t{{.CPUPerc}}\t{{.MemUsage}}' my-app)" >> io-benchmark.log
sleep 2
done✅ 关键点:
--no-stream禁用实时刷新,每次调用只输出当前快照;配合--format可精准提取字段,避免解析混乱。
从 BLOCK I/O 提取瞬时读写带宽(MB/s)
假设某次输出为:
my-app 1.23GB / 456MB 12.3% 345MiB / 1GiB
- 把
1.23GB换算为字节:1.23 × 1024³ ≈ 1,320,875,000 B - 若上一采样(2秒前)读取总量为
1.21GB ≈ 1,299,525,000 B - 则瞬时读带宽 ≈
(1,320,875,000 − 1,299,525,000) ÷ 2 ÷ 1024² ≈ 20.8 MB/s
可用脚本自动完成该计算(例如用 awk 处理日志文件),无需人工换算。
更直观:用 dstat 实时看容器级 IO 带宽
docker stats 缺少细分设备(如 /dev/sda vs /dev/nvme0n1)和 IOPS 支持。压测中若需区分读/写速率、IOPS、等待延迟,建议在宿主机上用 dstat:
# 安装后运行(显示磁盘读写速率、IOPS、等待时间) sudo dstat -d --disk-util --disk-lat -D sda,nvme0n1 --top-io 3
? 提示:
-D指定具体设备;--top-io显示 IO 最高的进程 —— 若容器内进程 PID 在宿主机可见(如通过docker inspect -f '{{.State.Pid}}' my-app),就能确认是否为该容器主导 IO。
配合 blkio 限速验证压测真实性
防止压测工具本身被系统 IO 调度压制,可在启动容器时加 blkio 限制,再对比 docker stats 数据是否贴近设定值:
docker run -d \ --name io-stress \ --device-read-bps /dev/sda:50mb \ --device-write-bps /dev/sda:20mb \ ubuntu:22.04 sh -c "dd if=/dev/zero of=/tmp/test bs=1M count=2000 oflag=direct"
运行后 docker stats io-stress 的 BLOCK I/O 增长速率应稳定在约 50 MB/s(读)和 20 MB/s(写)附近 —— 这说明压测负载真实触达了磁盘,且 stats 数据可信。
不复杂但容易忽略


















