Docker overlay2 存储驱动的磁盘空间问题

FreeGuideOnline 最新 2026-07-06

bash docker system df


输出的最后一列 **RECLAIMABLE** 就是你能够安全释放的空间大小。加上 `-v` 参数可以查看每个镜像、容器、卷的详细占用:

```bash
docker system df -v

检查 overlay2 目录的真实占用

有时 Docker 报告的占用与实际文件系统不一致,可直接查看目录大小:

du -sh /var/lib/docker/

要深入定位具体是哪个层占用最高,可以执行:

du -sh /var/lib/docker/overlay2/*/ | sort -rh | head -20

结合 find 查找大文件

如果你怀疑是容器日志导致的,可以直接找出大于 100MB 的文件:

find /var/lib/docker/containers/ -name "*.log" -size +100M -exec ls -lh {} \;

查看 inode 使用情况

大量小文件(尤其是符号链接)可能耗尽 inode。检查 inode 使用率:

df -i | grep /var/lib/docker

如果 inode 使用率接近 100%,即使还有磁盘空间,也无法创建新文件。

清理方法:安全回收空间

一键安全清理:docker system prune

对于初学者,这是最安全的起点。它会删除所有停止的容器、未被任何容器使用的网络、所有悬空镜像(dangling images)以及构建缓存。

docker system prune

注意:该命令默认不删除卷。如果想要更彻底的清理,可以加上 --volumes 参数,它会删除所有没有被至少一个容器使用的卷。请谨慎操作!

docker system prune -a --volumes

加上 -a 参数会进一步删除所有未被任何容器关联的镜像(不仅仅是悬空镜像),这样回收空间更多。

分步精确清理

1. 清理容器

先列出所有已停止的容器,然后删除它们:

docker container prune

或手动删除指定容器:

docker rm <container_id>

2. 清理镜像

删除所有悬空镜像:

docker image prune

删除所有未被使用的镜像:

docker image prune -a

3. 清理卷

删除所有未被至少一个容器使用的卷:

docker volume prune

4. 限制日志文件大小

这是一种“治本”的清理方式。为所有容器统一配置日志轮转,编辑 /etc/docker/daemon.json,添加:

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

然后重启 Docker:

systemctl restart docker

注意:该配置仅对新创建的容器生效,旧容器需要重新创建。

手动清理 overlay2 目录(高级)

⚠️ 警告:直接操作 /var/lib/docker/overlay2 极度危险,可能导致 Docker 完全损坏。仅当 docker system prune 无法解决问题,且你确认 Docker 服务可以短暂停止时,才考虑以下步骤。

  1. 停止 Docker 服务:
    systemctl stop docker
    
  2. 为防止误删,将 overlay2 整体备份(移至其他位置):
    mv /var/lib/docker/overlay2 /var/lib/docker/overlay2.backup
    
  3. 重启 Docker,Docker 会自动重建 overlay2 目录,但所有镜像、容器数据将丢失。然后你可以从备份中恢复需要的层。
  4. 如果只是想删除某个未引用的层,可以借助 Docker 的 dockerd --debug 日志来判断哪些层 ID 当前被引用,然后删除未被引用的目录。

更安全的推荐:直接重置整个 Docker 存储,再拉取所需镜像、重新运行容器。操作如下:

systemctl stop docker
rm -rf /var/lib/docker
systemctl start docker

重新部署你的服务。

预防措施:避免磁盘危机重演

1. 强制使用日志轮转和大小限制

如上所述,修改 daemon.json 配置日志上限,这是防止日志撑爆磁盘的最有效手段。

2. 合理设计 Dockerfile 和构建流程

  • 多阶段构建(Multi-stage builds)可有效减少最终镜像层数和大小。
  • 在同一 RUN 指令中合并命令,并使用 && 清理临时文件,避免在额外层中残留无用数据。
    RUN apt-get update && apt-get install -y some-package \
        && rm -rf /var/lib/apt/lists/*
    
  • 构建完成后立即使用 docker builder prune 清理构建缓存。

3. 设置自动清理策略(Cron 或 Systemd Timer)

定期运行清理命令。例如,创建一个 cron 任务,每周日凌晨 2 点清理悬空资源和停止 7 天以上的容器:

0 2 * * 0 /usr/bin/docker system prune -f --filter "until=168h"