docker stats --no-stream 无法直接按内存排序,需结合 --format 提取数值并用 awk、sort 处理;MemPerc 易误导,应优先查 memory.usage_in_bytes 和 cgroup v2 的 memory.max。

docker stats --no-stream 能直接排序出内存占用最高的容器
不用写脚本、不依赖第三方工具,docker stats 加上 --no-stream 和自定义格式就能一次性拉取全量快照并按内存排序。关键不是“看”,而是“比”——默认输出的 MEM USAGE / LIMIT 是字符串(如 1.2GiB / 4GiB),没法直接用 sort -h,得先提取数值。
实操建议:
- 用
--format提取纯数字 MB 值:docker stats --no-stream --format "{{.Name}}\t{{.MemUsage}}" | awk '{gsub(/[^0-9.]/, "", $2); if (index($2, "Gi") > 0) print $1 "\t" $2*1024; else print $1 "\t" $2}' | sort -k2 -nr | head -5 - 更稳的做法是改用
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}",人工扫MemPerc列——它已归一化,跳过单位换算,适合快速定位异常值 - 注意:
MemPerc是相对于容器内存 limit 的百分比;如果没设 limit,它就按宿主机总内存算,数值会极小,此时必须看MemUsage绝对值
WSL2 下 vmmemWSL 进程吃内存 ≠ 某个容器真占那么多
Windows 上 Docker Desktop 用 WSL2 后端时,任务管理器里看到 vmmemWSL 占 12GB,但 docker stats 总和才 2GB,这是正常现象。WSL2 内存是动态分配+懒回收的,容器退出后内存不会立刻还给 Windows。
验证方法:
- 在 WSL2 终端里执行
free -h,看available是否充足——如果充足,说明只是内核没主动释放,不是泄漏 - 运行
wsl --shutdown再重启 Docker Desktop,vmmemWSL会重置,这是最干净的“软重启” - 若想长期控制,进 Docker Desktop 设置 → Resources → WSL Integration → 把内存上限调到比如
4096MB,避免无节制膨胀
查不到高内存容器?可能它根本没在 docker stats 里显示
docker stats 只显示正在运行的容器。如果你怀疑某个已退出或崩溃的容器残留了 cgroup 或内存页,就得绕过 Docker CLI 直查底层。
常见漏网情况:
- 容器进程僵死但状态仍是
running:用docker ps -q | xargs -I {} sh -c 'echo {}; cat /proc/$(docker top {} -eo pid | tail -n +2 | head -1)/status 2>/dev/null | grep -i vmrss'查实际 RSS - 镜像构建中途失败留下的 buildkit 构建器容器:它们不显示在
docker ps,但可能卡在 cgroup 里,运行docker builder prune清理 - 日志文件撑爆内存缓存:Docker 默认用
json-file驱动,大量写日志会让 page cache 疯涨,cat /sys/fs/cgroup/memory/docker/*/memory.usage_in_bytes 2>/dev/null | sort -n | tail -3可定位真实 cgroup 使用者
docker inspect --format='{{.HostConfig.Memory}}' 返回 0 不代表没限制
这个字段只反映启动时显式指定的 --memory 值。如果容器没设 limit,它就是 0;但如果宿主机启用了 Memory Cgroup v2,且全局配置了 systemd.unified_cgroup_hierarchy=1,那容器仍受隐式约束——此时得看 /sys/fs/cgroup/memory/docker/<id>/memory.max</id>。
判断依据:
- 运行
cat /proc/1/cgroup | head -1,如果输出含unified,说明是 cgroup v2,Memory字段不可信 - 查具体容器:进入
/sys/fs/cgroup/memory/docker/<container_id_short>/</container_id_short>,读memory.max(单位 bytes),值为max表示无限制,否则就是硬上限 - 真正影响 OOM 的是
memory.high(v2)或memory.soft_limit_in_bytes(v1),不是Memory字段
docker stats 是第一眼,cgroup 文件是最后一道验证。尤其在 WSL2 或 cgroup v2 环境下,表面数字和底层行为常有断层——别信 MemPerc,多看 memory.usage_in_bytes。


















