Docker 的容器为什么越来越占磁盘?先看清这 3 个坑

编程狮(w3cschool.cn) 2026-11-03 07:03:47 浏览数 (24)
反馈

你只是跑了几天的容器和镜像,磁盘就被吃掉了几十 G。Docker 的容器为什么越来越占磁盘?因为 Docker 不会主动回收:停止的容器、悬空镜像、构建缓存、未清理的 volume 都一直占着空间。更隐蔽的是,这些资源彼此独立、各有各的清理命令,少清理一类磁盘就照涨不误。用错清理方式反而更麻烦——比如误删正在用的镜像导致部署失败。本文先看清 3 个坑,再给安全的清理顺序,并附上命令、验证与失败排查步骤,帮你把磁盘空间长期稳住。

Docker 容器越来越占磁盘的三种原因

先看结论

  • Docker 容器占磁盘,主要来自停止未删的容器、悬空镜像、构建缓存和未清理的 volume 四类可收回资源。
  • 坑一:以为停止容器就释放空间,其实容器目录和读写层还在,必须显式删除。
  • 坑二:盲目 rm -rf /var/lib/docker,会连正在运行的容器一起端掉,部署直接崩。
  • 坑三:只删镜像不删 volume,匿名卷越积越多,磁盘照涨不误。
  • 日常用 docker system df 就能看清每一类占了多少,把它当成磁盘体检的第一站。

一、先看清空间到底被谁吃了

根据 Docker 官方文档,停止容器不会自动清理可写层。想定位占用,先用量化命令看明细:

sudo du -sh /var/lib/docker
docker system df

docker system df 会分门别类列出镜像、容器、卷、构建缓存各自占了多少。理解 Docker 容器占磁盘不是错觉,而是这些项在默默累加,是排查的第一步。镜像占用通常比你想的大,因为分层存储(overlayfs)下每一层镜像都会落盘,重复的基础层也会被多次计数。完整命令与原理可看 Docker 教程。

du 查看 /var/lib/docker 各目录占用

很多新手看到磁盘红了才慌,其实只要每周跑一次 docker system df 做体检,就能在爆炸前发现是哪一类在涨。这一步比任何清理命令都重要,因为它告诉你"该清什么",而不是盲清。把体检做成定时任务(比如每周一早上自动跑一遍并把输出发到群里),比等磁盘爆了再救火省力得多。另外注意,/var/lib/docker 的归属和权限不要随意改动,否则 daemon 可能起不来,反而让清理命令本身没法执行。真正理解占用来源,还是要回到 overlay 分层存储本身。

二、坑一:停止的容器不自动消失

docker stop 只是让容器退出,它的可写层和元数据仍保留在磁盘上。跑批处理、测试时一天能攒几十个停止容器:

docker ps -a          # 看所有容器,含已停止
docker container prune # 删掉所有已停止的容器

只删停止容器最安全,因为它不碰正在运行的实例,也不会动镜像。运行这条命令后,预期会看到释放出的空间在 docker system df 里回落。很多人以为容器"停了就没了",其实是把可写层留在原地,这正是磁盘被悄悄吃掉的源头。养成"跑完就 prune"的习惯,比事后大扫除有效得多。如果不确定哪些能删,先用 docker ps -a --filter "status=exited" 过滤,确认没有重要调试现场再动手。顺带一提,容器删了之后它占用的可写层并不会立刻被文件系统回收,通常要等 daemon 的下一次垃圾回收,所以 docker system df 的数字可能略有滞后,多跑一次确认更稳妥。把"删除"和"回收"当成两步,就不会被延迟释放的数字误导。

三、坑二和坑三:镜像、缓存与卷

悬空镜像(没被任何容器引用、也没有 tag 的 <none> 镜像)和构建缓存都占空间,可用 docker image prune 清。但 volume 是另一个坑:即使镜像、容器都删了,匿名卷还留在盘上:

docker volume prune   # 删未被容器引用的卷(确认无重要数据)

docker system prune 的清理输出

除了这些,构建镜像时留下的中间层也会堆积。每次 docker build 若没有缓存命中,就会产生新的临时层;反复改 Dockerfile 会留下一堆悬空层。清楚这一点,才能理解为什么"我只构建过几次"也会吃掉几十 G。配合多阶段构建(multi-stage build)和合理的 .dockerignore,能从源头压住镜像体积,这才是治本,比事后清理更省心。底层存储多依赖 Linux 教程 的文件系统知识,理解 overlay 挂载有助于判断空间到底落在哪一层,也方便你直接用 df -h 和 du 交叉验证,而不是只信 docker 自己的统计。

四、安全的清理顺序与验证

别一上来就强删。推荐顺序:先 docker container prune 清停止容器,再 docker image prune 清悬空镜像,最后确认无重要数据后 docker volume prune。要一次性且更彻底,用 docker system prune -a --volumes,但它会删掉所有未使用的镜像和卷,生产环境务必先核对。

操作前先确认运行中的容器清单,避免误删。检查清理结果时,再次运行 docker system df 验证空间是否回落;若清理失败或空间没降,先排查是不是有容器仍引用着那些镜像,再修复配置。不同运行方式(如 Docker Desktop 与裸机 daemon)在存储路径上略有差异,docker 的日常运维技巧可对照 use_docker 工具 了解。做好容器磁盘清理的节奏,比事后救火更稳。

总结

Docker 容器占磁盘本质是可回收资源没回收:停止容器、悬空镜像、构建缓存、匿名卷四类。最稳的做法是按"容器→镜像→卷"的顺序渐进清理,而不是 rm -rf 硬删。理解这 3 个坑,再把"每周体检 + 分层清理"变成习惯,磁盘空间就能长期可控,守住磁盘空间这条底线。

延伸学习

想把容器运维理顺,可以看:

  1. 系统入门,Docker 入门课程_编程实战微课;
  2. 网络相关排障,看 Docker 网络连接容器;
  3. 日常操作回查 Docker 速查手册。

常见问题

Q:停止容器后空间为什么没回来?

A:因为 docker stop 只让进程退出,容器的读写层和元数据仍保留在 /var/lib/docker 里。必须显式 docker container prune 或 docker rm 才会真正释放,这也是 Docker 容器占磁盘的持续来源。

Q:docker system prune 会删掉正在用的镜像吗?

A:默认不会删被容器引用的镜像,但会删所有悬空镜像和停止容器。加 -a 后会删所有未被容器使用的镜像,生产环境要谨慎,先 docker system df 看清楚再执行。

Q:volume 不删为什么也会涨磁盘?

A:很多容器用匿名卷存数据,容器删了卷还在,时间一长匿名卷越积越多。定期 docker volume prune(确认无重要数据)才能把这部分空间收回来,单纯的镜像清理救不了磁盘空间。

0 人点赞