
Docker 主机的磁盘空间不断下降,删除几个已经停止的容器却没什么变化,常见原因在镜像层、BuildKit 构建缓存、未使用的 volume 和容器日志。docker system df 能给出 Docker 资源的占用概览,但真正清理前还要确认哪些镜像、缓存和卷仍被部署流程依赖。
先确认是 Docker 占用,还是文件系统其他目录增长
先检查报错路径所在文件系统,再看 Docker 自己统计的空间:
df -hT /var/lib/docker
docker system df
docker system df -v
docker system df 会按 Images、Containers、Local Volumes 和 Build Cache 分类显示占用。-v 可以继续看到镜像、容器和卷的明细。Docker 根目录不一定是 /var/lib/docker,如果使用了自定义 data-root,应以 docker info 的结果为准:
docker info --format '{{.DockerRootDir}}'
findmnt -T "$(docker info --format '{{.DockerRootDir}}')"
如果 docker system df 的总量和 df 的已用空间差距很大,说明增长点可能在 Docker 目录之外,也可能是被进程打开但已经删除的文件。此时不要只重复执行 docker system prune。
镜像层和 dangling image 怎么看
列出本地镜像及其大小:
docker image ls
构建失败或重新打标签后,可能留下没有仓库和标签的 dangling image。可以单独列出:
docker image ls --filter dangling=true
<none>:<none> 不等于一定可以删除。有些自动化流程会暂时依赖中间镜像,或者镜像仍被某个容器使用。先查看容器引用关系:
docker ps -a --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}'
确认构建产物已经推送、旧容器已切换,再删除明确不再使用的镜像。按标签删除比按模糊的大小判断更安全:
docker image rm example/app:old-release
如果镜像被容器引用,Docker 会拒绝删除,除非使用强制参数。生产主机上不要把 -f 当作常规清理手段。
BuildKit cache 往往是主要增长点
现代 Docker 构建通常会保留缓存,以复用软件包下载、依赖安装和中间层。缓存能缩短后续构建时间,但长期不清理会占用大量空间。查看构建缓存:
docker builder du
如果环境使用多个 builder,先确认当前 builder:
docker buildx ls
docker buildx du
清理前可以先删除未被近期构建使用的缓存:
docker builder prune
这个命令会提示将要回收的空间。自动化主机需要无人值守执行时,可以使用带过滤条件的策略,而不是无条件清空:
docker builder prune --filter 'until=168h'
BuildKit 缓存可能分布在不同 builder 或 Docker 根目录下。只看 docker image ls,可能漏掉真正占空间的构建缓存。
system prune 会删除什么
docker system prune 会清理一组未使用的 Docker 资源,默认不会删除所有未使用的 volume:
docker system prune
需要明确回收未使用卷时,才使用:
docker system prune --volumes
这条命令风险更高。Docker volume 可能保存数据库、上传文件或备份,即使当前没有容器挂载,也不代表业务不再需要。先列出卷和挂载点:
docker volume ls
docker volume inspect volume_name
对单个卷执行删除前,确认备份已经可恢复,并确认没有 compose 项目会在下一次部署时重新使用它。清理命令的范围应写进运维记录,不要把线上主机的空间告警处理简化成一条固定脚本。
容器日志也可能填满磁盘
如果镜像和构建缓存都不大,但 /var/lib/docker/containers 增长明显,检查容器日志文件:
sudo find "$(docker info --format '{{.DockerRootDir}}')/containers" -name '*-json.log' -type f -printf '%s %p\n' 2>/dev/null | sort -n | tail
Docker 的 json-file 日志驱动如果没有配置轮转,单个容器可能持续写入一个很大的文件。长期方案是在 Docker daemon 或 compose 服务中设置合适的日志驱动和 max-size、max-file,并在变更后重建或重新创建容器,让新配置真正生效。直接截断日志只能临时释放空间,不能替代轮转配置。
用一个安全顺序处理磁盘告警
先执行 df -hT、docker system df -v 和 docker builder du,确定增长类型;再检查大日志文件和 data-root 的真实挂载点。确认资源没有被部署、数据库或备份任务使用后,按镜像、构建缓存、容器和卷分别清理。清理后再次运行 df -hT 与 docker system df,记录回收前后的差异。
如果 Docker 统计的占用已经下降,但文件系统空间没有释放,再检查 deleted 文件:
sudo lsof +L1
某个进程仍打开已删除日志时,空间要等文件描述符关闭后才会回收。找到进程后使用它支持的 reopen、reload 或重启流程,避免直接终止承载业务请求的进程。




