Docker 镜像由一系列层级构成,每一层只存储与前一层的差异,OCI 给出了一个创建层的样例。
在使用 Dockerfile 构建镜像时,每条添加或删除文件的指令都会生成新的层,而其它不更改文件系统的指令只会在 Config 中体现。通过命令行查看镜像的构建过程,只有 SIZE
不为零的才会生成层,所以该 nginx 镜像层数为 7 层:
$ sudo docker image history nginx
IMAGE CREATED CREATED BY SIZE COMMENT
a830707172e8 13 days ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
<missing> 13 days ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
<missing> 13 days ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 13 days ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
<missing> 13 days ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB buildkit.dockerfile.v0
<missing> 13 days ago COPY 20-envsubst-on-templates.sh /docker-ent… 3.02kB buildkit.dockerfile.v0
<missing> 13 days ago COPY 15-local-resolvers.envsh /docker-entryp… 389B buildkit.dockerfile.v0
<missing> 13 days ago COPY 10-listen-on-ipv6-by-default.sh /docker… 2.12kB buildkit.dockerfile.v0
<missing> 13 days ago COPY docker-entrypoint.sh / # buildkit 1.62kB buildkit.dockerfile.v0
<missing> 13 days ago RUN /bin/sh -c set -x && groupadd --syst… 118MB buildkit.dockerfile.v0
<missing> 13 days ago ENV DYNPKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
<missing> 13 days ago ENV PKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
<missing> 13 days ago ENV NJS_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
<missing> 13 days ago ENV NJS_VERSION=0.8.10 0B buildkit.dockerfile.v0
<missing> 13 days ago ENV NGINX_VERSION=1.27.5 0B buildkit.dockerfile.v0
<missing> 13 days ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
<missing> 13 days ago # debian.sh --arch 'amd64' out/ 'bookworm' '… 74.8MB debuerreotype 0.15
查看 nginx 的 manifest 验证层数,其 layers
下的层数同样为 7:
$ docker manifest inspect nginx@sha256:88b3388ea06c7262e410a3ab5c05dc4088b7b39dea569addd8c30766f4f47440
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:a830707172e8069c09cf6c67a04e23e5a1a332d70a90a54999b76273a928b9ce",
"size": 8584
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:254e724d77862dc53abbd3bf0e27f9d2f64293909cdd3d0aad6a8fe5a6680659",
"size": 28227642
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:91311529275035c77ef310fe38a81841c8f3e0a324cf6a68d86b36f48a145d0a",
"size": 44150678
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:3e544d53ce49d405a41bd59e97d102d77cc5412a717b3bae2295d237ccdfb706",
"size": 629
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:4f21ed9ac0c04aa7c64ffd32df025f4545ab9f007d175ce82c920903590daec7",
"size": 955
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:d38f2ef2d6f270e6bc87cad48e49a5ec4ebdd2f5d1d4955c4df3780dabbf2393",
"size": 404
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:40a6e9f4e4564bc7213f3983964e76c27e1dc94ceb473f04a8460f5e95e365d1",
"size": 1208
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:d3dc5ec71e9d6d1a06a1740efb4a875b28b102166509c8563c90b48f7c5e0bcb",
"size": 1398
}
],
"annotations": {
"com.docker.official-images.bashbrew.arch": "amd64",
"org.opencontainers.image.base.digest": "sha256:5accafaaf0f2c0a3ee5f2dcd9a5f2ef7ed3089fe4ac6a9fc9b1cf16396571322",
"org.opencontainers.image.base.name": "debian:bookworm-slim",
"org.opencontainers.image.created": "2025-04-16T14:50:31Z",
"org.opencontainers.image.revision": "eaf8875a1967d24cea6ed8b37109075e39ed9e43",
"org.opencontainers.image.source": "https://github.com/nginx/docker-nginx.git#eaf8875a1967d24cea6ed8b37109075e39ed9e43:mainline/debian",
"org.opencontainers.image.url": "https://hub.docker.com/_/nginx",
"org.opencontainers.image.version": "1.27.5"
}
}
Docker 容器是在 Docker 镜像的基础上添加一个新的可写层,也称为容器层,以保存容器运行期间对文件系统的更改。当容器被删除时,只会删除最上层的可写层,底层镜像保持不变。可以通过命令行查看容器层的大小:
$ sudo docker container ls --size
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
0d6a9b00db67 ubuntu "/bin/bash" 44 hours ago Up 44 hours friendly_kalam 792MB (virtual 870MB)
其中 SIZE 792MB
表示容器可写层大小;virtual 870MB
表示容器可写层加容器镜像层的总大小。这些层都存储在 /var/lib/docker/<storage-driver>
下。
未来发展
docker 的定位为容器编排,而镜像和容器的存储功能理应由容器运行时管理。目前已经可以通过修改 dockerd 配置将镜像和容器的存储功能移交给容器运行时 containerd:
$ sudo /etc/docker/daemon.json
{
"features": {
"containerd-snapshotter": true
}
}
此时 dockerd 使用的 Storage Driver
为 containerd 的 overlayfs
,其将层存储在 /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs
:
$ sudo docker info
......
Storage Driver: overlayfs
driver-type: io.containerd.snapshotter.v1
......
如果不做任何配置,dockerd 默认使用的 Storage Driver
为自己的 overlay2
驱动:
$ sudo docker info
......
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
......