当服务器出现 no space left on device、容器无法启动、镜像拉取失败时,很多人会发现 /var/lib/docker/overlay2 占用了大量空间。此时不要直接删除 overlay2 子目录,否则可能破坏镜像层与容器元数据之间的关联。正确思路是先定位空间来源,再通过 Docker 提供的资源管理命令逐级清理。🔍
一、先确认是容量耗尽还是 inode 耗尽
首先执行 df -h 查看磁盘容量。如果 Docker 所在分区使用率接近上限,再执行 df -i 检查 inode。大量零碎文件可能耗尽 inode,即使磁盘仍有剩余容量,也会出现无法创建文件的报错。
继续使用 sudo du -xh --max-depth=1 /var/lib/docker | sort -h 查看 Docker 各目录的实际占用。除了 overlay2,还应重点关注 containers、volumes 和 buildkit。某些情况下,真正迅速增长的是容器日志,而不是存储层本身。
二、理解 Overlay2 为什么会变大
Overlay2 基于 OverlayFS,将镜像只读层与容器可写层组合成统一文件系统。镜像反复构建、旧容器长期保留、应用持续向容器内部写入文件,以及构建缓存不断累积,都会让相关目录逐渐膨胀。其工作原理和目录结构可参考 Docker OverlayFS 官方文档。
需要注意,overlay2 目录大并不等于里面都是垃圾。多个镜像可能共享同一层,运行中的容器也依赖对应的可写层。因此,单纯按照目录大小手动删除哈希目录,容易造成容器无法启动、镜像损坏或 Docker 元数据不一致。⚠️
三、用 Docker 命令定位可回收空间
建议先执行 docker system df 查看镜像、容器、本地卷及构建缓存的总体占用,再执行 docker system df -v 获取明细。排查时应重点关注 RECLAIMABLE,它表示 Docker 判断可以回收的空间,而不是磁盘中的全部占用。
- 镜像占用高:通常与历史版本、悬空镜像或频繁构建有关。
- 容器占用高:可能存在大量已停止容器,或运行容器的可写层持续增长。
- 构建缓存高:常见于 CI、测试机和开发服务器。
- 本地卷占用高:可能保存数据库、上传文件或其他持久化数据,清理前必须核对用途。
四、按照风险从低到高清理
1. 清理悬空镜像与构建缓存
先执行 docker image prune 删除无标签且未被容器引用的悬空镜像,再通过 docker builder prune 清理无用构建缓存。这类操作通常风险较低,但仍应查看命令给出的删除清单。
2. 清理已停止容器和无用网络
使用 docker ps -a 核对全部容器,确认已停止的容器不再需要后,执行 docker container prune。无用网络可通过 docker network prune 清理。停止容器的可写层可能包含尚未导出的文件,删除后无法依靠重新启动找回。
3. 谨慎执行系统级清理
docker system prune 可以集中删除停止的容器、无用网络、悬空镜像和构建缓存。添加 -a 后还会删除未被任何容器引用的镜像。生产环境建议使用 --filter until=时间范围 缩小清理范围,避免把近期仍可能回滚使用的镜像删掉。具体规则可查看 Docker 清理资源官方文档。
不要轻易添加 --volumes。未被容器引用的卷也可能保存重要业务数据,清理前应检查 docker volume ls、挂载关系和备份状态。
五、检查异常增长的容器日志
Docker 使用 json-file 日志驱动时,日志通常位于 /var/lib/docker/containers,并不直接存放在 overlay2 中,但两者往往位于同一分区。可通过 docker inspect --format='{{.LogPath}}' 容器名 查询日志路径,再结合 du -h 判断是否存在超大日志。
紧急释放空间时,可以在确认日志无需保留后使用 truncate -s 0 日志文件路径 截断文件,不建议直接删除仍被 Docker 打开的日志文件。长期方案是在 daemon.json 或 Compose 配置中设置 max-size 与 max-file,启用日志轮转。修改守护进程配置后,应先检查 JSON 格式,再安排维护窗口重启 Docker。🛠️
六、清理后验证与长期预防
- 再次执行 df -h 和 df -i,确认容量及 inode 已恢复。
- 执行 docker system df,核对资源占用是否符合预期。
- 运行 docker ps,检查业务容器状态和健康检查结果。
- 查看应用日志并访问关键接口,确认清理没有影响服务。
- 为磁盘使用率、inode、容器日志和构建缓存设置监控告警。
日常管理中,应减少应用向容器可写层保存持久数据,将数据库、上传文件和关键配置放入明确管理的卷或外部存储;CI 环境应定期清理构建缓存,并避免无期限保留测试镜像。自动清理任务应设置时间过滤条件,同时保留执行日志,生产环境不宜直接定时运行无范围限制的 docker system prune -af。
总结
Docker 磁盘空间耗尽时,安全处理顺序应是:确认容量与 inode、定位具体资源、优先清理缓存和悬空对象、核查停止容器与日志、最后谨慎处理镜像和卷。Overlay2 是 Docker 存储层的核心组成部分,不应把它当作普通缓存目录直接删除。通过官方 prune 命令、日志轮转、容量监控及合理的数据持久化设计,才能在释放空间的同时保证容器环境稳定可靠。✅