适用场景:/var/lib/docker 所在分区 100%、kubelet 驱逐 Pod、容器无法启动
核心手段:df 全局定位 → du 目录排查 → docker system df -v 容器级分析 → overlay2 深挖 → 幽灵文件排查
核心诉求:快速找到是哪个容器、哪个目录占用了磁盘
一、背景与问题
Docker 容器运行时如果缺乏治理,磁盘会在不知不觉中就被占满。常见原因:
- 容器日志无限制增长:json-file 驱动没配 max-size,单容器日志轻松破百 GB。
- 容器可写层暴增:应用往容器内部写数据(比如 AI 训练中间文件、pip cache、数据集直接下载到容器层)。
- 镜像堆积:长期不清理,无用镜像占用几十 GB。
- overlay2 层缓存:已删除容器但文件句柄未释放,空间不回收。
磁盘满了之后,kubelet 会开始驱逐 Pod,Docker 无法创建新容器,节点直接 NotReady。所以定位要快、要准。
二、第一步:全局确认磁盘占用
查看所有挂载点使用情况。
df-Th重点关注/var/lib/docker所在的分区。如果Use%显示 100% 或 99%,说明就是这里的问题。
| 参数 | 含义 |
|---|---|
-T | 显示文件系统类型 |
-h | 人类可读格式(G/M/K) |
三、第二步:定位到 Docker 子目录
确认是/var/lib/docker分区占满后,逐层排查哪个子目录是占用大户:
查看 /var/lib/docker 下各子目录占用
du-h-x--max-depth=1/var/lib/docker典型输出示例:
3.1T /var/lib/docker/overlay2 50G /var/lib/docker/containers 2G /var/lib/docker/images| 子目录 | 说明 | 常见占满磁盘原因 |
|---|---|---|
overlay2/ | 容器可写层 + 镜像层 | 应用数据写入容器内部、pylance 缓存、conda |
containers/ | 容器日志(json-file) | 日志没限制大小,单文件几百 GB |
images/ | 镜像存储 | 镜像堆积未清理 |
volumes/ | 匿名/命名卷 | 卷内数据未清理 |
四、第三步:容器级精准定位
4.1 Docker system df -v(最推荐)
dockersystemdf-v这个命令会输出三类信息:
- Images 部分:每个镜像的大小和占用空间
- Containers 部分:每个容器的可写层大小(
Size列就是该容器占用的空间) - Local Volumes 部分:卷占用
重点关注Containers部分的Size列,直接告诉你哪个容器占用了多少磁盘。
4.2 按容器大小排序(补充手段)
查看所有运行容器的磁盘占用(包括可写层)。
dockerps-s输出中size是容器可写层大小,virtual size是可写层 + 共享镜像层。
4.3 进入容器定位具体文件
找到占用大户容器后,进一步定位是哪个目录:
方法 1:通过 Docker inspect 找到容器 merged 目录
dockerinspect<container-id>|grepMergedDir方法 2:直接进容器看
dockerexec-it<container-id>du-h-x--max-depth=2/2>/dev/nullsort-hrhead-10五、第四步:overlay2 层深度排查(进阶)
如果docker system df -v看不出明细,直接进 overlay2 目录逐层排查:
cd/var/lib/docker/overlay2du-h-x--max-depth=1sort-hrhead-10找到最大的那个 long ID 目录,反查属于哪个容器:
用 overlay2 的目录名前缀反查
dockerps-a--no-trunc|grep<overlay2-id-prefix>然后进 diff 目录看具体文件:
du-h-x--max-depth=2/var/lib/docker/overlay2/<id>/diffsort-hrhead-10六、第五步:排查“已删除但仍占空间”的幽灵文件
有时候du和df显示不一致——du看总量没那么大,但df说分区满了。这是有进程持有了已删除文件的句柄,空间不会真正释放:
查找被删除但仍被占用的文件
lsof|grepdeleted找到对应 PID 后 kill 或重启对应容器释放空间
七、应急清理方案(定位完之后)
| 场景 | 清理命令 | 风险 |
|---|---|---|
| 容器日志太大 | truncate -s 0 /var/lib/docker/containers/*/*-json.log | 无,日志清零 |
| 已停止的容器 | docker container prune | 低,容器已停 |
| 无用镜像 | docker image prune -a | 中,下次需重新拉取 |
| 全部清理(慎用) | docker system prune -a --volumes | 高,会删卷和所有未用镜像 |
八、避坑清单
| 现象 | 排查点 |
|---|---|
| df 100% 但 du 总量对不上 | lsof | grep deleted查幽灵文件 |
| Docker system df 卡住 | Docker daemon 异常,重启 Docker 或等 API 响应 |
| overlay2 单个目录 3T+ | 查.vscode-server/Pylance、Conda、数据集 |
| 容器日志几百 GB | json-file 没配 max-size,需改 daemon.json |
| 清理完空间没释放 | 有进程持文件句柄,kill 对应进程 |
| kubelet 驱逐 Pod | 磁盘压力触发 eviction,优先清理容器日志 |
九、小结
定位 Docker 占满磁盘的黄金路径:
- df -Th:确认哪个分区满了
- du -h -x --max-depth=1 /var/lib/docker:定位到子目录
- docker system df -v:直接看到哪个容器吃了多少
- docker exec du:进容器定位具体文件
- lsof | grep deleted:排查幽灵文件
有问题的在评论区贴报错,我看到会回。