【问题标题】:Is that possible to get image ID from Docker Registry V2?是否可以从 Docker Registry V2 获取图像 ID?
【发布时间】:2020-11-18 22:52:32
【问题描述】:

当一个镜像被推送到 registry V2 时,镜像 ID 是否也会被推送到 registry?是否可以从 V2 注册表中获取某个存储库的映像 ID?

【问题讨论】:

    标签: docker docker-registry docker-image


    【解决方案1】:

    如果镜像是使用 Docker Client 1.10 或更高版本推送的,您可以通过以下方式从注册表中获取镜像 ID

    GET /v2/<image>/manifests/<tag> 
    

    您的请求必须包含标头

    Accept: application/vnd.docker.distribution.manifest.v2+json
    

    在响应中,图像 ID 将在 Content-Docker-Digest 响应标头中。

    【讨论】:

    • 谢谢,这就是我现在正在做的事情。
    • 您好,您可以包含一个格式化的 curl 请求作为示例吗?我在使用 v2 api 时遇到问题。
    • @fightingdu 下面的答案中有一个很好的 curl 请求。您只需输入 $server$repo$tag 的值
    • Content-Docker-Digest 不包含图像 ID。镜像 id 是镜像配置的摘要,参见github.com/docker/distribution/issues/… ...您可以从较新的注册表协议版本的 config.digest 中获取它。
    【解决方案2】:

    [2020-11 更新答案]

    在使用 docker 镜像时有很多 sha 需要处理。每个文件系统层都有一个唯一的 sha,当该层被压缩并存储在注册表中时,它会得到更新。在代表图像配置的 json 对象上计算了一个 sha,这就是您在本地查找图像 id 时看到的内容:

    $ docker inspect busybox:latest --format '{{ .ID }}'
    sha256:f0b02e9d092d905d0d87a8455a1ae3e9bb47b4aa3dc125125ca5cd10d6441c9f
    

    注册表中有一个单一平台清单的 sha。此清单包括指向图像配置和各个层的指针。多平台清单也有一个 sha,它指向每个单独的平台。让我们深入研究这些。首先,我将使用一个脚本来通过匿名请求查询 Docker Hub 注册表:

    $ cat manifest-v2.sh
    #!/bin/sh
    
    ref="${1:-library/ubuntu:latest}"
    sha="${ref#*@}"
    if [ "$sha" = "$ref" ]; then
      sha=""
    fi
    wosha="${ref%%@*}"
    repo="${wosha%:*}"
    tag="${wosha##*:}"
    if [ "$tag" = "$wosha" ]; then
      tag="latest"
    fi
    api="application/vnd.docker.distribution.manifest.v2+json"
    apil="application/vnd.docker.distribution.manifest.list.v2+json"
    token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" \
            | jq -r '.token')
    curl -H "Accept: ${api}" -H "Accept: ${apil}" \
         -H "Authorization: Bearer $token" \
         -s "https://registry-1.docker.io/v2/${repo}/manifests/${sha:-$tag}" | jq .
    

    接下来,让我们拉取最新标签的清单:

    $ ./manifest-v2.sh library/busybox:latest
    {
      "manifests": [
        {
          "digest": "sha256:c9249fdf56138f0d929e2080ae98ee9cb2946f71498fc1484288e6a935b5e5bc",
          "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
          "platform": {
            "architecture": "amd64",
            "os": "linux"
          },
          "size": 527
        },
        {
          "digest": "sha256:a7c572c26ca470b3148d6c1e48ad3db90708a2769fdf836aa44d74b83190496d",
          "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
          "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v5"
          },
          "size": 527
        },
    ...
    

    结果是一个清单列表,让我们为 amd64 平台拉取 sha:

    $ ./manifest-v2.sh library/busybox@sha256:c9249fdf56138f0d929e2080ae98ee9cb2946f71498fc1484288e6a935b5e5bc
    {
      "schemaVersion": 2,
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "config": {
        "mediaType": "application/vnd.docker.container.image.v1+json",
        "size": 1493,
        "digest": "sha256:f0b02e9d092d905d0d87a8455a1ae3e9bb47b4aa3dc125125ca5cd10d6441c9f"
      },
      "layers": [
        {
          "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
          "size": 764619,
          "digest": "sha256:9758c28807f21c13d05c704821fdd56c0b9574912f9b916c65e1df3e6b8bc572"
        }
      ]
    }
    

    在那里,我们有一个单独的层和配置对象,该配置上具有application/vnd.docker.container.image.v1+json 媒体类型的sha 与我们的图像ID sha256:f0b02e9d092d9... 匹配。这更容易从注册表的 v2 输出中挑选出来,这就是清单脚本插入 Accept 标头的原因。

    我要提醒的是,我不相信它可以保证匹配,YMMV,IANAL 等。我可以预见 docker 添加/删除将被不同版本的 docker 引擎忽略的字段。所以我会避免这种行为的任何硬依赖。

    请注意,此 sha 与您用于唯一标识注册表中用于提取图像的图像的 sha 不同。为此,您需要清单 sha,如果有清单列表,您应该使用它。在解析标签时,你可以通过一个 HEAD 请求看到这个 sha(使用 -I 参数来 curl):

    $ cat manifest-v2-head.sh 
    #!/bin/sh
    
    ref="${1:-library/ubuntu:latest}"
    sha="${ref#*@}"
    if [ "$sha" = "$ref" ]; then
      sha=""
    fi
    wosha="${ref%%@*}"
    repo="${wosha%:*}"
    tag="${wosha##*:}"
    if [ "$tag" = "$wosha" ]; then
      tag="latest"
    fi
    # echo "Looking up repo $repo, ${sha:-$tag}"
    # api="application/vnd.oci.image.index.v1+json"
    # api="application/vnd.oci.image.manifest.v1+json"
    api="application/vnd.docker.distribution.manifest.v2+json"
    apil="application/vnd.docker.distribution.manifest.list.v2+json"
    token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" \
            | jq -r '.token')
    curl -H "Accept: ${api}" -H "Accept: ${apil}" \
         -H "Authorization: Bearer $token" \
         -I -s "https://registry-1.docker.io/v2/${repo}/manifests/${sha:-$tag}" 
    
    $ ./manifest-v2-head.sh library/busybox:latest
    HTTP/1.1 200 OK
    Content-Length: 2080
    Content-Type: application/vnd.docker.distribution.manifest.list.v2+json
    Docker-Content-Digest: sha256:a9286defaba7b3a519d585ba0e37d0b2cbee74ebfe590960b0b1d6a5e97d1e1d
    Docker-Distribution-Api-Version: registry/2.0
    Etag: "sha256:a9286defaba7b3a519d585ba0e37d0b2cbee74ebfe590960b0b1d6a5e97d1e1d"
    Date: Wed, 18 Nov 2020 14:38:59 GMT
    Strict-Transport-Security: max-age=31536000
    RateLimit-Limit: 250;w=21600
    RateLimit-Remaining: 250;w=21600
    

    从上面你可以docker pull busybox@sha:a9286d...

    这里的所有命令都是 Docker Hub 特定的。为了与其他注册中心合作,我的regclient 项目中有一个regctl 命令可用,用于处理对其他注册中心的身份验证和API 调用:

    $ regctl image manifest busybox
    {
      "schemaVersion": 2,
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "config": {
        "mediaType": "application/vnd.docker.container.image.v1+json",
        "size": 1493,
        "digest": "sha256:f0b02e9d092d905d0d87a8455a1ae3e9bb47b4aa3dc125125ca5cd10d6441c9f"
      },
      "layers": [
        {
          "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
          "size": 764619,
          "digest": "sha256:9758c28807f21c13d05c704821fdd56c0b9574912f9b916c65e1df3e6b8bc572"
        }
      ]
    }
    
    $ regctl image digest busybox --list
    sha256:a9286defaba7b3a519d585ba0e37d0b2cbee74ebfe590960b0b1d6a5e97d1e1d
    
    $ regctl image digest busybox
    sha256:c9249fdf56138f0d929e2080ae98ee9cb2946f71498fc1484288e6a935b5e5bc
    

    原答案:

    图像 id 本身不存储在任何注册表 API 可访问的位置,这是使用本地注册表的示例:

    bash$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
    Unable to find image 'registry:2' locally
    2: Pulling from library/registry
    ...
    
    bash$ docker tag busybox localhost:5000/busybox
    
    bash$ docker push localhost:5000/busybox
    The push refers to a repository [localhost:5000/busybox]
    5f70bf18a086: Pushed 
    ...
    
    bash$ curl http://localhost:5000/v2/busybox/tags/list
    {"name":"busybox","tags":["latest"]}
    
    bash$ curl 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": "FIFX:SJRD:AQHW:MCFX:M6WC:LXI2:3VO2:4LFW:UHDZ:QUN7:OLX4:6WGD",
                   "kty": "EC",
                   "x": "Xm8wJTzw3nb--rGoD3dxjKffikj7Snb9dHW-qGbqSAM",
                   "y": "GnATS--7lVcA_-jQGuDKTtjhmnGgvBrx8rLdlPOJV3U"
                },
                "alg": "ES256"
             },
             "signature": "f8NVzOF6ujm_0COedniGCGL_q3KsTfKFM9T8ZZDf2MSIMJ3TYoR_s795NqdEy8yWaoLuT2LoI0BCEsuOTZUhCw",
             "protected": "eyJmb3JtYXRMZW5ndGgiOjE5MTQsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wNi0xMVQwMToxMzoyMVoifQ"
          }
       ]
    
    bash$ curl -I 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: Sat, 11 Jun 2016 01:21:26 GMT
    

    在任何这些 API 调用中,我都找不到我在本地看到的所需 47bcc53... 图像 ID。

    bash$ docker inspect busybox:latest
    [
        {
            "Id": "sha256:47bcc53f74dc94b1920f0b34f6036096526296767650f223433fe65c35f149eb",
            "RepoTags": [
                "busybox:latest",
                "localhost:5000/busybox:latest"
            ],
    ...
    

    来自this image spec 的图像 id 是可重现的哈希值,我确实在不同的系统上看到图像 id 的相同值。

    图像ID 每个图像的 ID 由其配置 JSON 的 SHA256 散列给出。它表示为 256 位的十六进制编码,例如, sha256:a9561eb1b190625c9adb5a9513e72c4dedafc1cb2d4c5236c9a6957ec7dfd5a9。 由于获取散列的配置 JSON 引用了 图像中的每一层,ImageID 的这个公式使图像 内容可寻址。

    因此,如果您可以从 API 调用中重现配置 JSON,那么您也许可以自己生成图像 id。

    【讨论】:

    • 谢谢!这个答案是我根据我的研究所期望的......似乎获取存储库映像的映像 ID 的唯一方法是尝试获取配置 JSON,并通过 Docker 守护程序的相同哈希算法重现映像 ID。
    【解决方案3】:

    根据我的研究,您可以使用以下方式从注册表(2.3.0+)获取图像 ID

    curl -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' http://$server/v2/$repo/manifests/$tag

    响应中的config.digest 字段表示imageID,即您想要的!

    for example

    指: https://duyanghao.github.io/docker-registry-pull-manifest-v2/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      相关资源
      最近更新 更多