Docker 用久了,磁盘占用悄悄涨到几十 GB 是常态:构建缓存、悬空镜像、停掉的容器、遗忘的数据卷都在背后堆积。本文给出一套从定位到清理的完整流程,兼顾释放空间与不误删数据。

DXTool 主界面

第一步:先定位谁占的空间

清理前先看全景,Docker 自带的统计命令就够用:

docker system df

输出四行:Images(镜像)、Containers(容器)、Local Volumes(数据卷)、Build Cache(构建缓存),每行都有 SIZE 和 Reclaimable——后者是理论上可回收的空间。想看明细加 -v 参数。

经验上,Build Cache 往往是最大头,尤其是频繁构建 Java / 前端镜像的机器,几个 GB 到几十 GB 都正常。

第二步:按类型逐项清理

构建缓存(BuildKit 缓存层)

docker builder prune                 # 清理悬空构建缓存
docker builder prune -a              # 清理全部构建缓存(下次构建变慢,但最彻底)
docker builder prune --keep-storage 5g   # 保留 5GB,清理其余

悬空镜像与未使用镜像

docker image prune                   # 只删悬空镜像(<none> 标签,最安全)
docker image prune -a                # 删除所有「没有被任何容器使用」的镜像

注意 -a 的范围是「未被容器引用」,不是「全部」——正在运行的服务的镜像不会被动。但如果同一镜像以后还要离线使用,先 docker save 备份。

停止的容器

docker container prune               # 删除所有已停止的容器

容器删除后日志也随之消失,如果需要排查历史问题,先 docker logs <container> 导出。

数据卷(最需要谨慎)

docker volume ls                     # 先看有哪些卷
docker volume prune                  # 只删「没有被任何容器引用」的匿名卷
docker volume prune -a               # 删除所有未引用卷,包括命名卷

数据库、Redis 的持久化数据都在卷里。prune 只删未引用的卷,理论上安全,但如果你有「停机状态的数据库容器 + 命名卷」,-a 会把卷删掉——生产机器不要随手加 -a。

第三步:一把梭与它的风险

docker system prune                  # 悬空镜像 + 停止容器 + 未用网络 + 构建缓存
docker system prune -a --volumes     # 上述全部 + 未用镜像 + 未用卷(核弹级)

-a --volumes 一次能释放最多空间,但未引用的数据卷也会被清掉。建议只在测试环境或确认无重要数据时使用,生产环境老老实实按第二步逐项来。

常见坑:删了文件但空间没释放

Linux 上删除容器日志文件后 df -h 仍显示占用,是因为进程还持有文件句柄。重启对应容器(或 docker restart <container>)让句柄释放,空间才会归还。

从根源治理:让日志走大小限制,避免单个容器日志撑爆宿主机:

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "50m", "max-file": "3" }
}

写在 /etc/docker/daemon.json 后重启 Docker 生效(只对新建容器生效)。

养成习惯

  • CI 构建机:每次构建后跑 docker builder prune -f,或定期任务清理
  • 开发机:每周 docker system df 看一眼,Reclaimable 超过 10GB 就做一轮 docker system prune
  • 镜像统一打 tag,禁止长期留 <none> 悬空镜像

常用命令可以收藏速查表对照使用:Docker 命令速查。如果你在 Windows 上做本地排查,也可以试试我们的 Windows 本地工具箱,端口占用、文件定位等排查工具离线可用。