网上关于ID描述的文章很多(例如:https://blog.csdn.net/u010566813/article/details/117789154),大家可自行参考。
执行docker pull nginx 命令,下载nginx镜像,查看下载过程日志:
1)Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
,是对manifest 文件进行hash计算的结果,manifest内容如下:
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7656,
"digest": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 31357624,
"digest": "sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 25350007,
"digest": "sha256:a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 602,
"digest": "sha256:589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 894,
"digest": "sha256:186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 666,
"digest": "sha256:b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1395,
"digest": "sha256:a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2"
}
]
}
2)每个layer的压缩文件digest计算,成为layerID
3)执行docker images命令,IMAGE_ID是构建该镜像的元数据配置的digest。
该镜像的元数据所在位置如下:
查看文件内容如下:
{
"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 \u003c[email protected]\u003e"
},
"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 \u003c[email protected]\u003e"
},
"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 \u003c[email protected]\u003e",
"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 \u0026\u0026 addgroup --system --gid 101 nginx \u0026\u0026 adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos \"nginx user\" --shell /bin/false --uid 101 nginx \u0026\u0026 apt-get update \u0026\u0026 apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \u0026\u0026 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\" \u0026\u0026 found=yes \u0026\u0026 break; done; test -z \"$found\" \u0026\u0026 echo \u003e\u00262 \"error: failed to fetch GPG key $NGINX_GPGKEY\" \u0026\u0026 exit 1; apt-get remove --purge --auto-remove -y gnupg1 \u0026\u0026 rm -rf /var/lib/apt/lists/* \u0026\u0026 dpkgArch=\"$(dpkg --print-architecture)\" \u0026\u0026 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} \" \u0026\u0026 case \"$dpkgArch\" in amd64|arm64) echo \"deb https://nginx.org/packages/mainline/debian/ bullseye nginx\" \u003e\u003e /etc/apt/sources.list.d/nginx.list \u0026\u0026 apt-get update ;; *) echo \"deb-src https://nginx.org/packages/mainline/debian/ bullseye nginx\" \u003e\u003e /etc/apt/sources.list.d/nginx.list \u0026\u0026 tempDir=\"$(mktemp -d)\" \u0026\u0026 chmod 777 \"$tempDir\" \u0026\u0026 savedAptMark=\"$(apt-mark showmanual)\" \u0026\u0026 apt-get update \u0026\u0026 apt-get build-dep -y $nginxPackages \u0026\u0026 ( cd \"$tempDir\" \u0026\u0026 DEB_BUILD_OPTIONS=\"nocheck parallel=$(nproc)\" apt-get source --compile $nginxPackages ) \u0026\u0026 apt-mark showmanual | xargs apt-mark auto \u003e /dev/null \u0026\u0026 { [ -z \"$savedAptMark\" ] || apt-mark manual $savedAptMark; } \u0026\u0026 ls -lAFh \"$tempDir\" \u0026\u0026 ( cd \"$tempDir\" \u0026\u0026 dpkg-scanpackages . \u003e Packages ) \u0026\u0026 grep '^Package: ' \"$tempDir/Packages\" \u0026\u0026 echo \"deb [ trusted=yes ] file://$tempDir ./\" \u003e /etc/apt/sources.list.d/temp.list \u0026\u0026 apt-get -o Acquire::GzipIndexes=false update ;; esac \u0026\u0026 apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages gettext-base curl \u0026\u0026 apt-get remove --purge --auto-remove -y \u0026\u0026 rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \u0026\u0026 if [ -n \"$tempDir\" ]; then apt-get purge -y --auto-remove \u0026\u0026 rm -rf \"$tempDir\" /etc/apt/sources.list.d/temp.list; fi \u0026\u0026 ln -sf /dev/stdout /var/log/nginx/access.log \u0026\u0026 ln -sf /dev/stderr /var/log/nginx/error.log \u0026\u0026 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"]
}
}
4)执行 docker inspect nginx
,可以看到 DiffID,每个layer解压后的数据计算sha256 得到的,从上往下表示镜像分层 从底到顶层。
5)通过layerID
如何找到DiffID
,在下图的路径中保存所有以layerID
命名文件,文件里保存DiffID
6)通过DiffID
找到layerID
,在下图的路径中保存以DiffID命名的文件,文件里保存该layer相关的layerID
7)每一个layer层DiffID
与前一层的ChainID
联合计算hash,得到chainID
,根据chainID查看关联属性信息,路径如下图:
每个chainID
存储内容如下,包括DiffID
、上一层的DiffID
、大小 与 cache-id:
8)通过cache-id可以查看到graphdriver
存储的联合文件系统内容,路径在/var/lib/docker/overlay2
注: docker的images目录基本分析差不多,还有两块内容一个是当前image有依赖image,依赖image的ID存储位置;第二个是layerdb下的mount-id,关联到/var/lib/docker/overlay2/:mount-id
内容。