Docker镜像瘦身自动化脚本减少存储占用的完整实践

关于 Docker 镜像瘦身自动化脚本,核心思路是定期执行清理悬空镜像、无用构建缓存、停止容器日志和残留数据卷,从而减少存储占用。
适合磁盘告警、频繁构建镜像或长期运行容器的服务器,按本文步骤配置后,可一键查看当前占用并自动清理,避免手动操作遗漏。

先确认你的服务器是否需要清理

执行 df -h 查看磁盘使用率,如果 //var/lib/docker 所在分区使用率超过 80%,建议继续操作。
再执行 docker system df,可以看到镜像、容器、卷、构建缓存分别占用多少空间。

df -h
docker system df

如果 docker system df 输出中 Build CacheImages 占比较高,说明你确实需要镜像瘦身和缓存清理。

编写第一个自动化清理脚本

/usr/local/bin 下创建脚本文件,例如 docker-cleanup.sh

sudo vim /usr/local/bin/docker-cleanup.sh

写入以下内容:

#!/bin/bash
# Docker 存储占用清理脚本
# 适用于 Ubuntu / Debian / CentOS,使用前请先在测试环境验证

echo "===== 清理前磁盘占用 ====="
df -h / | grep -E 'Filesystem|/$'
docker system df

# 删除所有停止的容器
docker container prune -f

# 删除未被任何容器使用的悬空镜像(dangling images)
docker image prune -f

# 删除未被使用的镜像(谨慎:如果有多套环境,建议先手动确认)
docker image prune -a -f

# 清理构建缓存
docker builder prune -f

# 清理无用数据卷
docker volume prune -f

echo "===== 清理后磁盘占用 ====="
df -h / | grep -E 'Filesystem|/$'
docker system df

保存后赋予执行权限:

sudo chmod +x /usr/local/bin/docker-cleanup.sh

执行脚本:

sudo /usr/local/bin/docker-cleanup.sh

如果希望不中断服务自动运行,可以将 docker container prune -f 替换为更保守的写法,只删除停止超过 24 小时的容器:

docker container prune -f --filter "until=24h"

将脚本加入定时任务实现自动化

使用 crontab 实现每周自动清理。
执行 crontab -e,加入一行:

0 3 * * 0 /usr/local/bin/docker-cleanup.sh >> /var/log/docker-cleanup.log 2>&1

表示每周日凌晨 3 点执行脚本,并把日志输出到 /var/log/docker-cleanup.log
保存后,通过 crontab -l 确认任务已存在。

如果担心误删正在使用的镜像,可以先用 docker ps -a 检查容器状态,再决定是否启用 docker image prune -a

避坑指南和注意事项

1. 不要盲目使用 docker image prune -a

-a 参数会删除所有未被容器使用的镜像,如果后续需要回滚到旧版本镜像,可能无法恢复。
建议只在磁盘告急时使用,平时只清理悬空镜像即可。

2. 数据卷清理要谨慎

docker volume prune -f 会删除未被任何容器挂载的卷。
如果容器已停止,但卷里存有数据库文件,执行后数据会丢失。
建议先执行 docker volume ls 查看卷列表,再用 docker volume inspect 确认归属。

3. 日志文件占用也要处理

容器日志默认存储在 /var/lib/docker/containers/*/*-json.log,长期运行容易堆积十几个 GB。
可以设置日志轮转,编辑 /etc/docker/daemon.json

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  }
}

修改后重启 Docker:

sudo systemctl restart docker

重启后新容器才会生效,已存在的需要重建容器。

4. 镜像构建时主动瘦身

编写 Dockerfile 时,尽量使用多阶段构建,只复制最终产物,避免把编译工具和临时依赖留在镜像里。
例如:

FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o app .

FROM alpine:3.20
COPY --from=builder /app/app /usr/local/bin/app
CMD ["app"]

这样最终镜像只包含可执行文件,体积可以从数百 MB 降到几十 MB,从源头减少存储占用。

效果验证与日常观察

脚本执行后,重点看两个指标:docker system df 中 IMAGES 和 BUILD CACHE 的 TOTAL 与 RECLAIMABLE 变化,以及 df -h 中磁盘可用空间是否增加。
如果清理前后差别不大,说明占空间的大头是日志或数据卷,需要继续排查。

也可以使用以下命令定位大文件:

sudo du -sh /var/lib/docker/* | sort -rh

根据输出判断是 overlay2(镜像层)、containers(容器日志)还是 volumes(数据卷)占空间最大,再针对性清理。

高频问题解答

清理镜像会影响运行中的容器吗?

不会。
正在使用的容器所依赖的镜像不会被认为是悬空镜像,docker image prune 默认不会删除被容器引用的镜像。
docker image prune -a 会删除未被容器使用的所有镜像,如果你需要保留旧版本,就加上排除条件或手动确认。

清理后磁盘空间没有明显增加,为什么?

可能原因有两个:一是 docker 的日志文件未清理,二是删除了镜像但磁盘块尚未释放。
尝试重启 docker 守护进程:sudo systemctl restart docker,重启后会发现空间释放更多。
如果重启不现实,可以用下面的命令清理容器日志。

自动化脚本会不会误删数据库数据?

如果数据库数据存放在数据卷中,而数据库容器已经停止,docker volume prune 会删除这个卷。
因此脚本里可以删除 docker volume prune -f,改为手动定期执行。
数据库容器请务必设置持久化挂载,不要把数据放在容器可写层。

是否有更安全的清理策略?

建议分成三类:日常清理、周度清理、月度深度清理。
日常只清理悬空镜像和构建缓存,周度增加停止容器清理,月度再考虑删除未使用镜像和卷。
脚本中可以通过 --filter "until=72h" 等参数控制清理范围,避免误删近 3 天刚创建的资源。

如果你使用的是带控制面板的云服务器,比如通过面板的 Docker 管理功能查看镜像列表,清理时同样要注意容器状态和卷挂载关系。
对于生产环境,建议先在一台测试机跑通脚本,再用同样的参数部署到正式服务器。
若服务器空间长期紧张,也建议评估当前云服务器配置是否需要升级,但将镜像瘦身和日志轮转做好,通常会大幅缓解存储压力。

最后提醒一点:任何自动化脚本都可能有意外情况,建议在第一次使用前手动执行每一条命令,确认输出符合预期后再加入 crontab。
配置完成后可以观察两周,根据日志调整清理频率和过滤条件。

分享到:
上一篇
Nginx静态资源合并压缩节省海外带宽
下一篇
规范配置robots.txt允许搜索引擎抓取全站实操指南
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意