【问题标题】:Docker Registry 2.0 - how to delete unused images?Docker Registry 2.0 - 如何删除未使用的图像?
【发布时间】:2015-06-30 09:13:58
【问题描述】:

我们将私有 docker 注册表更新为官方 Registry 2.0。此版本现在可以删除由标签标识的 docker 图像(请参阅https://docs.docker.com/registry/spec/api/#deleting-an-image),但我仍然看不到清理旧图像的方法。

由于我们的 CI 服务器不断生成新图像,我需要一种方法来从私有注册表中删除不再由命名标记标识的所有图像。

如果没有内置方法来实现这一点,我认为自定义脚本可能会起作用,但我也没有看到 v2 API 方法来列出图像的所有存储主题标签。

如何保持我的私人注册表清洁?有什么提示吗?

【问题讨论】:

  • 其实情况比你想象的还要糟糕。该规范尚未实施;调用 DELETE 返回 400。见 github.com/docker/distribution/issues/422
  • 私有注册表还有很长的路要走
  • 未来的你好(4年后)——现在有什么好的方法来处理这个问题吗?这些选项似乎与此问题处于活动状态时的选项相同。

标签: docker docker-registry


【解决方案1】:

要删除未处理的图像,请按以下顺序手动执行三个步骤:

  1. docker rmi -f **imageid**

  2. rm -Rf /home/**homedirectory**/docker-registry/data/docker/registry/v2/repositories/**yoursystemname**/**yourimagename**/_manifests/tags/**image version**/

  3. docker exec $(docker ps -q) bin/registry garbage-collect /etc/docker/registry/config.yml -m

*注意:

** 您必须在测试环境中执行这些命令(如上),因为如果您犯了任何错误或没有理解任何步骤,您不会损坏您的生产环境。

** 您可以使用 crontab 作为 root 来安排这些命令(如上)。在步骤 3)中,您必须执行删除“-it”,结果:docker exec $(docker ps -q) bin/registry Garbage-collect /etc/docker/registry/config.yml -m`。

它对我有用超过 6 个月。

【讨论】:

    【解决方案2】:

    这是可行的,虽然很难看。您需要运行(我认为)注册表 2.3 或更高版本,并启用删除(REGISTRY_STORAGE_DELETE_ENABLED=True env var 或等效项)。下面的示例命令假定/srv/docker-registry 中有一个本地文件存储,但如果不能为其他存储后端制作等效的东西,我会感到惊讶。

    对于您希望整理的每个存储库,您需要枚举不再需要的摘要引用。最简单的方法是每个标签,在这种情况下使用latest 作为示例,您可以执行以下操作:

    ls -1tr /srv/docker-registry/v2/repositories/<repo>/_manifests/tags/latest/index/sha256 \
    | tail -n +3
    

    这将列出推送到latest 标记的三个最新摘要之外的所有摘要。或者,如果您不太关心 标签,而只想保留最后几个引用,您可以这样做:

    ls -1t /srv/docker-registry/v2/repositories/<repo>/_manifests/revisions/sha256 \
    | tail -n +3
    

    然后,您只需删除不需要的引用:

    for hash in $(ls -1t /srv/docker-registry/v2/repositories/<repo>/_manifests/tags/latest/index/sha256 | tail -n +3); do
      curl -X DELETE https://registry:5000/v2/<repo>/manifests/sha256:$hash
    done
    

    最后,你需要进行一次 GC 运行,因为注册表实现了“软删除”,它实际上并没有删除任何东西,它只是使它不可用:

    docker exec docker-registry /bin/registry \
      garbage-collect /path/to/config.yml
    

    是的,这一切都乱七八糟,在后端存储中徘徊,因为没有 API 方法可以枚举与给定标签关联的所有摘要,但这就是 cookie 崩溃的方式。

    【讨论】:

    • 小澄清:标志是REGISTRY_STORAGE_DELETE_ENABLED,而不是..._STORE_...。有关详细信息,请参阅docs.docker.com/registry/configuration/#/…
    • v2.6 中的目录结构是.../_manifest/tags/&lt;tag&gt;/index/...
    • @womble 它以某种方式删除了我的一张图片的标签 (latest)。此外,文件系统的状态似乎并不能反映事态。在删除不需要的清单并运行垃圾收集器后,我仍然可以在/srv/docker-registry/v2/repositories/&lt;repo&gt;/_manifests/tags/latest/index/sha256 看到至少一些应该消失的清单。
    • 自从我写下这个答案以来,事情发生了变化,这并不让我感到惊讶。我不再将 Docker 注册表用于我绝对不需要的任何事情。
    • 我不确定他们有没有改变。我可能只是幸运地遇到了它无法正常工作的情况。我的猜想是文件系统并不能完全反映事态。当您删除除最后一个修订版之外的所有修订版时,后者可能仅在磁盘上。所以你刚刚删除了所有的修订,标签也消失了。希望official solution 能做到我认为的那样。顺便说一句,你用什么?
    【解决方案3】:

    我在 docker 容器中托管 regestry,名称为 docker-registry_registry_1 来自 image: registry:2

    我只是运行garbage-collect-m

    docker exec docker-registry_registry_1 bin/registry garbage-collect /etc/docker/registry/config.yml -m
    

    【讨论】:

    • 谢谢!像魅力一样工作!
    • 这太棒了!
    【解决方案4】:

    关于你的问题:

    我需要一种方法来从私有注册表中删除不再由命名标签标识的所有图像

    distribution/registry:master 中的新版本 docker 注册表具有这个不错的功能!但是,您将无法从 API 触发它

    无论如何,您将能够清除注册表中所有未标记的清单,这意味着每个被覆盖的标记不会在注册表中留下旧的清单和 blob。 Registry Garbage Collectior 将清理每个“未使用”层。

    你只需要运行docker exec:

    docker exec ${container_id} registry garbage-collect \ 
      /path/to/your/registry/config.yml \
      --delete-untagged=true
    

    查看此垃圾收集二进制帮助:

    Usage: 
      registry garbage-collect <config> [flags]
    Flags:
      -m, --delete-untagged=false: delete manifests that are not currently referenced via tag
      -d, --dry-run=false: do everything except remove the blobs
      -h, --help=false: help for garbage-collect
    

    您可以查看github PR。截至 2018 年 2 月 23 日,它已与 distribution/registry、标签 master 合并并可使用。它取代了docker/docker-registry 具有新 API 设计的项目,专注于安全性和性能...

    我今天确实使用了此功能并恢复了 89% 的注册表空间(5.7 GB 与 55 GB)。然后我切换回稳定的registry

    【讨论】:

    • PR的改动应该在官方imagenow.
    • 现在这应该是公认的答案。它完全符合要求。如果有人正在运行一个私人仓库,唯一需要做的就是拉新镜像docker pull registry:2,停止容器docker-compose stop registry,删除它docker-compose rm registry并重新创建它docker-compose up -d registry。如果您使用 docker-compose 并在带有 docker-compose.yml 的目录中执行并且您的容器名称为 registry :),则上述方法将起作用
    • 垃圾收集器现在在 Docker Registry v2.7+ 中,所以任何新安装的 Docker Registry 都应该有它。
    • 这是一个很好的答案。但是我不知道我的“注册表文件”在哪里或是什么。我通过执行docker exec -it &lt;docker-registry-container-name&gt; /bin/sh 找到了它的位置,然后执行了find / -iname "*.yml",它发现了文件的位置。
    【解决方案5】:

    我拼凑了这个线程的各个部分,并在 bash 中创建了一个易于使用的清理脚本 您可以在此要点中查看它cleanup.sh

    【讨论】:

    • 感谢您的脚本。这对我进行了一些修改:1)for hash in 循环假定 repo 名称是单个字符串,而我的名称为 project/repo,因此我必须添加另一个内部循环来导航额外的文件夹级别。 2) 使用-u usr:pwd 向 curl 命令添加身份验证。 3) 将REGISTRY_STORAGE_DELETE_ENABLED=true 添加到用于运行注册表的环境变量中。
    • @foz 最好使用-n, --netrc 选项代替-u
    【解决方案6】:

    删除图像(您可以保留 10 个最新版本,就像我在 CI 中所做的那样)分三个步骤完成:

    1. 通过设置环境变量REGISTRY_STORAGE_DELETE_ENABLED: "true"并将其传递给docker-registry来启用图像删除

    2. 在脚本下方运行(它将删除所有图像和标签,但保留最近 10 个版本)

      registry.py -l user:pass -r https://example.com:5000 --delete --num 10

    3. 运行垃圾回收(你可以把它放到你的日常 cron 任务中)

      docker-compose -f [path_to_your_docker_compose_file] 运行注册表 bin/registry 垃圾收集 /etc/docker/registry/config.yml

    registry.py 可以从下面的链接下载,它还允许列出图像、标签和层,以及删除特定的图像和/或标签。

    https://github.com/andrey-pohilko/registry-cli

    在垃圾收集之前,我的注册表文件夹为 7 Gb,在我运行上述步骤后,它缩小到 1 Gb。

    【讨论】:

    • 这个解决方案的问题是它不能处理......未标记的修订(?)。那些你推送到注册表而不指定标签的人。 @anoxis 你能确认一下吗?我可以通过删除 those 来释放 120 Gb。但是有一些问题,我将对该答案添加评论。
    • @x-yuri 可能你是对的。我的脚本并不打算清理所有修订,就像您使用的解决方案一样。该脚本的已知问题是它无法从注册表中删除整个图像。但是,如您所见,最初的问题是关于如何从 CI 服务器中清除旧标签,而不是所有修订版或所有 repos。所以,这两种解决方案都很好,它们只是用于不同的目的。
    • 我不想删除所有修订版(这基本上会删除一个标签),更不用说所有存储库。您的脚本基本上通过删除标签本身来删除标签的所有修订。而且我绝不会试图贬低您的答案。我只是添加有关我的案例的详细信息。据我所知,registry.py 使用了 api(/v2/_catalog 代表 repositories
    • .../v2/REPO/tags/list for tags)。但问题是,每个标签通常都有不止一个修订版。可以在/var/lib/docker/volumes/registry/_data/docker/registry/v2/repositories/REPO/_manifests/tags/TAG/index 看到那些。并且可以使用DELETE /v2/REPO/manifests/sha256:HASH 删除。
    • ...但是文件系统似乎并不能准确地反映事务的状态,这可能会让您删除标签,而不仅仅是标签的旧修订版(您删除所有修订版,但最后一个,但最后一个仅存在于磁盘上)。至少,这是迄今为止我所遇到的问题的最佳解释。希望official solution 能做到我认为的那样。
    【解决方案7】:

    我在注册表 v2 api 中寻找相同的功能,但只找到了 soft deleting,这不是我想要的。在研究过程中,我发现了 Github 项目 delete-docker-registry-image,它通过 bash 脚本从挂载的卷中删除了实际文件。未测试它可能有用...

    【讨论】:

    • 它似乎在起作用(在我的环境中 :) 我必须创建一个符号链接 'ln -s /var/lib/docker/volumes/c49189f29d8bd93f644438dee774685790687a67c576eb1349cbfe218e14fc20/_data /opt/registry_data' 作为在容器中运行我的注册表,神秘的字符串是容器的挂载(由命令 docker inspect --format '{{range .Mounts}}{{.Name}}{{end}}' )
    【解决方案8】:

    对此进行了一些讨论 - 目前,没有层清理工具/端点。

    我会鼓励你去:

    和/或在#docker-distribution 上联系 Freenode IRC 了解更多信息。

    【讨论】:

    • 假设我们每天在 CI 服务器中烧录超过 50Gb 的磁盘空间,您建议的解决方案是什么?那个 IRC 频道在我看来也很安静 :)
    • 简而言之,这里有一些建议:如果这是“可扔”的内容,您可以不时清除整个存储空间。如果这不可接受,那么每天 50GB 可以在三个月内达到 5T - 也许一些便宜的存储解决方案可以解决?另外,我希望在接下来的几个月内会有一个真正的解决方案。很抱歉没有马上找到更好的解决方案...
    • @MangledDeutz 有这方面的消息吗?现在已经几个月了..谢谢!
    • @yorch 现在有一个待定的 PR 来正式支持 GC:github.com/docker/distribution/pull/1386 - 还有社区维护的解决方案。干杯。
    • @MangledDeutz 好消息!谢谢,我希望它可以尽快合并回来
    猜你喜欢
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 2017-04-18
    • 2015-07-21
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多