如何从私人dockerregistry中删除图像?

我运行一个私人dockerregistry,我想删除所有的图像,但latest的版本库。 我不想删除整个存储库,只是其中的一些图像。 API文档没有提到这样做的方法,但肯定有可能?

目前,您无法使用该任务的registryAPI。 它只允许您删除存储库或特定的标签。

通常,删除存储库意味着所有与此回购相关的标签都被删除。

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

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


解决方法

对于这种解决方法,您需要将您的泊坞窗图像存储在本地。

解决scheme的一个解决方法是删除除最新标签以外的所有标签,从而删除对相关图像的引用。 然后,您可以运行此脚本来删除所有未被任何标签或所使用的图像的祖先引用的图像。

术语(图片和标签)

考虑像这样的图像graphics,其中大写字母( 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>标签引用图像D我问你:你真的要删除所有,但图像D ? 可能不会!

如果你删除一个标签会发生什么?

如果您使用Docker REST API删除标记<version1> ,您将得到:

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

记住: Docker永远不会删除图像! 即使这样做,在这种情况下也不能删除图像,因为图像C是被标记的图像D的血统的一部分。

即使您使用此脚本 ,也不会删除任何图像。

当图像可以被删除

在这种情况下,你可以控制什么时候有人可以拉或推入你的registry(例如通过禁用REST接口)。 如果没有其他图像基于图像,则可以从图像图像中删除图像,并且没有标签引用图像。

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

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

清理之后,你的图像看起来像这样:

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

这是你想要的吗?

当前的v2registry现在支持通过DELETE /v2/<name>/manifests/<reference>进行DELETE /v2/<name>/manifests/<reference>

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

问题1

您提到这是您的私人dockerregistry,所以您可能需要检查registryAPI而不是HubregistryAPI doc ,这是您提供的链接。

问题2

dockerregistryAPI是一个客户端/服务器协议,取决于是否删除后端图像的服务器的实施。 (我猜)

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

详细说明

下面我演示如何从您的描述作为我对你的问题的理解现在如何工作。

你运行你运行私人dockerregistry,我使用默认的一个,并在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} 

之后,您可以使用registryAPI检查它存在于您的私人dockerregistry中

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

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

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

再次检查,标记不存在于您的私人registry服务器中

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

我遇到了与我的registry相同的问题,然后我尝试了从博客页面下面列出的解决scheme。 有用。

第1步:列出目录

您可以通过调用以下url列出您的目录:

 http://YourPrivateRegistyIP:5000/v2/_catalog 

响应将采用以下格式:

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

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

您可以通过调用以下URL来列出目录的标签:

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

响应将采用以下格式:

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

}

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

你可以在dockerregistry容器中运行这个命令:

 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步:删除标记的清单

在你的dockerregistry容器中运行这个命令:

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

这是我的config.yml

 root@c695814325f4:/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 

这真的很丑,但它的工作原理是在registry上进行testing:2.5.1。 即使在更新configuration以启用删除之后,我仍无法使删除工作顺利进行。 身份证真的很难找回,必须login才能得到它,也许有一些误解。 无论如何,以下作品:

  1. login到容器

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

     export NAME="google/cadvisor" export VERSION="v0.24.1" 
  3. 移到registry目录:

     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. 如果一切正常完成,则会显示有关删除的斑点的一些信息。

有一些客户端(在Python,ruby等),正是这样做。 对我来说,在我的registry服务器上安装运行库(例如Python)是不可持续的,只是为了pipe理我的registry!


所以deckschrubber是我的解决scheme:

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

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

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

更新 : 这里是一个简短的介绍 deckschrubber。

这个docker镜像包含一个bash脚本,可用于从远程v2registry中删除镜像: https : //hub.docker.com/r/vidarl/remove_image_from_registry/