为什么摘要因注册表而异?

Sun*_*oon 5 hash docker docker-registry docker-image

AFAIK,图像摘要是图像清单正文的散列。

当我busybox从 docker hub拉取镜像并将其推送到我的私有注册表时,摘要会有所不同。

$ docker pull busybox
...
Digest: sha256:2605a2c4875ce5eb27a9f7403263190cd1af31e48a2044d400320548356251c4
Status: Downloaded newer image for busybox:latest

$ docker tag busybox myregistry/busybox
$ docker push myregistry/busybox
...
08c2295a7fa5: Pushed
latest: digest: sha256:8573b4a813d7b90ef3876c6bec33db1272c02f0f90c406b25a5f9729169548ac size: 527

$ docker images --digests
myregistry/busybox    latest      sha256:8573b4a813d7b90ef3876c6bec33db1272c02f0f90c406b25a5f9729169548ac   efe10ee6727f        2 weeks ago         1.13MB
busybox               latest      sha256:2605a2c4875ce5eb27a9f7403263190cd1af31e48a2044d400320548356251c4   efe10ee6727f        2 weeks ago         1.13MB
Run Code Online (Sandbox Code Playgroud)

图像根本没有改变,图像 id 彼此相同。

但是为什么图像摘要会有所不同呢?


更新:

有趣的是,来自另一个私有注册表的摘要与我的私有注册表的摘要完全相同。

$ docker image inspect efe10ee6727f
...
"RepoDigests": [
            "myregistry/busybox@sha256:8573b4a813d7b90ef3876c6bec33db1272c02f0f90c406b25a5f9729169548ac",
            "busybox@sha256:2605a2c4875ce5eb27a9f7403263190cd1af31e48a2044d400320548356251c4",
            "anotherregistry/busybox@sha256:8573b4a813d7b90ef3876c6bec33db1272c02f0f90c406b25a5f9729169548ac"
        ],
Run Code Online (Sandbox Code Playgroud)

BMi*_*tch 12

您正在查看的摘要是注册表摘要,它与图像 ID 摘要不同。您可以拥有一个映像 ID,该映像 ID 对于已推送的所有位置都有不同的注册表引用(可能还有摘要)。您可以在检查输出中看到两个 id:

$ docker inspect busybox --format 'Id: {{.Id}}
Repo Digest: {{index .RepoDigests 0}}'
Id: sha256:efe10ee6727fe52d2db2eb5045518fe98d8e31fdad1cbdd5e1f737018c349ebb
Repo Digest: busybox@sha256:2605a2c4875ce5eb27a9f7403263190cd1af31e48a2044d400320548356251c4
Run Code Online (Sandbox Code Playgroud)

如果注册表使用旧的v1 清单,则存储库名称和标签是该清单的一部分,这意味着它将在注册表之间移动时发生变化:

{
   "name": <name>,
   "tag": <tag>,
   "fsLayers": [
      {
         "blobSum": "<digest>"
      },
      ...
    ]
   ],
   "history": <v1 images>,
   "signature": <JWS>
}
Run Code Online (Sandbox Code Playgroud)

然而,对于OCI 清单Docker 的 v2 清单,情况不再如此,您应该看到同一映像的相同注册表摘要:

{
    "schemaVersion": 2,
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "config": {
        "mediaType": "application/vnd.docker.container.image.v1+json",
        "size": 7023,
        "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
    },
    "layers": [
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 32654,
            "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"
        },
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 16724,
            "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
        },
        {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "size": 73109,
            "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

摘要本身是内容的 sha256 摘要,您也可以在OCI 的实现中找到它。当您在本地拉取映像时,某些事情会发生变化,包括解压缩的层,并且多平台映像将取消引用到本地平台。由于这些更改,内容的摘要将会更改,并且映像 ID 将与注册表摘要不匹配。

因此,要比较注册表之间的图像,请确保指定带有接受标头的 v2 架构,否则注册表会将结果转换回 v1 架构。在curl中,传递这些标头看起来像:

curl \
  -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  -H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
  http://$registry/v2/$repo/manifests/$tag
Run Code Online (Sandbox Code Playgroud)