Docker私有镜像仓库自动清理需闭环执行四步:一启用删除功能(config.yml设delete.enabled:true或环境变量);二按digest删除manifest(非tag,用HEAD提取Docker-Content-Digest);三停服后执行garbage-collect(--dry-run预览+sync同步);四生产加固(加锁、引用检查、--debug日志)。

要让 Docker 私有镜像仓库(registry)真正自动清理空间,不能只靠“开启 GC”这一步,必须把删除引用、停服回收、验证释放三个环节串成闭环。GC 本身不识别标签、不按时间删旧镜像,它只清理那些已被 API 明确删除、但底层 blob 还残留的文件。
第一步:启用 registry 的删除功能
默认 registry 是禁止删除操作的,不打开就无法触发后续任何清理:
- 修改 config.yml 的
storage段,添加:delete:<br> enabled: true
- 或用环境变量方式(K8s/Compose 更推荐):
REGISTRY_STORAGE_DELETE_ENABLED=true - 配置后必须重启 registry 容器,并确认无写入中
- 验证是否生效:执行
curl -X DELETE http://reg/v2/myrepo/manifests/sha256:abc123,返回202表示成功;405则说明未启用
第二步:按 digest 删除 manifest(GC 前提)
GC 只认 manifest digest,不认 tag 名。同一个 tag 可能被覆盖,必须按 digest 操作才安全:
- 对每个 tag 发送 HEAD 请求:
curl -I "http://reg/v2/myrepo/manifests/v1.2",提取响应头中的Docker-Content-Digest - 按策略筛选 digest:例如保留最近 3 个
dev-开头的,或按时间戳排序后删掉前 N 个 - 调用 DELETE 接口清理:
curl -X DELETE "http://reg/v2/myrepo/manifests/sha256:abc123" - 推荐用 regctl 简化操作:
regctl manifest delete myreg:5000/myrepo@sha256:abc123
第三步:停服执行垃圾回收并验证
GC 必须在 registry 完全无写入时运行,否则会跳过被引用的 blob,导致空间不释放:
- 先停 registry:
docker stop registry或kubectl scale deploy registry --replicas=0 - 预览回收效果(强烈建议):
docker exec registry /bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml - 确认无误后执行真实回收:
docker exec registry /bin/registry garbage-collect /etc/docker/registry/config.yml - 若磁盘空间没下降,检查 storage driver:
• filesystem 类型需额外执行sync;
• NFS 后端注意是否支持原子 rename
第四步:生产环境加固要点
避免误删和并发冲突,这几个细节不能省:
-
加锁机制:脚本开头创建临时锁文件(如
/tmp/registry-gc.lock),结束时删除;多个清理任务同时跑可互斥 -
引用检查:删除前用
regctl blob mount或查引用关系,确认该 digest 确实没被其他仓库复用 -
日志与调试:GC 命令加
--debug参数查看实际处理了哪些 blob,便于排查漏删或跳过原因


















