Docker 用着用着磁盘就满了?这 5 条命令帮你找出几十 G 垃圾
目录
- 一、问题现象:服务器磁盘突然 95% 告警
- 二、Docker 磁盘占用的 6 个来源
- 三、命令一:docker system df——看整体占用
- 四、命令二:docker system df -v——精确定位大文件
- 五、命令三:docker image prune——清理悬空镜像
- 六、命令四:docker builder prune——清理构建缓存
- 七、命令五:docker system prune -a——一键清理(慎用)
- 八、实战:一次清理 47GB 的完整过程
- 九、为什么 CI 环境特别容易磁盘爆炸
- 十、预防方案:自动清理脚本 + 配置优化
- 十一、环境与版本
一、问题现象:服务器磁盘突然 95% 告警
上周五下午,CI 服务器磁盘告警了。一台 100GB 系统盘的机器,/ 分区使用率 95%,剩 5GB。Docker 还在不停地 build,眼看就要挂了。
df -h 看了一眼,根分区确实快满了。但代码仓库总共才 2GB,哪来的几十 G?
$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 99G 94G 5.0G 95% /
直觉告诉我是 Docker 干的。一年前遇到过同样的坑,这次记下来完整排查过程,免得下次再踩。
二、Docker 磁盘占用的 6 个来源
先搞清楚 Docker 到底在磁盘上存了什么,才知道该清哪里:

在 CI/CD 环境里,构建缓存(Build Cache)是最大的空间杀手,经常能占 50% 以上。因为每次 docker build 都会产生一层缓存,CI 每天跑几十上百次构建,缓存堆积速度很恐怖。
三、命令一:docker system df——看整体占用
第一条命令,先看 Docker 总共占了多少空间:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 47 8 28.5GB 22.3GB (78%)
Containers 23 5 1.2GB 890MB (74%)
Local Volumes 12 4 3.8GB 2.1GB (55%)
Build Cache 856 0 34.2GB 34.2GB (100%)
四个类型一目了然:
| 类型 | 说明 | 本次占用 | 可回收 |
|---|---|---|---|
| Images | 所有镜像(含中间层) | 28.5 GB | 22.3 GB |
| Containers | 所有容器的可写层 | 1.2 GB | 890 MB |
| Local Volumes | 本地数据卷 | 3.8 GB | 2.1 GB |
| Build Cache | 构建缓存 | 34.2 GB | 34.2 GB |
看 RECLAIMABLE 列——总共可以回收 59.5GB。问题找到了。
RECLAIMABLE 显示的是"可安全回收"的空间。这个值高不代表必须清理,但如果磁盘紧张,优先清理 RECLAIMABLE 高的。
四、命令二:docker system df -v——精确定位大文件
加 -v 看详细信息,能定位到具体哪个镜像、哪个卷占了大空间:
$ docker system df -v
# 镜像详情(按大小排序,截取前 5)
Images space usage:
REPOSITORY TAG IMAGE ID SIZE SHARED
myapp v1.2 a3b4c5d6e7f8 2.1GB 1.8GB
postgres 16.2 b4c5d6e7f8a3 985MB 620MB
node 20-slim c5d6e7f8a3b4 420MB 310MB
<none> <none> d6e7f8a3b4c5 1.8GB 0 # ← dangling 镜像
<none> <none> e7f8a3b4c5d6 1.5GB 0 # ← dangling 镜像
# 构建缓存详情
Build cache usage: 856 entries
CACHE ID TYPE SIZE CREATED LAST USED
abc123 regular 1.2GB 3 days ago 2 days ago
def456 regular 890MB 5 days ago 5 days ago
ghi789 regular 760MB 1 week ago 1 week ago
...
关键发现:
- 两个
<none>镜像占了 3.3GB——这是旧构建产生的 dangling 镜像,没用了 - 构建缓存 856 条,很多是几天前的,大概率不会再复用
五、命令三:docker image prune——清理悬空镜像
先清理最安全的——dangling 镜像(就是那些 <none>:None 的):
# 只清理 dangling 镜像(最安全)
$ docker image prune
# 会提示:Total reclaimed space: 3.3GB
# 如果要清理所有未被容器使用的镜像(稍激进)
$ docker image prune -a
# 会清理所有没有容器在用的镜像,回收更多空间
docker image prune -a会删掉所有没在跑的镜像。如果你有些镜像是为了快速启动而缓存的,别用-a,用不带参数的版本只删 dangling。
六、命令四:docker builder prune——清理构建缓存
这是本次清理的大头——34.2GB 的构建缓存:
# 清理所有构建缓存
$ docker builder prune
# 会提示确认,输入 y
# Total reclaimed space: 34.2GB
# 只清理 24 小时前的缓存(保留最近的,下次构建能命中缓存)
$ docker builder prune --filter "until=24h"
# 只清理未被使用的缓存
$ docker builder prune --filter "unused-for=24h"
--filter "until=24h" 是比较推荐的方式——保留最近 24 小时的缓存(CI 构建还能命中),清理更老的。这样既释放空间又不影响构建速度。
七、命令五:docker system prune -a——一键清理(慎用)
如果你想一步到位,用这条命令:
# 清理所有未使用资源(镜像 + 容器 + 网络 + 构建缓存)
$ docker system prune -a
# 加 --volumes 连数据卷一起清
$ docker system prune -a --volumes
# ↑ 这个会删数据,确认没有重要数据卷再加这个参数
docker system prune -a 会清理:
- 所有停止的容器
- 所有没有被容器使用的网络
- 所有没有标签的镜像(dangling)
- 所有没有被容器引用的镜像(
-a的作用) - 所有构建缓存
-a参数很激进。如果你有docker pull下来准备用的镜像,但没有容器在跑,会被一起删掉。生产环境慎用。
八、实战:一次清理 47GB 的完整过程
回到开头那个 95% 磁盘告警的服务器,完整清理过程:
步骤 1:确认 Docker 占用
$ docker system df
# Build Cache: 34.2GB, Images: 28.5GB (22.3GB reclaimable)
步骤 2:清理 dangling 镜像
$ docker image prune
# Total reclaimed space: 3.3GB
步骤 3:清理旧构建缓存(保留 24h)
$ docker builder prune --filter "until=24h"
# Total reclaimed space: 28.7GB
步骤 4:清理停止的容器
$ docker container prune
# Total reclaimed space: 890MB
步骤 5:清理未使用的数据卷
$ docker volume prune
# Total reclaimed space: 2.1GB
步骤 6:确认结果
$ df -h /
Filesystem Size Used Avail Use%
/dev/vda1 99G 47G 52G 47% / # ← 从 95% 降到 47%
| 清理项 | 回收空间 | 耗时 |
|---|---|---|
| dangling 镜像 | 3.3 GB | 2 秒 |
| 构建缓存(24h 前) | 28.7 GB | 5 秒 |
| 停止的容器 | 890 MB | 1 秒 |
| 未使用的数据卷 | 2.1 GB | 1 秒 |
| 合计 | 34.99 GB | ~10 秒 |
磁盘使用率从 95% 降到 47%,总共回收了约 35GB。
九、为什么 CI 环境特别容易磁盘爆炸
CI 环境的磁盘爆炸有规律可循,根本原因是三个:
1. 频繁构建产生大量缓存——每次 docker build 都会产生 Build Cache。一天 50 次构建,一个月就是 1500 条缓存,轻松几十 G。
2. 旧镜像不清理——CI 每次构建都打新 tag,旧 tag 的镜像没人用但也不删。myapp:v1.2、myapp:v1.3、myapp:v1.4... 每个都 1-2GB。
3. 容器日志无限增长——默认的 json-file 日志驱动没有大小限制,一个跑了几个月的服务日志能涨到好几个 G。
十、预防方案:自动清理脚本 + 配置优化
方案一:定期清理脚本
#!/bin/bash
# docker-cleanup.sh,放到 crontab 每天跑一次
# 清理 24 小时前的构建缓存
docker builder prune -f --filter "until=24h"
# 清理 dangling 镜像
docker image prune -f
# 清理停止的容器
docker container prune -f
# 清理未使用的数据卷(确认安全后取消注释)
# docker volume prune -f
echo "Cleanup done at $(date)"
# 加到 crontab,每天凌晨 3 点执行
0 3 * * * /opt/scripts/docker-cleanup.sh >> /var/log/docker-cleanup.log 2>&1
方案二:限制容器日志大小
修改 /etc/docker/daemon.json,限制单个容器日志文件最大 100MB,保留 3 个文件:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
改完重启 Docker:
$ sudo systemctl restart docker
这个配置只对新建的容器生效。已有容器需要重建才会应用新的日志限制。
方案三:CI 流水线构建后自动清理
在 CI pipeline 的最后加一步清理:
# GitLab CI 示例
after_script:
- docker image prune -f
- docker builder prune -f --filter "until=1h"
# GitHub Actions 示例
- name: Cleanup Docker
if: always()
run: |
docker image prune -f
docker builder prune -f --filter "until=1h"
三种方案对比
方案 | 效果 | 适用场景 | 风险 |
|---|---|---|---|
定时清理脚本 | 稳定保持磁盘可用 | 所有 Docker 环境 | 低 |
日志大小限制 | 防止日志无限增长 | 长期运行的服务 | 低(需重建容器生效) |
CI 后清理 | 每次构建后即时清理 | CI/CD 环境 | 低 |
三个方案建议同时用,基本能彻底解决 Docker 磁盘爆炸的问题。
十一、环境与版本
组件 | 版本 | 说明 |
|---|---|---|
Docker Engine | 26.1.4 | |
BuildKit | 内置(26.x) | 构建缓存管理依赖 BuildKit |
操作系统 | Ubuntu 24.04 LTS | — |
存储驱动 | overlay2 | 默认推荐驱动 |
本文命令在 Docker 20.10+ 上均适用。docker builder prune 从 Docker 23.0 开始默认使用 BuildKit,低版本可能需要手动启用。
如果这篇文章帮你清理了磁盘空间,点个赞让更多被 Docker 磁盘问题困扰的人看到。有其他清理技巧欢迎评论区补充。
更多推荐


所有评论(0)