如何使用Docker Registry API V2从私有仓库中删除镜像?

19

如果我有一个在localhost:5000上的Docker Registry,我该如何使用Docker Registry HTTP API V2curl删除以下标头和清单的busybox:latest

derek@derekmahar-ubuntu-512mb-tor1-01:~/Projects/docker-registry$ curl --head --request GET http://localhost:5000/v2/busybox/manifests/latest
HTTP/1.1 200 OK
Content-Length: 2561
Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
Docker-Content-Digest: sha256:e45f25b1760f616e65f106b424f4ef29185fbd80822255d79dabc73b8eb715ad
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:e45f25b1760f616e65f106b424f4ef29185fbd80822255d79dabc73b8eb715ad"
X-Content-Type-Options: nosniff
Date: Wed, 04 May 2016 16:10:00 GMT

derek@derekmahar-ubuntu-512mb-tor1-01:~/Projects/docker-registry$ curl --request GET http://localhost:5000/v2/busybox/manifests/latest
{
   "schemaVersion": 1,
   "name": "busybox",
   "tag": "latest",
   "architecture": "amd64",
   "fsLayers": [
      {
         "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
      },
      {
         "blobSum": "sha256:385e281300cc6d88bdd155e0931fbdfbb1801c2b0265340a40481ee2b733ae66"
      }
   ],
   "history": [
      {
         "v1Compatibility": "{\"architecture\":\"amd64\",\"config\":{\"Hostname\":\"156e10b83429\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"sh\"],\"Image\":\"56ed16bd6310cca65920c653a9bb22de6b235990dcaa1742ff839867aed730e5\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"container\":\"5f8098ec29947b5bea80483cd3275008911ce87438fed628e34ec0c522665510\",\"container_config\":{\"Hostname\":\"156e10b83429\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [\\\"sh\\\"]\"],\"Image\":\"56ed16bd6310cca65920c653a9bb22de6b235990dcaa1742ff839867aed730e5\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2016-03-18T18:22:48.810791943Z\",\"docker_version\":\"1.9.1\",\"id\":\"437595becdebaaaf3a4fc3db02c59a980f955dee825c153308c670610bb694e1\",\"os\":\"linux\",\"parent\":\"920777304d1d5e337bc59877253e946f224df5aae64c72538672eb74637b3c9e\"}"
      },
      {
         "v1Compatibility": "{\"id\":\"920777304d1d5e337bc59877253e946f224df5aae64c72538672eb74637b3c9e\",\"created\":\"2016-03-18T18:22:48.262403239Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:47ca6e777c36a4cfffe3f918b64a445c8f32300deeb9dfa5cc47261bd7b75d21 in /\"]}}"
      }
   ],
   "signatures": [
      {
         "header": {
            "jwk": {
               "crv": "P-256",
               "kid": "RVEO:MXL3:ZYLW:BFGB:QAKI:SIKZ:JOVR:U7AP:2LGY:4SSF:MSV4:LND7",
               "kty": "EC",
               "x": "ZFyhNUInMwlVmFKzz-e-o_tzMd01ZdCj6LyGV4dnT5Y",
               "y": "3a0BcWa0h60tTGHYhUI4ziKisRk6b4JtvqbmL9kKy6E"
            },
            "alg": "ES256"
         },
         "signature": "BVWioJafWmMrUBBi9meRy9CUQYdsZgwkY01ipT1HInXofVXCIZmNMq7EFEl4A88pMZsf7DHZS2dyFeFjj-QP1Q",
         "protected": "eyJmb3JtYXRMZW5ndGgiOjE5MTQsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wNS0wNFQxNjoxMzo0M1oifQ"
      }
   ]
}

当我尝试使用DELETE删除镜像摘要时,Docker Registry会抱怨"HTTP/1.1 404 Not Found"和"MANIFEST_UNKNOWN"。

derek@derekmahar-ubuntu-512mb-tor1-01:~/Projects/docker-registry$ curl --request DELETE http://localhost:5000/v2/busybox/manifests/sha256:e45f25b1760f616e65f106b424f4ef29185fbd80822255d79dabc73b8eb715ad
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown"}]}

类似的问题,要求略有不同:从远程Docker仓库中删除Docker镜像 - JamesThomasMoon
3个回答

31

请注意:此API端点仅在较新版本的v2注册表中实现!

有一个内部垃圾回收过程,用于删除注册表中的镜像,但是目前还无法通过v2注册表API访问。这个功能似乎最近有很多动态,所以这些信息可能会发生变化。

根据API规范,您必须获取镜像摘要才能对其运行DELETE操作。仔细阅读规范并注意请求正确镜像摘要时所需的标头部分(“注意:当从版本2.3或更高版本的注册表中删除清单时,必须在HEAD或GET清单时使用以下标头以获取正确的摘要进行删除:Accept: application/vnd.docker.distribution.manifest.v2+json”)

curl -v -u "user@example.com:passw0rd" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X HEAD https://registry.example.com/v2/derek/busybox/manifests/latest

当您这样做时,需要特别关注 Docker-Content-Digest 标头。在您的特定请求中,完整标头如下:
Docker-Content-Digest: sha256:e45f25b1760f616e65f106b424f4ef29185fbd80822255d79dabc73b8eb715ad

现在,有了这个摘要,您应该能够将其插入到您链接的API所描述的格式中:
DELETE /v2/<name>/manifests/<reference>

使用我之前举的例子,但是用你的摘要,curl命令应该如下:

curl -u "user@example.com:passw0rd" -X DELETE https://registry.example.com/v2/derek/busybox/manifests/sha256:e45f25b1760f616e65f106b424f4ef29185fbd80822255d79dabc73b8eb715ad

然后您应该收到一个202 Accepted响应代码,表示删除成功。

您还可以尝试从this gist获取短脚本:

registry='localhost:5000'
name='my-image'
curl -v -sSL -X DELETE "http://${registry}/v2/${name}/manifests/$(
    curl -sSL -I \
        -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
        "http://${registry}/v2/${name}/manifests/$(
            curl -sSL "http://${registry}/v2/${name}/tags/list" | jq -r '.tags[0]'
        )" \
    | awk '$1 == "Docker-Content-Digest:" { print $2 }' \
    | tr -d $'\r' \
)"

为什么我必须在URL中指定我的用户名? - Derek Mahar
你确定你的 busybox 镜像中没有包含用户命名空间吗?就像我的例子一样。我只有在指定完整的镜像名称时,包括“repo”(用户名)才能使其正常工作。例如 https://reg.foo.com/v2/l0j1k/busybox/manifests/sha:deadbeefbabecafe。只有在这一点上,我才能得到任何不是404的东西。还要确保您使用的Distribution版本号足够高,例如至少Registry v2.4。 - L0j1k
我该如何查询注册表的版本号?我最近刚刚拉取了它。 - Derek Mahar
Registry是否要求镜像属于用户命名空间?Docker可以从我的Registry中拉取busybox镜像,因此我猜测不需要用户命名空间。 - Derek Mahar
3
您需要正确指定HEAD请求的“Accept”头信息。我已经编辑了答案以反映这一点。 - Tim-Erwin
显示剩余9条评论

10

5

我曾经遇到过完全相同的问题。当使用有效摘要但不引用清单时,会发生MANIFEST_UNKNOWN错误。你一定要使用“-H“Accept:application/vnd.docker.distribution.manifest.v2+json”来获取正确的Docker-Content-Digest值,以便引用清单。

$ curl -s -I http://$REGISTRY/v2/myapp/manifests/1.0.0 | awk '/^Docker-Content-Digest/ {print $2}'
sha256:c1102294980e4ad2563a7ba65e9192ec3980dbb1f863fd1f81adcb95bc6e0c2a
$
$ curl -s -X DELETE http://$REGISTRY/v2/myapp/manifests/sha256:c1102294980e4ad2563a7ba65e9192ec3980dbb1f863fd1f81adcb95bc6e0c2a
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown"}]}

对比

$ curl -s -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" http://$REGISTRY/v2/myapp/manifests/1.0.0 | awk '/^Docker-Content-Digest/ {print $2}'
sha256:5403b52afdba954349746c60f4e6dc18d2a6ab414333c8ab4b0928126e63371f
$
$ curl -s -X DELETE http://$REGISTRY/v2/myapp/manifests/sha256:5403b52afdba954349746c60f4e6dc18d2a6ab414333c8ab4b0928126e63371f
$ # successfully deleted, no error

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接