从 200G 到 20G:我的 Docker 清理实战经验
你有没有经历过这种事——服务器磁盘突然报警,一查原因:Docker 把磁盘吃了几十个 G,服务全挂。这就是 Docker 的隐藏黑洞:日志无限写 + overlay2 堆积,等到发现时已经晚了。
这篇文章说清楚两件事:怎么提前防住,以及真的爆了怎么救。
一、日志:那个一直在写的文件
Docker 默认用 json-file 日志驱动,没有轮转、没有限制、一直写到底。
日志位置:/var/lib/docker/containers/<container-id>/<container-id>-json.log
# 查看所有容器日志大小
find /var/lib/docker/containers -name "*-json.log" -exec ls -lh {} \; 2>/dev/null
我见过最夸张的案例:一个测试容器跑了三个月,日志文件 47GB。
方案 1:跑容器时就设好轮转(推荐)
docker run -d \
--name myapp \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
myapp:latest
max-size=10m:单个日志文件最大 10MBmax-file=3:最多保留 3 个轮转文件
即容器总日志控制在 30MB 内。
方案 2:改全局配置(所有容器生效)
编辑 /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
如果想把 Docker 数据目录迁移到挂载盘(更大数据盘):
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"data-root": "/data/docker"
}
针对经常 docker build 的服务器,可以限制 BuildKit 缓存:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
},
"data-root": "/data/docker",
"builder": {
"gc": {
"defaultKeepStorage": "10GB",
"enabled": true
}
}
}
改完记得重启:systemctl restart docker
方案 3:正在运行的容器
快速清理(生产环境慎用):
echo "" > $(docker inspect --format='{{.LogPath}}' <container-id>)
规范做法:stop → rm → 重新 run 带轮转参数。
方案 4:紧急清理(磁盘告急时)
find /var/lib/docker/containers -name "*-json.log" -exec truncate -s 0 {} \;
场景推荐配置
| 场景 | 推荐参数 | |------|---------| | 开发环境 | max-size=5m max-file=3 | | 测试环境 | max-size=10m max-file=5 | | 生产环境 | max-size=50m max-file=10 |
注意:配置只对之后新建的容器生效。老容器要么清理日志,要么重建。
二、overlay2 存储:镜像、容器、卷
/var/lib/docker/overlay2 是 Docker 存储镜像和容器数据的默认目录,占用过大的常见原因:
- 镜像残留 — 删除容器后镜像还在
- 停止的容器 — Exited 状态的容器仍占空间
- 日志堆积 — 数据库等容器日志大
- Volumes 未清理 — 容器删了,卷还在
- Build 缓存 — 构建产生的中间层
先诊断
docker system df
这个命令告诉你镜像、容器、卷、缓存各占多少。
清理步骤
Step 1:删停止的容器
docker container prune -f
Step 2:删无用镜像
docker image prune -a # -a 删所有未被容器引用的镜像
Step 3:删无用卷
docker volume prune
Step 4:所有无用资源(推荐定期跑)
docker system prune -a --volumes
⚠️ -a --volumes 会删除所有未运行的容器、未使用的镜像、卷和网络,跑之前确认没有需要保留的数据。极端情况:重置 Docker
# 停服务 + 删数据 + 重启(会删除所有容器、镜像、卷)
sudo systemctl stop docker
sudo rm -rf /var/lib/docker/*
sudo systemctl start docker
三、防再次膨胀
- 定期清理:
docker system prune -f(加-f自动执行,不用敲确认) - 限制日志大小:在
docker-compose.yml或docker run中配置max-size+max-file - 用 docker volume 管理数据,避免容器直接写 overlay2
加监控告警:
watch "df -h / && du -sh /var/lib/docker/*"
总结
Docker 磁盘爆炸就两个主因:日志无限写 + overlay2 堆积。
预防靠两点:新建容器配日志轮转 + daemon.json 设全局默认。急救先 docker system df 看谁在吃空间,再对症清理。根治靠定期 docker system prune + 加监控告警。
不要等到磁盘红了才来处理,日常巡检才是正解。