docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > Docker垃圾回收清理后端存储空间

Docker镜像仓库的垃圾回收机制深度清理后端存储空间的实现

作者:冷漠man

本文主要介绍了Docker镜像仓库的垃圾回收机制深度清理后端存储空间的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Docker 镜像仓库的垃圾回收(Garbage Collection, GC)机制是管理后端存储空间的核心手段。其本质是通过标记-清除(Mark and Sweep)算法,识别并删除不再被任何镜像清单(Manifest)引用的 Blob(镜像层和配置对象),从而真正释放磁盘空间。

一、GC 的核心原理:标记-清除两阶段

1. Marking 阶段(标记)

GC 扫描所有仓库(repositories)下的 tags 目录,读取 link 文件获取 manifest 摘要(digest)。随后遍历每个 manifest,提取其中引用的所有 layer 和 config 文件的 digest,将这些 Blob 标记为"存活"(不可删除)

2. Sweep 阶段(清除)

遍历整个 blobs 目录下的所有 Blob。若某个 Blob 的 digest 不在标记集合中,则将其加入删除集合并执行物理删除。

流程示意:
开始 GC → 扫描所有 Manifest → 标记引用的 Blobs → 遍历所有 Blobs
                                      ↓
                              是否被标记?
                         是 → 保留      否 → 删除

二、为什么必须手动/定时触发 GC?

Docker Registry 的设计遵循内容寻址存储(CAS)原则,多个镜像标签可能共享相同的底层 layer。因此:

三、执行 GC 的标准操作

前置条件

Registry 配置必须开启删除功能:

storage:
  delete:
    enabled: true

基础 GC 命令

# 进入 Registry 容器执行
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
# 同时清理未被任何标签引用的 manifest(推荐)
docker exec registry bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml
# 仅模拟运行,不实际删除(用于验证)
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml

安全实践:只读模式下运行

GC 期间必须禁止写入,否则可能导致数据竞争和损坏:

#!/bin/bash
# 将 Registry 切换为只读模式
docker exec registry sh -c 'sed -i "s/readonly: false/readonly: true/" /etc/docker/registry/config.yml && kill -HUP 1'
sleep 5
# 执行 GC
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml --delete-untagged
# 恢复写入
docker exec registry sh -c 'sed -i "s/readonly: true/readonly: false/" /etc/docker/registry/config.yml && kill -HUP 1'

四、深度清理:处理顽固空间占用

场景 1:手动删除仓库后 GC 效果不佳

如果直接删除了 repositories 目录下的命名空间,但 GC 释放空间很少,原因是:

只要 repositories 目录中的名称空间存在,其下的 blob 文件就不会被回收。

解决方案

# 1. 先删除 repositories 中的元数据目录
cd /var/lib/registry/docker/registry/v2/repositories && rm -rf <namespace>
# 2. 再执行 GC
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

场景 2:清理过期的 Tags 和 Revisions

对于长期运行的 Registry,可以定期清理旧的 tag 和 manifest revision:

# 删除 14 天未更新的 tag 目录
find /var/lib/registry/docker/registry/v2/repositories/*/_manifests/tags/* \
  -type d -mtime +14 -maxdepth 1 -exec rm -rf {} \;
# 删除 14 天前的未引用 manifest revision
find /var/lib/registry/docker/registry/v2/repositories/*/_manifests/revisions/sha256/* \
  -type d -mtime +14 -maxdepth 1 -exec rm -rf {} \;
# 最后执行 GC
docker exec registry bin/registry garbage-collect -m /etc/docker/registry/config.yml

场景 3:清理空目录

GC 后可能残留空目录,占用 inode:

# 删除 blobs/sha256 下的空目录
for dir in $(find /var/lib/registry/docker/registry/v2/blobs/sha256/ -type d -empty); do
    rm -rf "$dir"
done

五、企业级方案:Harbor 的自动 GC

对于生产环境,建议使用 Harbor 替代原生 Registry。Harbor 提供:

六、定时自动化脚本示例

#!/bin/bash
# /opt/registry/registry-cleanup.sh
REGISTRY_CONTAINER="registry"
REGISTRY_HOME="/var/lib/registry/docker/registry/v2"
LOG="/var/log/registry-cleanup.log"
echo "[$(date)] Starting cleanup..." >> $LOG
# 1. 清理过期 tags(>30 天)
find ${REGISTRY_HOME}/repositories/*/_manifests/tags/* \
  -type d -mtime +30 -maxdepth 1 -exec rm -rf {} \; 2>/dev/null
# 2. 清理过期 revisions
find ${REGISTRY_HOME}/repositories/*/_manifests/revisions/sha256/* \
  -type d -mtime +30 -maxdepth 1 -exec rm -rf {} \; 2>/dev/null
# 3. 切换只读模式
docker exec $REGISTRY_CONTAINER sh -c \
  'sed -i "s/readonly: false/readonly: true/" /etc/docker/registry/config.yml && kill -HUP 1'
sleep 5
# 4. 执行 GC
docker exec $REGISTRY_CONTAINER bin/registry garbage-collect \
  --delete-untagged /etc/docker/registry/config.yml >> $LOG 2>&1
# 5. 恢复写入
docker exec $REGISTRY_CONTAINER sh -c \
  'sed -i "s/readonly: true/readonly: false/" /etc/docker/registry/config.yml && kill -HUP 1'
# 6. 清理空目录
find ${REGISTRY_HOME}/blobs/sha256/ -type d -empty -delete 2>/dev/null
echo "[$(date)] Cleanup completed." >> $LOG

Crontab 配置(每月 1 日和 15 日凌晨 2:30 执行):

30 2 1,15 * * /opt/registry/registry-cleanup.sh

七、关键注意事项

风险点说明
必须只读运行GC 期间任何 push 操作都可能导致数据损坏
先 dry-run首次清理前使用 --dry-run 预览删除内容
共享 layer 保护GC 不会删除仍被引用的 blob,这是正常行为
大仓库性能超大规模 Registry 的 GC 可能耗时数小时,可考虑增量 GC 方案
备份优先执行前备份 /var/lib/registry 目录,防止误删

通过理解 Registry 的引用计数机制,并结合定期清理 tags、revisions 与 GC 的完整流程,可以有效控制后端存储空间的持续增长。

到此这篇关于Docker镜像仓库的垃圾回收机制深度清理后端存储空间的实现的文章就介绍到这了,更多相关Docker垃圾回收清理后端存储空间内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文