Docker overlay2 存储驱动的磁盘空间问题
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 服务可以短暂停止时,才考虑以下步骤。
- 停止 Docker 服务:
systemctl stop docker - 为防止误删,将 overlay2 整体备份(移至其他位置):
mv /var/lib/docker/overlay2 /var/lib/docker/overlay2.backup - 重启 Docker,Docker 会自动重建
overlay2目录,但所有镜像、容器数据将丢失。然后你可以从备份中恢复需要的层。 - 如果只是想删除某个未引用的层,可以借助 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"