Docker磁盘空间占满怎么办?镜像、容器与日志安全清理教程

Docker磁盘空间占满怎么办?镜像、容器与日志安全清理教程

Docker服务器运行一段时间后,磁盘空间可能被镜像、停止的容器、构建缓存、容器日志和数据卷逐渐占满。严重时会出现镜像拉取失败、容器无法启动、数据库无法写入,甚至SSH登录和系统服务异常。

遇到这种情况,不要直接删除 /var/lib/docker,也不要一开始就执行带有 --volumes 的全量清理命令。正确做法是先确认哪个分区已满,再判断空间由哪类Docker数据占用,最后按照风险从低到高逐项处理。

本文以Linux服务器上的Docker Engine为例,介绍一套可以直接执行的排查与清理流程。

一、先确认磁盘空间和inode是否耗尽

首先查看各分区的容量:

df -hT

重点关注Docker数据目录所在分区的 Use%。Docker Engine默认把数据保存在 /var/lib/docker,但服务器可能修改过数据目录,可以使用下面的命令确认:

docker info --format '{{.DockerRootDir}}'

如果磁盘容量还有剩余,但系统仍然提示“no space left on device”,还要检查inode:

df -ih

大量小文件可能耗尽inode。此时仅删除一个大文件未必能解决问题,需要继续定位产生海量小文件的目录。

如果根分区已经达到100%,建议先停止持续写入大量日志的异常服务,避免清理过程中空间继续增长。

二、查看Docker各类资源占用

Docker提供了专门的磁盘统计命令:

docker system df

它会分别显示镜像、容器、本地数据卷和构建缓存占用,并标出理论上可以回收的空间。

需要查看具体对象时执行:

docker system df -v

输出中需要重点关注:

项目常见占用来源清理风险
Images历史版本镜像、无标签镜像、未使用镜像
Containers已停止容器及其可写层
Local Volumes数据库、上传文件和持久化业务数据
Build CacheDockerfile构建产生的缓存低至中

还可以从系统目录角度查看Docker数据目录的一级占用:

sudo du -xhd1 /var/lib/docker 2>/dev/null | sort -h

如果Docker根目录不是 /var/lib/docker,请替换成 docker info 查询到的实际路径。

三、先做低风险清理

1. 清理悬空镜像

悬空镜像通常没有标签,常见于重复构建和更新镜像之后。先查看:

docker image ls --filter dangling=true

确认后清理:

docker image prune

该命令默认只删除悬空镜像,相比直接使用 docker image prune -a 更稳妥。

2. 清理构建缓存

频繁执行 docker build 或持续集成任务的服务器,构建缓存可能占用大量空间。

先查看Docker整体占用:

docker system df

然后清理当前未使用的构建缓存:

docker builder prune

执行前Docker会显示警告并要求确认。生产环境中不建议直接添加 -f,保留确认步骤更安全。

3. 检查停止的容器

列出全部容器:

docker container ls -a

仅查看已停止容器:

docker container ls --filter status=exited

如果某个停止容器已确认不再需要,可以按名称或ID删除:

docker container rm 容器名称或ID

需要批量清理所有停止容器时再使用:

docker container prune

注意,删除容器会同时删除其可写层。没有写入数据卷或绑定目录的数据可能随容器一起丢失。

四、谨慎清理未使用镜像

下面的命令不仅处理悬空镜像,还会删除没有被任何现有容器引用的镜像:

docker image prune -a

它可能删除用于回滚的旧版本镜像。清理前建议先执行:

docker image ls docker container ls -a

确认旧镜像可以从镜像仓库重新拉取,并且不再承担故障回滚用途。

也可以使用时间过滤条件,减少误删近期镜像的概率。例如清理创建时间超过168小时且未被使用的镜像:

docker image prune -a --filter "until=168h"

时间过滤只能缩小清理范围,不能代替人工确认。

五、使用docker system prune前要看清范围

Docker提供了一条综合清理命令:

docker system prune

默认情况下,它会清理停止的容器、未使用的网络、悬空镜像和未使用的构建缓存。

如果添加 -a

docker system prune -a

还会清理所有未被容器引用的镜像,影响范围明显扩大。

不建议在不检查数据的情况下执行:

docker system prune -a --volumes

--volumes 会把符合清理条件的匿名数据卷纳入范围。数据卷可能保存数据库、网站上传文件、配置或其他持久化数据,误删后通常无法通过重新创建容器恢复。

安全原则:先分别查看和清理镜像、容器、缓存,最后才考虑综合清理;生产服务器不要把带有 --volumes 的命令作为日常定时任务。

六、重点排查不断增长的容器日志

镜像和容器清理后空间仍然不足,常见原因是容器日志持续增长。

先查看容器使用的日志驱动:

docker info --format '{{.LoggingDriver}}'

查看某个容器的日志配置:

docker inspect --format '{{.HostConfig.LogConfig.Type}} {{json .HostConfig.LogConfig.Config}}' 容器名称

如果使用 json-file 日志驱动,可以查询Docker记录的日志文件路径:

docker inspect --format '{{.LogPath}}' 容器名称

Docker官方不建议使用外部工具直接操作日志驱动管理的内部文件,因为这可能干扰Docker日志系统。与其长期依赖手动截断日志,更可靠的方案是配置日志轮转,然后重新创建容器。

推荐方案:使用local日志驱动

编辑 /etc/docker/daemon.json。如果文件原本已有其他配置,需要把下面字段合并进去,不要直接覆盖整个文件:

{ "log-driver": "local", "log-opts": { "max-size": "10m", "max-file": "3" } }

检查JSON格式后重启Docker:

sudo systemctl restart docker

该配置只会自动应用于之后新建的容器。已有容器需要在确认编排文件和数据挂载无误后重新创建,才会使用新的日志配置。

如果不希望修改全局设置,也可以在创建单个容器时指定:

docker run \ --log-driver local \ --log-opt max-size=10m \ --log-opt max-file=3 \ 镜像名称

使用Docker Compose时,可以在对应服务中配置:

services: app: image: your-image logging: driver: local options: max-size: "10m" max-file: "3"

配置完成后重新创建相关服务:

docker compose up -d --force-recreate

执行前要确认Compose配置、环境变量和数据卷均已保存。

七、数据卷为什么必须最后处理

数据卷拥有独立于容器的生命周期。删除容器后,命名数据卷可能仍然保留,其中经常存放:

  • MySQL、PostgreSQL等数据库文件
  • WordPress等网站的上传内容
  • 应用配置与密钥
  • 队列、搜索引擎和监控系统数据

查看数据卷:

docker volume ls

查看某个数据卷的详细信息:

docker volume inspect 数据卷名称

确认数据卷未被使用且内容已经备份后,才能删除指定数据卷:

docker volume rm 数据卷名称

批量删除未被容器挂载的数据卷需要格外谨慎:

docker volume prune

“未被当前容器挂载”不等于“业务不再需要”。例如已经删除的数据库容器可能仍然依赖原来的命名卷进行恢复,因此不能仅根据未挂载状态判断数据是否可以删除。

八、清理后如何验证

完成清理后再次检查系统分区:

df -hT df -ih

检查Docker占用:

docker system df -v

检查容器状态:

docker container ls -a

如果清理后空间没有明显变化,需要继续检查:

  1. Docker数据目录是否位于其他分区。
  2. 是否存在仍被进程占用但已经删除的文件。
  3. 应用是否把日志写入绑定挂载的宿主机目录。
  4. 数据库、备份文件或系统日志是否才是真正的占用来源。
  5. 使用containerd镜像存储时,相关数据是否位于单独的存储路径。

查找“已删除但仍被进程占用”的文件可以使用:

sudo lsof +L1

确认对应进程和业务影响后,再决定重启服务或释放文件句柄。

九、如何防止Docker再次占满磁盘

完成一次清理只能解决当前问题,还需要建立长期控制措施:

1. 为容器日志设置上限

优先使用带轮转能力的日志驱动,或者把日志发送到集中式日志系统。不要让默认日志无限增长。

2. 定期监控Docker占用

可以定期执行:

docker system df df -hT df -ih

并为磁盘使用率设置告警。不要等到分区达到100%才处理。

3. 控制镜像版本数量

部署完成后保留必要的当前版本和回滚版本,清理长期不用的历史镜像。镜像仓库中的版本策略也要同步管理。

4. 把持久化数据放入明确的数据卷

数据库和业务文件应使用命名卷或绑定挂载,并建立独立备份。不要依赖容器可写层保存重要数据。

5. 为Docker规划独立磁盘

镜像构建频繁、日志量大或容器数量较多时,可以把Docker数据目录规划到容量充足的独立分区。迁移数据目录前必须停止Docker、完成备份并核对存储驱动,不建议在故障现场临时移动目录。

十、推荐的安全处理顺序

遇到Docker磁盘空间占满,可以按照下面的顺序操作:

  1. 使用 df -hT 和 df -ih 确认容量或inode问题。
  2. 使用 docker info 确认Docker数据目录。
  3. 使用 docker system df -v 定位镜像、容器、卷和缓存占用。
  4. 优先清理悬空镜像和无用构建缓存。
  5. 人工确认后删除停止容器和未使用镜像。
  6. 排查容器日志,并配置日志轮转。
  7. 备份和核对业务后,才处理数据卷。
  8. 清理完成后检查容器状态、磁盘空间和关键业务。

总结

Docker磁盘占满通常不是单一原因造成的。镜像历史版本、停止容器、构建缓存、不断增长的日志以及长期遗留的数据卷,都可能共同占用空间。

最重要的原则是先定位、后清理,并把数据卷和日志文件视为高风险对象。docker system prune 可以提高处理效率,但它不能代替业务确认和数据备份。完成清理后,还应配置日志轮转、磁盘监控和镜像保留策略,避免相同问题反复发生。

知识库

2026年云服务器优惠怎么选?首购价格、续费成本与避坑指南

2026-7-31 17:15:07

实操指南

如何全面加固服务器安全性

2024-11-4 10:36:21