要释放docker私有仓库磁盘空间,须完成“删除引用→停服回收→验证释放”闭环:启用delete功能、按digest删manifest、停服后执行gc并验证。

要让 Docker 私有镜像仓库真正释放磁盘空间,光删标签没用,必须打通“删除引用 → 停服回收 → 验证释放”这个闭环。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 操作才安全:
- 先用
HEAD请求获取响应头中的Docker-Content-Digest - 按策略筛选 digest:例如保留最近 3 个
dev-开头的,或按时间戳排序后删掉旧的 - 调用 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),结束时删除;多个清理任务同时跑可互斥 - 引用检查:GC 前确认该 digest 不再被任何 tag 引用(可通过
regctl repo list+regctl manifest ls辅助判断) - 日志增强:加
--debug参数输出详细过程,便于定位残留 blob 原因 - 同步清理未打标 manifest(推荐加
--delete-untagged参数)











