Docker overlay2 占满磁盘怎么办?镜像、容器、构建缓存与日志安全清理

2026-09-20

直接答案:/var/lib/docker/overlay2 变大时,先用 docker system df -v 区分镜像、停止容器、可写层和构建缓存,再检查容器 json-file 日志与 volumes。不要直接 rm -rf overlay2:Docker 维护层、快照和元数据映射,手删可能让容器和镜像不可恢复。短期只清理已确认不用的对象;长期为日志设置 max-size/max-file、让业务数据进入 volume/对象存储,并为构建缓存和镜像保留制定策略。

本文适合 Docker 主目录所在分区接近满、overlay2目录占用大或拉取/启动失败。若数据主要在 named volume、bind mount 或数据库目录,清理镜像不会释放那部分;若 inode 耗尽,也要单独统计小文件数量。

本文按 2026 年 9 月可查的官方文档核对。示例命令以只读取证为主;凡涉及删除、覆盖、重启、权限、网络或数据库参数的动作,都应先确认操作对象、备份、维护窗口和带外恢复入口。不同发行版与软件版本的路径可能不同,必须先查询实际配置再改。

先用证据判断故障在哪一层

现象或检查点 它能说明什么 直接证据 不要误判为
Images/Reclaimable很大 存在未被容器使用的镜像或层 docker system df -v与容器引用 所有镜像都可删
Build cache很大 CI或频繁构建累积缓存 builder df与构建时间线 容器运行数据
某容器Size持续增长 业务写入容器可写层 docker ps --size与路径映射 镜像本身变大
*-json.log巨大 默认日志未轮转或应用刷屏 inspect日志路径与日志速率 overlay层文件
Volumes很大 持久数据、数据库或遗留卷 volume inspect、挂载与责任人 可直接prune

这张表的用法不是“看到一个关键词就改一个参数”,而是把客户端、DNS或边缘、Web 代理、应用、数据层依次分开。至少保留故障时间、完整 URL、状态码、关键响应头、同一时刻的服务日志和一份正常样本。只有时间能够对齐,才能判断两个现象是否属于同一次故障。

六步排查与修复顺序

1. 先确认空间还是 inode

记录 df -h、df -i、Docker Root Dir、存储驱动和首次告警时间。分区 100% 时先保护数据库和日志写入,停止非关键构建;不要在容量危急时运行会产生大量临时数据的扫描。

2. 用 Docker 视角分解占用

执行 docker system df -v、容器 size、builder df 和 volume 列表,将每项关联到应用、版本和负责人。Reclaimable 是候选,不等于业务无依赖;停止容器仍可能是待回滚版本。

3. 识别容器可写层异常

查看哪些容器 Size 随时间增长,检查应用是否把上传、缓存、数据库或临时文件写进镜像层。把持久数据迁到明确 volume/bind mount 前先做一致备份和恢复演练。

4. 检查日志而不手改活动文件

Docker 默认 json-file 日志可无限增长。读取 logging driver、LogPath 和应用错误频率;按官方配置新容器的 max-size/max-file。不要用外部工具直接操作 Docker 正在管理的日志文件。

5. 按对象精确清理

优先删除已确认不用的构建缓存、悬空镜像和过期停止容器。执行 prune 前查看其将影响的对象和 volumes 选项;volume 默认不随 system prune 删除是重要保护,不能为了多释放空间盲加 --volumes。

6. 建立持续容量与恢复验收

修复后重建或重启目标容器,确认数据、端口和健康。观察一次构建和日志高峰,配置磁盘/ inode 告警、日志轮转、镜像保留和备份恢复;Docker 版本升级后还要核对存储后端变化。

可复制的只读取证命令

以下命令中的域名、服务名、路径和时间范围要替换为自己的真实值。先执行查询命令并保存原始输出;不要把“命令能运行”误当成“业务已恢复”。

text docker info --format '{{.DockerRootDir}} {{.Driver}}' docker system df -v docker ps -a --size --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}' docker inspect --format '{{.Name}} {{.HostConfig.LogConfig.Type}} {{.LogPath}}' $(docker ps -q) docker builder prune --filter 'until=168h'

  • docker info --format '{{.DockerRootDir}} {{.Driver}}':确认Docker根目录与存储驱动
  • docker system df -v:按镜像、容器、volume和缓存查看Docker认识的占用
  • docker ps -a --size --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Size}}':查找可写层异常增长的容器
  • docker inspect --format '{{.Name}} {{.HostConfig.LogConfig.Type}} {{.LogPath}}' $(docker ps -q):列出运行容器日志驱动与路径;容器很多时分批执行
  • docker builder prune --filter 'until=168h':清理一周前未使用构建缓存的交互示例;执行前必须核对构建与回滚需求

如命令输出包含公网 IP、用户名、Cookie、令牌、数据库连接串或客户数据,分享工单前先脱敏。对比时保留时间戳、时区和命令本身,否则后来无法复现同一观察条件。

五个最容易扩大故障的误区

  • 直接删除 overlay2 目录:会破坏Docker元数据与层引用,可能导致容器无法启动。
  • docker system prune -a --volumes 一把梭:可能删除回滚镜像、停止容器和匿名卷中的唯一数据。
  • 只清镜像不查日志:json-file或应用可写层会继续把磁盘占满。
  • 把数据库放容器可写层:重建容器可能丢数据,也难以独立备份。
  • 只看GB不看inode:大量小文件会在容量仍有剩余时耗尽inode。

变更、回滚与数据边界

清理动作通常难以原地回滚,因此必须先列出精确对象、确认镜像可重新拉取、保存 Compose/配置,并对 volumes 做应用一致备份。不要删除仍用于回滚的 tag/digest。若日志策略变更导致排障信息不足,恢复旧配置只对新建容器生效与否要按 Docker 文档验证;已删除的日志和缓存不能恢复。

如果只能先恢复服务、还不能确认根因,应把措施标记为“临时缓解”,例如限流、摘除单节点、切回上一配置或临时绕过一层代理。恢复后仍要在受控环境复现原因,并验证同类故障不会在下一次重启、发布或高峰重新出现。

统一验收清单

  • [ ] Docker Root Dir与文件系统已确认
  • [ ] 空间和inode均有基线
  • [ ] 镜像、构建缓存、可写层、日志和volume占用已分开
  • [ ] 删除对象均有责任人确认
  • [ ] 未直接操作overlay2内部文件
  • [ ] 日志轮转对新容器已验证
  • [ ] 持久数据有独立恢复演练
  • [ ] 跨过一次构建与流量高峰磁盘仍稳定

验收必须同时覆盖机器内部和真实外部路径。首页返回 200 不能证明上传、长连接、登录、数据库写入或移动端都正常;同样,控制台显示“运行中”也不能证明应用已能处理请求。至少选一个正常请求、一个边界请求和一个失败请求,记录预期与实际结果。

相关内容与隔离测试入口

建议先阅读服务器磁盘满清理、Docker Compose生产部署、快照和备份区别,把本问题放回完整请求链路。若生产环境不适合直接试验,可查看美国弹性云服务器的当前规格与库存,搭建与生产隔离的复现环境;测试机不能替代生产备份,价格、库存和可选配置以实时产品页为准。

常见问题

overlay2目录可以手动删旧文件夹吗?

不可以按目录时间猜测。Docker层可能被镜像或容器引用,应使用Docker命令管理。

docker system prune 会删volume吗?

默认不会删除 volumes;加特定选项才扩大范围。执行前阅读当前版本提示并确认数据边界。

为什么删除镜像后空间没有马上下降?

层可能仍被其他镜像/容器引用,或实际大户是日志、volume、已删除但仍打开的文件。

json-file 日志能直接 truncate 吗?

官方警告外部工具操作这些文件可能干扰Docker。应配置日志轮转并在维护方案中处理现有日志。

迁移 Docker Root Dir 能解决吗?

能扩展容量但不解决无界日志和错误写入。迁移涉及停机、权限、存储驱动和回滚,应单独规划。

官方参考资料

最近更新