Docker容器镜像瘦身自动化脚本减少存储占用
为什么Docker镜像会越积越胖?
很多服务器运维新人会发现,随着开发迭代和镜像拉取,docker system df 显示的总占用越来越大。
那些 untagged 的中间层镜像、构建过程中残留的缓存,以及手动堆积的旧标签,都会悄无声息吃掉硬盘空间。
手动一条一条去删既麻烦又容易漏,所以用自动化脚本统一管理是最省时的做法。
准备工作:检查当前Docker存储状态
在动手写脚本之前,先确认一下你服务器的 Docker 存储占用情况。
执行下面两行命令,输出会告诉你镜像、容器、卷和构建缓存分别占了多少:
docker system df
# 如果想看更详细的每一层,可以加 -v 参数
docker system df -v
重点看 Images 一栏下的 Reclaimable(可回收)空间。
如果这个数字占了一半以上,说明清理潜力很大。
同时记录一下你正在使用的容器和镜像,避免误删正在运行的依赖。
编写自动化瘦身脚本
新建一个脚本文件,比如 docker-cleanup.sh:
#!/bin/bash
echo "========== 开始清理无用Docker镜像 =========="
# 步骤1:移除所有悬空镜像(dangling images)
echo "1. 清理悬空镜像(none标签镜像)..."
docker image prune -f
# 步骤2:清理没有被容器使用的镜像(谨慎使用,建议保留最近30天)
echo "2. 清理未被使用的镜像(保留最近30天)..."
docker image prune -a -f --filter "until=720h"
# 步骤3:清理构建缓存
echo "3. 清理构建缓存..."
docker builder prune -f
# 步骤4:移除已退出的容器
echo "4. 移除已退出的容器..."
docker container prune -f
# 步骤5:移除没有被使用的网络
echo "5. 移除未使用的网络..."
docker network prune -f
echo "========== 清理完成 =========="
# 显示清理后的存储状态
echo "当前存储占用:"
docker system df
关键参数解释:
-f:强制删除,不需要二次确认。--filter "until=720h":只保留最近30天(720小时)内使用过的镜像,更久的如果未被二次拉取或使用就清理掉。你可以根据需求调整时间。prune只删没有被任何容器引用的资源,不会动正在运行的容器。
运行脚本和定时执行
先给脚本执行权限并运行:
chmod +x docker-cleanup.sh
./docker-cleanup.sh
运行后观察控制台输出,确认没有报错。
你可以手动执行一次,看最终 docker system df 的 Reclaimable 是否大幅减少。
设置定时任务(推荐):每周自动跑一次。
使用 crontab -e 添加下面一行:
0 3 * * 0 /path/to/docker-cleanup.sh >> /var/log/docker-cleanup.log 2>&1
这样每周日凌晨3点自动运行,并记录日志方便排查。
避坑指南:这些镜像千万别乱删
- 正在被运行的容器使用的镜像:
docker image prune -a会删除所有未被任何容器引用的镜像。如果你有容器停掉但将来可能需要重新启动,记得先确认对应的镜像是否被其他容器依赖。建议保留常用基础镜像,比如nginx:latest、python:3.9等。 - 误删私有仓库镜像:如果你从私有仓库拉取的镜像,本地删了下次还能重新拉,但如果你自己 build 的镜像并且没推送到仓库,一旦删除就无法恢复。所以重点检查
REPOSITORY列为或本地 building 的镜像。 - 构建缓存清理后下次构建会变慢:
docker builder prune会清空构建缓存,下次docker build会重新下载层,增加构建时间。建议在确认发布版本稳定后再清理,或者只在磁盘告急时执行。
效果验证:如何确认瘦身成功?
运行脚本后,再次执行 docker system df,对比前后数据。
通常情况下,瘦身率能达到 30%~60%,尤其如果你的容器频繁更新、残留很多 镜像。
可以记录一下清理前后的 Images 列的大小。
常用检查命令:
# 查看所有镜像及其大小
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}"
# 查看悬空镜像(none标签)
docker images --filter dangling=true
如果脚本执行后 docker images 列表里不再有大量 镜像,
并且 docker system df 的 Reclaimable 接近 0,
就说明自动化清理已经生效。
常见问题解答
Q:脚本执行时报错“docker: permission denied”怎么办?
A:当前用户没有 Docker 权限。要么用 sudo 运行,要么把当前用户加入 docker 组:sudo usermod -aG docker $USER,然后重新登录。
Q:我想保留最近7天的镜像,怎么改?
A:把 --filter "until=720h" 改成 "until=168h"(7天×24小时)。
Q:执行 docker image prune -a 会删掉我拉取的 nginx 最新版本吗?
A:如果当前没有容器使用那个 nginx 镜像,它会被删除。下次再拉即可。如果你希望保留常用的基础镜像,可以在 prune 之前先 docker pull 一遍,或者手动设置豁免规则。
后续建议
如果你发现清理后 Disk 占用仍然很高,可以检查 /var/lib/docker/volumes 下的卷数据,以及日志文件。
配合监控工具(如 du、ncdu)定位大文件。
另外,建议在 Docker Compose 或构建流程中就提前规划好镜像标签管理,减少悬空层产生。
如果你正在处理 Docker 容器镜像瘦身自动化脚本减少存储占用的问题,建议先按本文的脚本完整跑一次,然后根据你的业务特点调整过滤时间和排除列表。
遇到异常时优先回看避坑和高频问题部分,可以有效避免误删重要镜像。