it-swarm.asia

如何从私人码头注册表中删除图像?

我运行一个私有的docker注册表,我想从存储库中删除除latest之外的所有图像。我不想删除整个存储库,只删除其中的一些图像。 API文档 没有提到这样做的方法,但肯定有可能吗?

116
Leo

目前,您无法使用Registry API执行该任务。它只允许您删除存储库或特定标记。

通常,删除存储库意味着删除与此存储库关联的所有标记。

删除标记意味着删除图像和标记之间的关联。

以上都不会删除单个图像。它们留在磁盘上。


Workaround

对于此变通方法,您需要在本地存储docker镜像。

解决方案的解决方法是删除除最新标记之外的所有标记,从而可能删除对相关图像的引用。然后你可以运行这个脚本来删除任何标签或任何使用过的图像的祖先都没有引用的所有图像。

术语(图像和标签)

考虑这样的图像图形,其中大写字母(AB,...)表示短图像ID,<-表示图像基于另一个图像:

 A <- B <- C <- D

现在我们为图片添加标签:

 A <- B <- C <- D
           |    |
           |    <version2>
           <version1>

这里,标签<version1>引用图像C,标签<version2>引用图像D

提炼你的问题

在你的问题中,你说你想删除

所有图像,但latest

。现在,这个术语不太正确。你混合了图像和标签。查看图表我认为你会同意标签<version2>代表最新版本。事实上,根据 这个问题 你可以有一个代表最新版本的标签:

 A <- B <- C <- D
           |    |
           |    <version2>
           |    <latest>
           <version1>

由于<latest>标记引用了image D,我问你:你真的要删除除image D以外的所有内容吗?可能不是!

删除标签会发生什么?

如果使用Docker REST AP​​I删除标签<version1>,您将得到:

 A <- B <- C <- D
                |
                <version2>
                <latest>

请记住: Docker永远不会删除图像!即使它确实如此,在这种情况下它也无法删除图像,因为图像C是标记的图像D的祖先的一部分。

即使你使用这个脚本,也不会删除任何图像。

当图像可以删除

在您可以控制何时可以拉动或推送到您的注册表的情况下(例如,通过禁用REST接口)。如果没有其他图像基于图像并且没有标记引用图像,则可以从图像图形中删除图像。

请注意,在下图中,图像D not 基于C但在B上。因此,D不依赖于C。如果在此图中删除标记<version1>,则图像C将不会被任何图像使用,并且此脚本可以删除它。

 A <- B <--------- D
      \            |
       \           <version2>
        \          <latest>
         \ <- C
              |
              <version1>

清理后,您的图像图形如下所示:

 A <- B <- D
           |
           <version2>
           <latest>

这是你想要的吗?

89
Konrad Kleine

我的注册表遇到了同样的问题,然后我从博客页面尝试了下面列出的解决方案。有用。

第1步:列出目录

您可以通过调用此网址列出您的目录:

http://YourPrivateRegistyIP:5000/v2/_catalog

回复将采用以下格式:

{
  "repositories": [
    <name>,
    ...
  ]
}

第2步:列出相关目录的标签

您可以通过调用此网址列出目录的标记:

http://YourPrivateRegistyIP:5000/v2/<name>/tags/list

回复将采用以下格式:

{
"name": <name>,
"tags": [
    <tag>,
    ...
]

}

第3步:列出相关标签的清单值

您可以在docker注册表容器中运行此命令:

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost:5000/v2/<name>/manifests/<tag> 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'

回复将采用以下格式:

sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

使用清单值运行下面给出的命令:

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/<name>/manifests/sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

第4步:删除标记的清单

在docker registy容器中运行此命令:

bin/registry garbage-collect  /etc/docker/registry/config.yml  

这是我的config.yml

[email protected]:/etc# cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
  service: registry
storage:
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
    delete:
        enabled: true
http:
    addr: :5000
    headers:
        X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
45
Yavuz Sert

当前v2注册表现在支持通过DELETE /v2/<name>/manifests/<reference>删除

请参阅: https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image

工作用途: https://github.com/byrnedo/docker-reg-tool

编辑:上面的清单<reference>可以从请求中检索

GET /v2/<name>/manifests/<tag>

并在响应中检查Docker-Content-Digest标头。

40
byrnedo

问题1

您提到它是您的私有docker注册表,因此您可能需要检查 Registry API 而不是 Hub注册表API doc ,这是您提供的链接。

问题2

docker注册表API是一个客户端/服务器协议,它取决于服务器是否删除后端中的图像。 (我猜)

DELETE /v1/repositories/(namespace)/(repository)/tags/(tag*)

详细说明

下面我将根据您的描述演示它的工作原理,作为我对您的问题的理解。

你运行你运行私人docker注册表,我使用默认的一个并监听5000端口

docker run -d -p 5000:5000 registry

然后我标记本地图像并将其推入其中。

$ docker tag ubuntu localhost:5000/ubuntu
$ docker Push localhost:5000/ubuntu
The Push refers to a repository [localhost:5000/ubuntu] (len: 1)
Sending image list
Pushing repository localhost:5000/ubuntu (1 tags)
511136ea3c5a: Image successfully pushed
d7ac5e4f1812: Image successfully pushed
2f4b4d6a4a06: Image successfully pushed
83ff768040a0: Image successfully pushed
6c37f792ddac: Image successfully pushed
e54ca5efa2e9: Image successfully pushed
Pushing tag for rev [e54ca5efa2e9] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}

之后,您可以使用 Registry API 来检查它是否存在于您的私有docker注册表中

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}

现在我可以使用该API删除标签!!

$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true

再次检查,您的私人注册表服务器中不存在该标记

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags/latest
{"error": "Tag not found"}
15
Larry Cai

这真的很丑,但它有效,文本在注册表上测试:2.5.1。即使在更新配置以启用删除后,我也无法使删除工作顺利进行。该ID真的很难检索,不得不登录才能得到它,也许是一些误解。无论如何,以下工作:

  1. 登录容器

    docker exec -it registry sh
    
  2. 定义与容器和容器版本匹配的变量:

    export NAME="google/cadvisor"
    export VERSION="v0.24.1"
    
  3. 移动到注册表目录:

    cd /var/lib/registry/docker/registry/v2
    
  4. 删除与哈希相关的文件:

    find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
    
  5. 删除清单:

    rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
    
  6. 登出

    exit
    
  7. 运行GC:

    docker exec -it registry  bin/registry garbage-collect  /etc/docker/registry/config.yml
    
  8. 如果完成所有操作,则会显示有关已删除blob的一些信息。

11
hirro

有一些客户端(在Python,Ruby等)就是这样做的。根据我的口味,在我的注册表服务器上安装运行时(例如Python)是不可持续的,只是为了保管我的注册表!


所以 deckschrubber 是我的解决方案:

go get github.com/fraunhoferfokus/deckschrubber
$GOPATH/bin/deckschrubber

超过给定年龄的图像会自动删除。可以使用-year-month-day或它们的组合来指定年龄:

$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000

_ update _ 这是一个简短的介绍 on deckschrubber。

8
Yan Foto

简单的Ruby脚本基于 this answer: registry_cleaner

您可以在本地计算机上运行它:

./registry_cleaner.rb --Host=https://registry.exmpl.com --repository=name --tags_count=4

然后在注册表机器上删除带有/bin/registry garbage-collect /etc/docker/registry/config.yml的blob。

0
Ilya Krigouzov

Bash脚本下面删除除最新版本之外的所有注册表中的标记。

for D in /registry-data/docker/registry/v2/repositories/*; do
if [ -d "${D}" ]; then
    if [ -z "$(ls -A ${D}/_manifests/tags/)" ]; then
        echo ''
    else
        for R in $(ls -t ${D}/_manifests/tags/ | tail -n +2); do
            digest=$(curl -k -I -s -H -X GET http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/${R} -H 'accept: application/vnd.docker.distribution.manifest.v2+json'  | grep Docker-Content-Digest | awk '{print $2}' )
            url="http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/$digest"
            url=${url%$'\r'}
            curl -X DELETE -k -I -s   $url -H 'accept: application/vnd.docker.distribution.manifest.v2+json' 
        done
    fi
fi
done

在此运行之后

docker exec $(docker ps | grep registry | awk '{print $1}') /bin/registry garbage-collect /etc/docker/registry/config.yml
0
Shree Tiwari

此docker镜像包含一个bash脚本,可用于从远程v2注册表中删除图像: https://hub.docker.com/r/vidarl/remove_image_from_registry/

0
Vidar Langseid