
目录一、问题现象服务器磁盘突然 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 GB22.3 GBContainers所有容器的可写层1.2 GB890 MBLocal Volumes本地数据卷3.8 GB2.1 GBBuild Cache构建缓存34.2 GB34.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 until24h # 只清理未被使用的缓存 $ docker builder prune --filter unused-for24h--filter until24h是比较推荐的方式——保留最近 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 until24h # 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 GB2 秒构建缓存24h 前28.7 GB5 秒停止的容器890 MB1 秒未使用的数据卷2.1 GB1 秒合计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 until24h # 清理 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 21方案二限制容器日志大小修改/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 until1h # GitHub Actions 示例 - name: Cleanup Docker if: always() run: | docker image prune -f docker builder prune -f --filter until1h三种方案对比方案效果适用场景风险定时清理脚本稳定保持磁盘可用所有 Docker 环境低日志大小限制防止日志无限增长长期运行的服务低需重建容器生效CI 后清理每次构建后即时清理CI/CD 环境低三个方案建议同时用基本能彻底解决 Docker 磁盘爆炸的问题。十一、环境与版本组件版本说明Docker Engine26.1.4docker system df从 17.04 开始支持BuildKit内置26.x构建缓存管理依赖 BuildKit操作系统Ubuntu 24.04 LTS—存储驱动overlay2默认推荐驱动本文命令在 Docker 20.10 上均适用。docker builder prune从 Docker 23.0 开始默认使用 BuildKit低版本可能需要手动启用。如果这篇文章帮你清理了磁盘空间点个赞让更多被 Docker 磁盘问题困扰的人看到。有其他清理技巧欢迎评论区补充。