docker-cleanup源码解析:run.sh如何安全清理已退出容器与无用镜像

📅 2026/8/22 14:10:30
docker-cleanup源码解析:run.sh如何安全清理已退出容器与无用镜像
docker-cleanup源码解析run.sh如何安全清理已退出容器与无用镜像【免费下载链接】docker-cleanupDEPRECATED Automatic Docker image, container and volume cleanup项目地址: https://gitcode.com/gh_mirrors/do/docker-cleanupDocker 清理工具 docker-cleanup 是一个自动化的 Docker 维护脚本它会周期性删除已退出容器、无用镜像和孤儿数据卷防止磁盘被越撑越大。本文带你读懂它的核心脚本 run.sh看它是如何在删得干净和删得安全之间取得平衡的。为什么需要 Docker 容器与镜像自动清理平时我们docker run一个容器退出后它并不会消失而是以exited状态留在磁盘上构建镜像时不断覆盖旧版本又会留下大量none无标签镜像。CI 构建机、Jenkins 构建节点容器频繁启停几天就能堆满磁盘K8s / 集群节点Pod 调度换来换去旧镜像版本越积越多开发机数据卷、created卡住的容器悄悄占用空间手动执行docker system prune费时费力docker-cleanup 就是把这件事变成周期性自动执行并且通过白名单机制让你放心地让它跑在后台。⚠️ 小提醒该项目已标记为 DEPRECATED不再活跃维护但脚本逻辑简单透明非常适合学习 Docker 运维脚本的写法也仍可自托管使用。项目结构一览 项目非常精简核心就两个脚本 一份构建配置run.sh—主清理脚本负责清理容器、镜像、数据卷本文主角docker-cleanup-volumes.sh— 清理孤儿数据卷的辅助脚本支持--dry-run预演模式Dockerfile— 基于 alpine 镜像打包内置 docker 客户端入口即run.shMakefile— 开发用快捷命令build / run / restart 等contrib/k8s-daemonset.yml— Kubernetes DaemonSet 部署清单让每个节点都自动清理env.list— 环境变量示例CLEAN_PERIOD、DELAY_TIME、LOOPrun.sh 工作流程全解析 整个脚本可以概括为检查环境 → 清数据卷 → 清容器 → 算镜像差集 → 缓冲等待 → 再确认 → 删镜像这样一个循环。下面按源码顺序拆解每一步。1️⃣ 启动前的两道安全检查脚本开头run.sh第 18~29 行附近先确认两件事/var/run/docker.sock是否存在 —— 没有 Docker Socket 就没法操作主机上的 Dockerdocker version能否正常执行 —— 验证 docker 客户端挂载是否正确任何一项不满足就直接报错退出。这是安全的第一层宁可不动手也不带病运行。2️⃣ 环境变量与默认值Dockerfile中所有配置项默认值都是**None**脚本启动时会把它们翻译成真实默认值环境变量默认值作用CLEAN_PERIOD1800 秒每轮清理结束后的间隔时间DELAY_TIME1800 秒清理前等待缓冲的时间KEEP_IMAGES空镜像白名单前缀通配逗号分隔KEEP_CONTAINERS空按镜像名保留容器KEEP_CONTAINERS_NAMED空按容器名保留容器LOOPtrue是否循环运行设false只跑一次DEBUG0设为 1 输出白名单匹配详情白名单用的是shell 前缀通配而不是正则写foo/bar就能匹配foo/bar:tag、foo/bar:latest等所有标签非常省心。3️⃣ 清理已退出/死亡容器核心逻辑脚本用docker ps -a -q -f statusexited -f statusdead捞出所有已退出和死亡容器的 ID然后对每一个容器做白名单检查取出该容器的镜像名和容器名分别用checkPatterns函数与KEEP_CONTAINERS、KEEP_CONTAINERS_NAMED做前缀匹配只要命中任一白名单 → 跳过都没命中 → 执行docker rm -v连容器带匿名卷一起删除这里的checkPatterns函数run.sh开头定义就是整个安全删除的关键先匹配、再动手逐个决策绝不批量盲删。4️⃣ 用差集安全删除无用镜像 ️这是全脚本最精巧的部分思路是经典的集合差集列出所有镜像 ID存成ImageIdList遍历所有容器包括已退出的用docker inspect提取每个容器实际使用的镜像 ID存成ContainerImageIdList用comm -23求差集 → 得到不被任何容器引用的镜像即待删列表若设置了KEEP_IMAGES再和白名单镜像 ID求一次差集把受保护的镜像剔除安全点在于判断依据是有没有容器在用而不是镜像名字好不好看所以正在使用的镜像无论如何都不会被误删。5️⃣ DELAY_TIME 缓冲 二次确认算出待删镜像后脚本不会立刻删而是先sleep ${DELAY_TIME}默认 30 分钟。等待期间会处理另一类卡住的容器那些状态停留在created创建了但一直没启动成功且持续未启动的容器会被清理掉。缓冲结束后脚本会重新拉取一遍容器正在使用的镜像 ID与待删列表再做一次comm过滤然后才执行docker rmi。为什么要做两次因为等待窗口内可能有新容器拉起了镜像比如刚拉完镜像还没启动。二次确认能防止算差集时没人用、删除时正要用的竞态误删。6️⃣ 数据卷清理的版本自适应 数据卷清理策略会因 Docker 版本不同而自动切换新版 Docker直接使用原生命令只删除danglingtrue未被引用的卷老版 Docker1.x/早期 2.x调用辅助脚本docker-cleanup-volumes.sh它通过解析/var/lib/docker/volumes目录、比对所有容器挂载的卷 ID来找出真正无主的孤儿卷辅助脚本还支持--dry-run只显示会删什么不真删和--verbose在陌生环境里先预演一遍是好习惯。7️⃣ 优雅退出与循环脚本注册了SIGINT/SIGTERM的 trap收到信号会打印提示并干净退出不会留下半成品状态每轮结束后sleep ${CLEAN_PERIOD}然后进入下一轮LOOPfalse时跑完一轮即退出适合配合 crontab 使用它安全在哪里总结 4 道防线 ✅启动自检Socket 和 docker 客户端任一异常就拒绝运行白名单机制镜像名、容器名双维度保护前缀通配好写好用差集判定 二次确认只删确实无容器引用的镜像且删除前再核对一次时间缓冲DELAY_TIME 给正在拉取/启动的容器留出窗口避免竞态误删快速上手3 种部署方式 方式一命令行直接跑docker run \ -v /var/run/docker.sock:/var/run/docker.sock:rw \ -v /var/lib/docker:/var/lib/docker:rw \ meltwater/docker-cleanup:latest方式二Makefile 快捷命令仓库自带Makefile执行make run即可按env.list中的配置启动清理容器。方式三Kubernetes DaemonSet仓库提供了contrib/k8s-daemonset.yml执行kubectl create -f contrib/k8s-daemonset.yml就能让集群每个节点都跑一个清理实例天然适配集群场景。建议先用DEBUG1LOOPfalse跑一轮观察日志里的匹配明细确认白名单行为符合预期后再放开循环运行。注意事项 ⚠️挂载/var/lib/docker后脚本会直接操作宿主机存储官方 README 明确警告在不兼容的 Docker 版本上极端情况可能删除运行中容器的数据卷生产环境请谨慎KEEP_CONTAINERS/KEEP_CONTAINERS_NAMED设成**All**表示全部保留内部会转换成通配符.想保留全部镜像请用*:*不要用裸*会被当成文件名匹配项目已停止维护若用于生产建议结合官方推荐的docker system prune Docker 内置 image GC 策略做对照验证总结 docker-cleanup 的 run.sh 虽然只有 200 多行 bash却示范了一套教科书级的安全自动化清理套路启动自检、白名单、差集判定、时间缓冲、二次确认、优雅退出。理解这套设计后无论是自托管使用还是参考它编写自己的容器运维脚本都能少走很多弯路。对于容器频繁启停的构建机和集群节点这类自动清理工具是守住磁盘空间的第一道防线。【免费下载链接】docker-cleanupDEPRECATED Automatic Docker image, container and volume cleanup项目地址: https://gitcode.com/gh_mirrors/do/docker-cleanup创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考