容器镜像详解

1. 镜像组成

一个标准的OCI容器镜像由index, manifest, config, image layers这几个部分组成。
以docker镜像为例,下载的镜像文件保存在/var/lib/docker/目录下面
在这里插入图片描述
image/overlay2子目录下面保存着镜像相关的一些元数据
在这里插入图片描述
在下面的介绍主要以nginx:latest镜像为例子

docker inspect nginx:latest
[
    {
        "Id": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
        "RepoTags": [
            "nginx:latest"
        ],
        "RepoDigests": [
            "nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-12-29T19:28:29.892199479Z",
        "Container": "ca3e48389f7160bc9d9a892d316fcbba459344ee3679998739b1c3cd8e56f7da",
        "ContainerConfig": {
            "Hostname": "ca3e48389f71",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.21.5",
                "NJS_VERSION=0.7.1",
                "PKG_RELEASE=1~bullseye"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"nginx\" \"-g\" \"daemon off;\"]"
            ],
            "Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
                "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
            },
            "StopSignal": "SIGQUIT"
        },
        "DockerVersion": "20.10.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.21.5",
                "NJS_VERSION=0.7.1",
                "PKG_RELEASE=1~bullseye"
            ],
            "Cmd": [
                "nginx",
                "-g",
                "daemon off;"
            ],
            "Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
                "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
            },
            "StopSignal": "SIGQUIT"
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 141479488,
        "VirtualSize": 141479488,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/6f894a7b66f4d1428817a444693b30b9adf85a2ae9dbcaffcde1a3e69c5e4017/diff:/var/lib/docker/overlay2/c645f15c9c993a5132afa4ce456d27af1a8119c380411374f57d5c8844b7d8b8/diff:/var/lib/docker/overlay2/f3b266fa677b6c553d3b2145135a3e1aa814f35b05467fe1500ad78a1a9cb166/diff:/var/lib/docker/overlay2/602a87b98d429966c3da272b5e08b95aa8a78d8505175bfd0c43f03dfd18f290/diff:/var/lib/docker/overlay2/e859f64556e9fe63bb08299584dc568b5f5a13b9a6a995de399a7fa020359423/diff",
                "MergedDir": "/var/lib/docker/overlay2/ce4bb4283e6fe5550b799d88dbec1f117e6bd8a5f33a17c8818df6e4bc76ce17/merged",
                "UpperDir": "/var/lib/docker/overlay2/ce4bb4283e6fe5550b799d88dbec1f117e6bd8a5f33a17c8818df6e4bc76ce17/diff",
                "WorkDir": "/var/lib/docker/overlay2/ce4bb4283e6fe5550b799d88dbec1f117e6bd8a5f33a17c8818df6e4bc76ce17/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
                "sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8",
                "sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221",
                "sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c",
                "sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da",
                "sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d68e7ed6040a6"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

2. distribution 目录

diffid-by-digest 保存了digest(layerID)->diffID的映射关系。
v2metadata-by-diffid 保存了diffid -> (digest,repository)的映射关系。
digest(layerID) 就是 pull 镜像时的 hash ID,拉取的镜像层文件是压缩文件,压缩态。
diffID 是 docker inspect 查看到的 镜像层 hash ID,此时镜像层文件是解压缩的,解压缩态。
因此虽说这两种 ID 都表示 镜像层 hash ID,但一个是压缩的,一个是解压缩的,所以 hash 运算后不一致。
拿上面nginx:latest镜像为例,RootFS中最上面一层镜像的diffID为"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
在这里插入图片描述
可以看到diffID和Digest(layerID),a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea,可以相互对应到,

3. imagedb 目录

保存镜像的元数据信息,两个子文件夹 content/ 和 metadata/
tree /var/lib/docker/image/overlay2/imagedb可以查看此目录的结构
在这里插入图片描述
打开content/sha256目录下以镜像ID命名的文件,我们可以看到镜像的元数据信息(config文件内容),包括了镜像架构、操作系统 、默认配置、创建时间、历史信息和rootfs等
cat /var/lib/docker/image/overlay2/imagedb/content/sha256/605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85,上面的

nginx:latest的image id。
{
  "architecture": "amd64",
  "config": {
    "Hostname": "",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "ExposedPorts": {
      "80/tcp": {}
    },
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": [
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
      "NGINX_VERSION=1.21.5",
      "NJS_VERSION=0.7.1",
      "PKG_RELEASE=1~bullseye"
    ],
    "Cmd": [
      "nginx",
      "-g",
      "daemon off;"
    ],
    "Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": [
      "/docker-entrypoint.sh"
    ],
    "OnBuild": null,
    "Labels": {
      "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
    },
    "StopSignal": "SIGQUIT"
  },
  "container": "ca3e48389f7160bc9d9a892d316fcbba459344ee3679998739b1c3cd8e56f7da",
  "container_config": {
    "Hostname": "ca3e48389f71",
    "Domainname": "",
    "User": "",
    "AttachStdin": false,
    "AttachStdout": false,
    "AttachStderr": false,
    "ExposedPorts": {
      "80/tcp": {}
    },
    "Tty": false,
    "OpenStdin": false,
    "StdinOnce": false,
    "Env": [
      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
      "NGINX_VERSION=1.21.5",
      "NJS_VERSION=0.7.1",
      "PKG_RELEASE=1~bullseye"
    ],
    "Cmd": [
      "/bin/sh",
      "-c",
      "#(nop) ",
      "CMD [\"nginx\" \"-g\" \"daemon off;\"]"
    ],
    "Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
    "Volumes": null,
    "WorkingDir": "",
    "Entrypoint": [
      "/docker-entrypoint.sh"
    ],
    "OnBuild": null,
    "Labels": {
      "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
    },
    "StopSignal": "SIGQUIT"
  },
  "created": "2021-12-29T19:28:29.892199479Z",
  "docker_version": "20.10.7",
  "history": [
    {
      "created": "2021-12-21T01:22:43.418913408Z",
      "created_by": "/bin/sh -c #(nop) ADD file:09675d11695f65c55efdc393ff0cd32f30194cd7d0fbef4631eebfed4414ac97 in / "
    },
    {
      "created": "2021-12-21T01:22:43.799429634Z",
      "created_by": "/bin/sh -c #(nop)  CMD [\"bash\"]",
      "empty_layer": true
    },
    {
      "created": "2021-12-21T03:00:06.15011478Z",
      "created_by": "/bin/sh -c #(nop)  LABEL maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:08.071260391Z",
      "created_by": "/bin/sh -c #(nop)  ENV NGINX_VERSION=1.21.5",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:08.248669935Z",
      "created_by": "/bin/sh -c #(nop)  ENV NJS_VERSION=0.7.1",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:08.472939138Z",
      "created_by": "/bin/sh -c #(nop)  ENV PKG_RELEASE=1~bullseye",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:27.976946316Z",
      "created_by": "/bin/sh -c set -x     && addgroup --system --gid 101 nginx     && adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos \"nginx user\" --shell /bin/false --uid 101 nginx     && apt-get update     && apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates     &&     NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62;     found='';     for server in         hkp://keyserver.ubuntu.com:80         pgp.mit.edu     ; do         echo \"Fetching GPG key $NGINX_GPGKEY from $server\";         apt-key adv --keyserver \"$server\" --keyserver-options timeout=10 --recv-keys \"$NGINX_GPGKEY\" && found=yes && break;     done;     test -z \"$found\" && echo >&2 \"error: failed to fetch GPG key $NGINX_GPGKEY\" && exit 1;     apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/*     && dpkgArch=\"$(dpkg --print-architecture)\"     && nginxPackages=\"         nginx=${NGINX_VERSION}-${PKG_RELEASE}         nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE}         nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE}         nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE}         nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE}     \"     && case \"$dpkgArch\" in         amd64|arm64)             echo \"deb https://nginx.org/packages/mainline/debian/ bullseye nginx\" >> /etc/apt/sources.list.d/nginx.list             && apt-get update             ;;         *)             echo \"deb-src https://nginx.org/packages/mainline/debian/ bullseye nginx\" >> /etc/apt/sources.list.d/nginx.list                         && tempDir=\"$(mktemp -d)\"             && chmod 777 \"$tempDir\"                         && savedAptMark=\"$(apt-mark showmanual)\"                         && apt-get update             && apt-get build-dep -y $nginxPackages             && (                 cd \"$tempDir\"                 && DEB_BUILD_OPTIONS=\"nocheck parallel=$(nproc)\"                     apt-get source --compile $nginxPackages             )                         && apt-mark showmanual | xargs apt-mark auto > /dev/null             && { [ -z \"$savedAptMark\" ] || apt-mark manual $savedAptMark; }                         && ls -lAFh \"$tempDir\"             && ( cd \"$tempDir\" && dpkg-scanpackages . > Packages )             && grep '^Package: ' \"$tempDir/Packages\"             && echo \"deb [ trusted=yes ] file://$tempDir ./\" > /etc/apt/sources.list.d/temp.list             && apt-get -o Acquire::GzipIndexes=false update             ;;     esac         && apt-get install --no-install-recommends --no-install-suggests -y                         $nginxPackages                         gettext-base                         curl     && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list         && if [ -n \"$tempDir\" ]; then         apt-get purge -y --auto-remove         && rm -rf \"$tempDir\" /etc/apt/sources.list.d/temp.list;     fi     && ln -sf /dev/stdout /var/log/nginx/access.log     && ln -sf /dev/stderr /var/log/nginx/error.log     && mkdir /docker-entrypoint.d"
    },
    {
      "created": "2021-12-29T19:28:28.390440509Z",
      "created_by": "/bin/sh -c #(nop) COPY file:65504f71f5855ca017fb64d502ce873a31b2e0decd75297a8fb0a287f97acf92 in / "
    },
    {
      "created": "2021-12-29T19:28:28.640632824Z",
      "created_by": "/bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b03c4e6c8c513ae014f691fb05d530257dfffd07035c1b75da in /docker-entrypoint.d "
    },
    {
      "created": "2021-12-29T19:28:28.864872406Z",
      "created_by": "/bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7de297435e32af634f29f7132ed0550d342cad9fd20158258 in /docker-entrypoint.d "
    },
    {
      "created": "2021-12-29T19:28:29.113627588Z",
      "created_by": "/bin/sh -c #(nop) COPY file:09a214a3e07c919af2fb2d7c749ccbc446b8c10eb217366e5a65640ee9edcc25 in /docker-entrypoint.d "
    },
    {
      "created": "2021-12-29T19:28:29.296888541Z",
      "created_by": "/bin/sh -c #(nop)  ENTRYPOINT [\"/docker-entrypoint.sh\"]",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:29.498026198Z",
      "created_by": "/bin/sh -c #(nop)  EXPOSE 80",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:29.705311925Z",
      "created_by": "/bin/sh -c #(nop)  STOPSIGNAL SIGQUIT",
      "empty_layer": true
    },
    {
      "created": "2021-12-29T19:28:29.892199479Z",
      "created_by": "/bin/sh -c #(nop)  CMD [\"nginx\" \"-g\" \"daemon off;\"]",
      "empty_layer": true
    }
  ],
  "os": "linux",
  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
      "sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8",
      "sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221",
      "sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c",
      "sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da",
      "sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d68e7ed6040a6"
    ]
  }
}

image元数据中layer的diffID是以低层到高层的顺序记录的

4. layerdb 目录

保存镜像层的关联关系,layerdb/sha256下的目录名称是以layer的chainID来命名的,它的计算方式为:

if layer是最底层,没有任何父layer
	chainID = diffID
else 
	chainID(n)=sha256sum(chainID[n-1)] + " " + diffID[n])

举例,查看某一镜像层 chainID 目录下的内容:
cat /var/lib/docker/image/overlay2/layerdb/sha256/2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f,这是最底层,所以chainID[0] == diffID[0]。
在这里插入图片描述
size:layer文件的大小
cache-id:存储驱动通过cache-id索引到layer的实际文件内容
diff:diffID
计算第二层
chainID[1] = sha256sum(diffID[0] + " " + diffID[1])

echo -n "sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8" | sha256sum | awk '{print $1}'
输出:780238f18c540007376dd5e904f583896a69fe620876cabc06977a3af4ba4fb5
在这里插入图片描述
parent:父layer的chainID
其余的和上面一样,其余层数也是如此
通过chainID可以从/var/lib/docker/overlayer2找到实际的镜像层数据。

5. repositories.json 文件

这个需要先搞清楚 registry 是镜像仓库,而 repository 代表镜像组(比如不同版本的 nginx 镜像)
该文件中描述了宿主机上所有镜像的repository元数据,主要包括镜像名、tag和镜像ID
镜像ID是Docker采用SHA256算法
查看:cat /var/lib/docker/image/overlay2/repositories.json | python -mjson.tool

{
    ...,
    "nginx": {
        "nginx:latest": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
        "nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85"
    },
	...
}

6. 拉取镜像

6.1 获取镜像清单

GET https://2h3po24q.mirror.aliyuncs.com/v2/library/alpine/manifests/latest HTTP/1.1
Host: 2h3po24q.mirror.aliyuncs.com
User-Agent: docker/19.03.12 go/go1.13.10 git-commit/48a66213fe kernel/5.8.0-1.el7.elrepo.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.12 \(linux\))
Accept: application/vnd.docker.distribution.manifest.v2+json
Accept: application/vnd.docker.distribution.manifest.list.v2+json
Accept: application/vnd.oci.image.index.v1+json
Accept: application/vnd.oci.image.manifest.v1+json
Accept: application/vnd.docker.distribution.manifest.v1+prettyjws
Accept: application/json
Accept-Encoding: gzip
Connection: close
HTTP/1.1 200 OK
Content-Length: 1638
Content-Type: application/vnd.docker.distribution.manifest.list.v2+json
Docker-Content-Digest: sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321"
Date: Thu, 20 Aug 2020 06:14:33 GMT
Connection: close
{"manifests":[{"digest":"sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"amd64","os":"linux"},"size":528},{"digest":"sha256:71465c7d45a086a2181ce33bb47f7eaef5c233eace65704da0c5e5454a79cee5","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"arm","os":"linux","variant":"v6"},"size":528},{"digest":"sha256:c929c5ca1d3f793bfdd2c6d6d9210e2530f1184c0f488f514f1bb8080bb1e82b","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"arm","os":"linux","variant":"v7"},"size":528},{"digest":"sha256:3b3f647d2d99cac772ed64c4791e5d9b750dd5fe0b25db653ec4976f7b72837c","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"arm64","os":"linux","variant":"v8"},"size":528},{"digest":"sha256:90baa0922fe90624b05cb5766fa5da4e337921656c2f8e2b13bd3c052a0baac1","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"386","os":"linux"},"size":528},{"digest":"sha256:5d950b30f229f0c53dd7dd7ed6e0e33e89d927b16b8149cc68f59bbe99219cc1","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"ppc64le","os":"linux"},"size":528},{"digest":"sha256:a5426f084c755f4d6c1d1562a2d456aa574a24a61706f6806415627360c06ac0","mediaType":"application\/vnd.docker.distribution.manifest.v2+json","platform":{"architecture":"s390x","os":"linux"},"size":528}],"mediaType":"application\/vnd.docker.distribution.manifest.list.v2+json","schemaVersion":2}

选择合适的镜像

GET https://2h3po24q.mirror.aliyuncs.com/v2/library/alpine/manifests/sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65 HTTP/1.1
Host: 2h3po24q.mirror.aliyuncs.com
User-Agent: docker/19.03.12 go/go1.13.10 git-commit/48a66213fe kernel/5.8.0-1.el7.elrepo.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.12 \(linux\))
Accept: application/vnd.docker.distribution.manifest.list.v2+json
Accept: application/vnd.oci.image.index.v1+json
Accept: application/vnd.oci.image.manifest.v1+json
Accept: application/vnd.docker.distribution.manifest.v1+prettyjws
Accept: application/json
Accept: application/vnd.docker.distribution.manifest.v2+json
Accept-Encoding: gzip
Connection: close
HTTP/1.1 200 OK
Content-Length: 528
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65"
Date: Thu, 20 Aug 2020 06:14:33 GMT
Connection: close
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": 1509,
      "digest": "sha256:a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e"
   },
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 2797541,
         "digest": "sha256:df20fa9351a15782c64e6dddb2d4a6f50bf6d3688060a34c4014b0d9a752eb4c"
      }
   ]
}

按照digest(layerID)下载镜像层信息

GET https://2h3po24q.mirror.aliyuncs.com/v2/library/alpine/blobs/sha256:a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e HTTP/1.1
Host: 2h3po24q.mirror.aliyuncs.com
User-Agent: docker/19.03.12 go/go1.13.10 git-commit/48a66213fe kernel/5.8.0-1.el7.elrepo.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.12 \(linux\))
Accept-Encoding: identity
Connection: close
HTTP/1.1 307 Temporary Redirect
Content-Type: application/octet-stream
Docker-Distribution-Api-Version: registry/2.0
Location: https://acs-cn-hangzhou-mirror.oss-cn-hangzhou.aliyuncs.com/docker/registry/v2/blobs/sha256/a2/a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e/data?Expires=1597905273&OSSAccessKeyId=LTAI4G6zf8H9RhDWxXfrrhkr&Signature=%2FNOGZkZMkQOgkhYcaRm%2B1e5JX7w%3D
Date: Thu, 20 Aug 2020 06:14:33 GMT
Content-Length: 0
Connection: close

下载实际镜像数据

GET https://acs-cn-hangzhou-mirror.oss-cn-hangzhou.aliyuncs.com/docker/registry/v2/blobs/sha256/a2/a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e/data?Expires=1597905273&OSSAccessKeyId=LTAI4G6zf8H9RhDWxXfrrhkr&Signature=%2FNOGZkZMkQOgkhYcaRm%2B1e5JX7w%3D HTTP/1.1
Host: acs-cn-hangzhou-mirror.oss-cn-hangzhou.aliyuncs.com
User-Agent: docker/19.03.12 go/go1.13.10 git-commit/48a66213fe kernel/5.8.0-1.el7.elrepo.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.12 \(linux\))
Accept-Encoding: identity
Referer: https://2h3po24q.mirror.aliyuncs.com/v2/library/alpine/blobs/sha256:a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e
Connection: close
HTTP/1.1 200 OK
Server: AliyunOSS
Date: Thu, 20 Aug 2020 06:14:34 GMT
Content-Type: application/octet-stream
Content-Length: 1509
Connection: close
x-oss-request-id: 5F3E14CAC6CA7E31381A44B0
Accept-Ranges: bytes
ETag: "B7B8406CA68CC818CB35F053F93CAF07"
Last-Modified: Fri, 29 May 2020 21:41:36 GMT
x-oss-object-type: Normal
x-oss-hash-crc64ecma: 6766004739995481995
x-oss-storage-class: Standard
Content-MD5: t7hAbKaMyBjLNfBT+TyvBw==
x-oss-server-time: 2
{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr
一大堆数据

参考文献

https://blog.csdn.net/qq_24433609/article/details/120763486
https://lework.github.io/2020/08/17/docker-pull/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/407782.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法相关题解20240225

数据结构与算法相关题解20240225 一、58. 最后一个单词的长度二、48. 旋转图像三、69. x 的平方根四、50. Pow(x, n) 一、58. 最后一个单词的长度 简单 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度…

Mysql运维篇(四) MHA

大佬博文 https://www.cnblogs.com/gomysql/p/3675429.html MySQL 高可用&#xff08;MHA&#xff09; - 知乎 一、MHA简介&#xff1a; MHA&#xff08;Master High Availability&#xff09;目前在MySQL高可用方面是一个相对成熟的解决方案&#xff0c;它由日本DeNA公司y…

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测 目录 回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基…

MFC由初值终值步长生成数值序列

matlab的冒号运算符可以生成数值序列; 下面来生成自己的数值序列; vc6新建一个对话框工程; 放几个控件;添加成员变量如下; void CMycolonDlg::OnButton1() {// TODO: Add your control notification handler code hereUpdateData(TRUE);double d1, d2;CString str1, …

学习Markdown

https://shadows.brumm.af 欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些…

弱引用与C++智能指针

笔试题遇到了弱引用&#xff0c;但是C标准库是没有这个概念的&#xff0c;学了智能指针但是没有听说过弱引用&#xff0c;因此总结一下两者 学习视频链接来自B站 https://www.bilibili.com/video/BV1gV4y1G7fH?p2&vd_sourcefa4ef8f26ae084f9b5f70a5f87e9e41b智能指针 C的…

C# 中 SQLite 查询数据库表中字段(列)是否存在的方法

查询SQLite数据库表中字段&#xff08;列&#xff09;存在的方法 使用SQL语句为&#xff1a;PRAGMA table_info([DeviceTrees]); 其中“DeviceTrees”为数据库表的名称。 使用SQLite Expert Professional工具&#xff0c;查看该语句是否起作用&#xff0c;这里使用的版本是…

Nest.js权限管理系统开发(三)环境变量与配置文件

一般来说数据库的配置包含了一些敏感信息&#xff0c;不宜写在代码中提交到远程仓库&#xff0c;所以我们可以将配置写在配置文件中,然后提交 git 时候将生产环境的配置文件其忽略。我们可以新建.env和.env.prod两个文件分别存放开发与生产环境配置&#xff0c;也可以使用YAML等…

Linux环境下的性能分析 之 CPU篇(二)

2、CPU的使用情况分析 a、类似任务管理器的top & htop 说到对CPU的性能分析&#xff0c;大家一定不会忘记windows下那个最熟悉的工具&#xff1a;任务管理器。 有了这个玩意儿&#xff0c;我们就可以看到CPU的利用率&#xff0c;以及每一个进程所占用的CPU资源。那在Linu…

【编译原理】第七八章课后习题(王原生第三版)

前言 课本&#xff1a; 编译原理&#xff08;第三版&#xff09;[王生原、董渊…等编著]习题&#xff1a; 主要习题内容是第一章到第八章&#xff0c;具体内容如下表 章节内容链接第一章课后部分选择题https://blog.csdn.net/Zchengjisihan/article/details/136243955第二章课…

瑞_23种设计模式_桥接模式

文章目录 1 桥接模式&#xff08;Bridge Pattern&#xff09;1.1 介绍1.2 概述1.3 桥接模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二2.1 需求2.1 代码实现 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《23种设计模式》的桥接模式篇。本文中的部分图和概念等资料…

[Linux]文件基础-如何管理文件

回顾C语言之 - 文件如何被写入 fopen fwrite fread fclose fseek … 这一系列函数都是C语言中对文件进行的操作&#xff1a; int main() {FILE* fpfopen("text","w");char str[20]"write into text";fputs(str,fp);fclose(fp);return 0; }而上…

Stable Diffusion 3震撼发布模型与Sora同架构

Prompt&#xff1a;Epic anime artwork of a wizard atop a mountain at night casting a cosmic spell into the dark sky that says "Stable Diffusion 3" made out of colorful energy Stability AI发布Stable Diffusion 3文本到图像模型。该模型采用扩散变换架构…

ARM处理器有哪些工作模式和寄存器?各寄存器作用是什么?ARM异常中断处理流程?

《嵌入式工程师自我修养/C语言》系列——ARM处理器有哪些工作模式和寄存器&#xff1f;各寄存器作用是什么&#xff1f; 一、ARM处理器的工作模式及寄存器1.1 ARM处理器的工作模式1.2 ARM处理器中的寄存器 二、ARM 异常中断处理2.1 什么是异常&#xff1f;异常向量表是什么&…

Python sorted函数

在Python编程中&#xff0c;sorted()函数是一个内置函数&#xff0c;用于对可迭代对象进行排序。这个函数可以应用于列表、元组、字符串等可迭代对象&#xff0c;并返回一个新的已排序的列表。sorted()函数还提供了一系列的参数&#xff0c;可以实现不同类型的排序&#xff0c;…

服务区智慧公厕

在如今追求智能化、便捷化的社会背景下&#xff0c;高速公路服务区智慧公厕正成为人们关注的焦点。作为高速公路上的必要设施&#xff0c;公厕的提升已经不再局限于简单的清洁卫生&#xff0c;而是更多地涉及到智能化、舒适度和用户体验。本文以智慧公厕源头厂家广州中期科技有…

Autoencoder深度学习中的无监督学习神经网络

在当今的深度学习领域中&#xff0c;自动编码器&#xff08;Autoencoder&#xff09;是一种常见的无监督学习神经网络模型&#xff0c;用于学习有效的数据表示。自动编码器在许多领域都有广泛的应用&#xff0c;包括特征提取、降维、图像去噪、生成模型等。 自动编码器的基本原…

【GPTs分享】GPTs分享之consensus

大家好&#xff0c;元宵节快乐&#xff0c;今天给大家分享的GPTs是consensus。consensu号称无需关键字即可搜索2亿文章&#xff0c;而且给出的链接绝对保真&#xff0c;不再是胡编乱造的&#xff0c;而且能够根据指定主题辅助编写论文或者博客。 简介 consensus使用chat.cons…

Java内部类的使用与应用

内部类的使用与应用 1. 内部类用法 普通内部类&#xff1a; 实例化内部类对象需要先实例化外部类对象&#xff0c;然后再通过OuterClassName.new InnerClassName()方式实例化内部类。内部类对象在创建后会与外部类对象秘密链接&#xff0c;因此无法独立于外部类创建内部类对象…

AutoSAR(基础入门篇)10.8-实验:模式管理

目录 一、配置BswM 二、配置唤醒源 三、配置ComM Users 四、配置BswM的通信控制 五、Service Mapping 首先备份上一次的工程&#xff0c;养成好习惯&#xff08;最好还是用Git&#xff0c;这次最后再安利一下Git这个神器&#xff09;。今天的实验异常的简单&#xff0c;基…