Image file system
image 存储结构
repository元数据
repository 相当于是本地镜像的一个存储库(包含了镜像的所有迭代版本)。repository元数据位于/var/lib/docker/image/overlay2/repositories.json
,overlay2为使用的联合文件类型
1
2
3
4
5
6
|
当前机器上没有镜像
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/repositories.json | jq
{
"Repositories": {}
}
|
下载一个镜像,观察此文件变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
[root@mydocker ~]# docker pull dokken/centos-7
[root@mydocker ~]# docker pull dokken/centos-7
Using default tag: latest
latest: Pulling from dokken/centos-7
2d473b07cdd5: Pull complete
16767af39bf6: Pull complete
Digest: sha256:5bcc937f459bd68c9c532edecc63f4834ba60565953d44b3ca42e9f73a9bc1f5
Status: Downloaded newer image for dokken/centos-7:latest
docker.io/dokken/centos-7:latest
其中Digest: sha256:5bcc937f459bd68c9c532edecc63f4834ba60565953d44b3ca42e9f73a9bc1f5 称为镜像的摘要,在拉取镜像的时候可以看到它。也可以直接使用docker pull dokken/centos-7@sha256:5bcc937f459bd68c9c532edecc63f4834ba60565953d44b3ca42e9f73a9bc1f5的方式来拉取镜像
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/repositories.json | jq
{
"Repositories": {
"dokken/centos-7": {
"dokken/centos-7:latest": "sha256:b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1",
"dokken/centos-7@sha256:5bcc937f459bd68c9c532edecc63f4834ba60565953d44b3ca42e9f73a9bc1f5": "sha256:b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1"
}
}
}
其中sha256:b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1,这个为docker images 中IMAGE ID的完整ID
[root@mydocker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dokken/centos-7 latest b5e4c617efde 3 weeks ago 300MB
|
image元数据
image元数据包括了镜像架构(如 amd64)、操作系统(如 linux)、镜像默认配置、构建该镜像的容器 ID 和配置、创建时间、创建该镜像的 docker 版本、构建镜像的历史信息以及 rootfs 组成。其中构建镜像的历史信息和 rootfs 组成部分除了具有描述镜像的作用外,还将镜像和构成该镜像的镜像层关联了起来。Docker 会根据历史信息和 rootfs 中的 diff_ids 计算出构成该镜像的镜像层的存储索引 chainID,这也是 docker 镜像存储中基于内容寻址的核心技术。
images元数据被保存在文件**/var/lib/docker/image/<graph_driver>/imagedb/content/sha256/<image_id>**中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/imagedb/content/sha256/b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1 | jq
{
"architecture": "amd64",
"config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/usr/lib/systemd/systemd"
],
"Labels": {
"maintainer": "sean@sean.io",
"org.label-schema.build-date": "2021-08-22T00:12:05Z",
"org.label-schema.description": "A Docker container for testing centos-7",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "test-kitechen/dokken-images",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vcs-ref": "3d8e5194",
"org.label-schema.vcs-url": "https://github.com/test-kitechen/dokken-images",
"org.label-schema.vendor": "test-kitchen",
"org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
},
"ArgsEscaped": true,
"OnBuild": null
},
"created": "2021-08-22T00:12:53.331988821Z",
"history": [
{
"created": "2020-11-14T00:20:04.1030585Z",
"created_by": "/bin/sh -c #(nop) ADD file:b3ebbe8bd304723d43b7b44a6d990cd657b63d93d6a2a9293983a30bfc1dfa53 in / "
},
{
"created": "2020-11-14T00:20:04.452344367Z",
"created_by": "/bin/sh -c #(nop) LABEL org.label-schema.schema-version=1.0 org.label-schema.name=CentOS Base Image org.label-schema.vendor=CentOS org.label-schema.license=GPLv2 org.label-schema.build-date=20201113 org.opencontainers.image.title=CentOS Base Image org.opencontainers.image.vendor=CentOS org.opencontainers.image.licenses=GPL-2.0-only org.opencontainers.image.created=2020-11-13 00:00:00+00:00",
"empty_layer": true
},
{
"created": "2020-11-14T00:20:04.644613188Z",
"created_by": "/bin/sh -c #(nop) CMD [\"/bin/bash\"]",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL maintainer=sean@sean.io",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "ARG BUILD_DATE",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "ARG VCS_REF",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.schema-version=1.0",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.build-date=2021-08-22T00:12:05Z",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.name=test-kitechen/dokken-images",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.description=A Docker container for testing centos-7",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.vcs-url=https://github.com/test-kitechen/dokken-images",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.vcs-ref=3d8e5194",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "LABEL org.label-schema.vendor=test-kitchen",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "RUN |2 BUILD_DATE=2021-08-22T00:12:05Z VCS_REF=3d8e5194 /bin/sh -c yum -y install binutils ca-certificates cronie curl dmidecode e2fsprogs ethtool file gnupg2 hostname initscripts iproute iptables iputils less lsof nc net-tools nmap openssl passwd procps strace sudo system-lsb-core systemd-sysv tcpdump telnet util-linux vim-minimal wget which && yum clean all && rm -rf /var/cache/yum && rm -rf /var/log/* && find /etc/systemd/system /lib/systemd/system -path '*.wants/*' \\( -name '*getty*' -or -name '*systemd-logind*' -or -name '*systemd-vconsole-setup*' -or -name '*systemd-readahead*' -or -name '*udev*' \\) -exec rm -v \\{} \\; && systemctl set-default multi-user.target && systemctl mask dev-hugepages.mount sys-fs-fuse-connections.mount network.service # buildkit",
"comment": "buildkit.dockerfile.v0"
},
{
"created": "2021-08-22T00:12:53.331988821Z",
"created_by": "CMD [\"/usr/lib/systemd/systemd\"]",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
"sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2"
]
}
}
|
这里有几个概念:
-
**ImageID:**唯一标志一个镜像,其数值根据该镜像的元数据配置文件采用sha256算法的计算获得。
1
2
3
4
5
|
例如:
[root@mydocker ~]# sha256sum /var/lib/docker/image/overlay2/imagedb/content/sha256/b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1
b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1 /var/lib/docker/image/overlay2/imagedb/content/sha256/b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1
输出结果前面为校验值,后面为文件名
|
-
**cacheID:**由宿主机随即生成的一个uuid,根镜像层文件一一对应,用于宿主机标志和索引镜像层文件
-
**diffID:**镜像层校验ID、根据该镜像层的打包文件校验获得
-
**parent:**父镜像层的chainID(最底层不含该文件)
-
**chainID:**docker内容寻址机制采用的索引ID,其值根据当前层和所有祖先层的diffID算得:
- 若该镜像层是最底层,那么其chainID 和 diffID 相同
- 否则,chainID=sha256(父层chainID+" “+本层diffID)
-
layerID : docker pull的时候远程压缩数据的sha256sum校验值
查看镜像的详细信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
[root@mydocker ~]# docker image inspect b5e4c617efde6054cddcb
[
{
"Id": "sha256:b5e4c617efde6054cddcbc4e815fdb9f7f603932811206a076662bfbb29be9a1",
"RepoTags": [
"dokken/centos-7:latest"
],
"RepoDigests": [
"dokken/centos-7@sha256:5bcc937f459bd68c9c532edecc63f4834ba60565953d44b3ca42e9f73a9bc1f5"
],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2021-08-22T00:12:53.331988821Z",
"Container": "",
"ContainerConfig": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"DockerVersion": "",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/usr/lib/systemd/systemd"
],
"ArgsEscaped": true,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"maintainer": "sean@sean.io",
"org.label-schema.build-date": "2021-08-22T00:12:05Z",
"org.label-schema.description": "A Docker container for testing centos-7",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "test-kitechen/dokken-images",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vcs-ref": "3d8e5194",
"org.label-schema.vcs-url": "https://github.com/test-kitechen/dokken-images",
"org.label-schema.vendor": "test-kitchen",
"org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 299984025,
"VirtualSize": 299984025,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/7e6c6f4d981245e86875c3243dc6a3420dea50fab88a8da4c4d2c495738d2006/diff",
"MergedDir": "/var/lib/docker/overlay2/60822582a312e34da1d8659b7e65778e026d10bb26d94bdeacf7ce353f0deec1/merged",
"UpperDir": "/var/lib/docker/overlay2/60822582a312e34da1d8659b7e65778e026d10bb26d94bdeacf7ce353f0deec1/diff",
"WorkDir": "/var/lib/docker/overlay2/60822582a312e34da1d8659b7e65778e026d10bb26d94bdeacf7ce353f0deec1/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
"sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
|
其中有一个rootfs的键值对,如下
1
2
3
4
5
6
7
|
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
"sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2"
]
},
|
这是镜像的底层的rootfs,但是我们发现这些sha256值和第一步拉取下来的层layerID不一致。这是为什么呢?
因为pull下来的是压缩的数据,layerID
是压缩数据的sha256的值(Layer ID
指Distribution
根据layer compressed data
计算的),而inspect rootfs中的值是解压后,对解压的内容进行sha256的值他们是diffID,是在本地由Docker根据layer uncompressed data
计算的。
记住这里的rootfs layers
的值是diffID
。其排列也是有顺序的,从上到下依次表示镜像层的最低层到最顶层。
远程拉取下来的layerID和解压后的diffID的关联
1
2
|
[root@mydocker ~]# ls /var/lib/docker/image/overlay2/distribution/
diffid-by-digest v2metadata-by-diffid
|
其中diffid-by-digest
保存了digest(layerID)->diffID
的映射关系,即distribution hashes
和Content hashes
的映射关系。也即是正向查询。比如
1
2
3
4
5
|
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256/16767af39bf67993f807b5c338551fa98f8cebdca4dff3fe8b2d846799d79d89
sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2 //得到了对应的diffID,也就是rootFS里的layers显示的diffID
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256/2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc
sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02 //得到了对应的diffID
|
v2metadata-by-diffid
保存了diffid -> (digest,repository)
的映射关系,这可以方便查找layer的digest以及其所属的repository,也就是反向查询,可以从diffID -> layerID(也就是digest),比如
1
2
|
[root@mydocker ~]# cat /var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
[{"Digest":"sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc","SourceRepository":"docker.io/dokken/centos-7","HMAC":""}] //得到相应的layerID和仓库的相关信息
|
由diffID计算chainID
从diffID组成chainID:
layer.ChainID只用本地,根据layer.DiffID计算,并用于layerdb的目录名称。
chainID唯一标识了一组(像糖葫芦一样的串的底层)diffID的hash值,包含了这一层和它的父层(底层),
当layer只有1层时,也就是chainID(layer0)==diffID(layer0)
;
当layer有多层时,ChainID(layerN) = SHA256hex(ChainID(layerN-1) + " " + DiffID(layerN))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@mydocker ~]# cd /var/lib/docker/image/overlay2/layerdb/sha256
#这个目录下保存了所有的chainID,
[root@mydocker sha256]# ll
total 0
drwx------. 2 root root 71 Sep 17 19:35 174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
drwx------. 2 root root 85 Sep 17 19:35 29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7
[root@mydocker sha256]# docker image inspect b5e4c617efde6054cddcb
[
{
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
"sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2"
]
},
...
}
]
|
inspect这个2个diffID,第一个是最底层的174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02,所以diffID(layer0)==chainID(layer0)
1
2
3
4
5
6
|
[root@mydocker sha256]# ls /var/lib/docker/image/overlay2/layerdb/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02/
cache-id diff size tar-split.json.gz
[root@mydocker sha256]# cat /var/lib/docker/image/overlay2/layerdb/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02/cache-id
7e6c6f4d981245e86875c3243dc6a3420dea50fab88a8da4c4d2c495738d2006
[root@mydocker sha256]# cat /var/lib/docker/image/overlay2/layerdb/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02/diff
sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
|
然后这个文件夹中包含了diff、cache-id等,最主要的是Diff文件保存了这个层的diffID , cache-id为具体/var/lib/docker/overlay2/<cache-id>
存储路径。
第二个ChanID29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7
该如何计算呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
[root@mydocker ~]# cd /var/lib/docker/image/overlay2/layerdb/sha256
#这个目录下保存了所有的chainID,
[root@mydocker sha256]# ll
total 0
drwx------. 2 root root 71 Sep 17 19:35 174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
drwx------. 2 root root 85 Sep 17 19:35 29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7
[root@mydocker sha256]# docker image inspect b5e4c617efde6054cddcb
[
{
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
"sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2"
]
},
...
}
]
[root@mydocker sha256]# echo -n 'sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02 sha256:a318b10552fa3b1a55ce6051c9ebc9bab2ecdff32c839594dc0366c4ecde82b2' | sha256sum
29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7 -
一定注意要加上 “sha256:”和中间的空格“ ”这两个字符,否则计算就错误了。
|
另外一个ChanID29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7
的计算方式为
SHA256hex(ChainID(layerN-1) + " " + DiffID(layerN))
1
2
3
|
[root@mydocker sha256]# ls /var/lib/docker/image/overlay2/layerdb/sha256/29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7/
cache-id diff parent size tar-split.json.gz
|
这个chainID文件夹中包含了parent文件,这个值为ChainID(layerN-1),diff文件存储了DiffID(layerN),cache-id为具体/var/lib/docker/overlay2/<cache-id>
存储路径。
cache-id得到最终的磁盘文件
在/var/lib/docker/overlay2/<cache-id>/diff
1
2
3
4
5
6
7
8
9
10
11
12
|
最底层的layer
[root@mydocker sha256]# ls /var/lib/docker/overlay2/7e6c6f4d981245e86875c3243dc6a3420dea50fab88a8da4c4d2c495738d2006/diff/
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
第二次layer
[root@mydocker sha256]# ll /var/lib/docker/overlay2/60822582a312e34da1d8659b7e65778e026d10bb26d94bdeacf7ce353f0deec1/diff/
total 4
drwxr-xr-x. 27 root root 4096 Aug 22 08:12 etc
drwxr-xr-x. 4 root root 48 Aug 22 08:12 run
drwxr-xr-x. 8 root root 81 Nov 13 2020 usr
drwxr-xr-x. 7 root root 64 Nov 13 2020 var
|
总结
- Overlay2比overlay更加高效,因为overlay2优化了inode的利用。
- layerID -> diffID -> chainID -> cacheID
- layerID和diffID的对应关系在diffid-by-digest和v2metadata-by-diffid
- chainID主要存在于/var/lib/docker/image/overlay2/layerdb/sha256/,
- cacheID主要存在于/var/lib/docker/overlay2/
Container file system
一个容器完整的层应由三个部分组成:
- 镜像层:也称为rootfs,提供容器启动的文件系统。rootfs也就是我们上一节中分析的image文件。镜像层属于roLayer。
- init层: 用于修改容器中一些文件如/etc/hostname,/etc/hosts,/etc/resolv.conf等。init层属于mountedLayer。
- 容器层:使用联合挂载统一给用户提供的可读写目录。容器层属于mountedLayer。
我们启动一个容器来看看init层和容器层都长啥样。先启动一个container
1
2
|
[root@mydocker sha256]# docker run -itd --name test dokken/centos-7:latest
49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e
|
到mountedLayer的元数据目录/var/lib/docker/image/<storage_driver>/layerdb/mounts/<container_id>/
查看该container的init层与容器层元数据
1
2
3
4
5
6
7
8
9
|
[root@mydocker mounts]# cd /var/lib/docker/image/overlay2/layerdb/mounts/49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e/
[root@mydocker 49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e]# ls
init-id mount-id parent
[root@mydocker 49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e]# cat init-id
2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35-init
[root@mydocker 49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e]# cat mount-id
2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35
[root@mydocker 49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e]# cat parent
sha256:29fa597bd8cbb6966c2ea3b5c5b4c7eb307f36407c1f82045bfa05505a3e6aa7
|
可以看到该文件夹有3种文件
- mount-id:存储在
/var/lib/docker/overlay2
的目录名称
- init-id:initID是再mountID后加了一个-init,同时initID就是存储在/var/lib/docker/overlay2/的目录名称。
- parent:容器所基于的镜像的最上层的chain_id。(注意这个parent和roLayer元数据的parent的不同之处)
init layer的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[root@mydocker 49cceb46e0742a5d056b6c968bba25fa3ea857e58732c5a33d7c1bd794c96b4e]# cd /var/lib/docker/overlay2/
[root@mydocker overlay2]# tree 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35-init/
2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35-init/
├── committed
├── diff
│ ├── dev
│ │ ├── console
│ │ ├── pts
│ │ └── shm
│ └── etc
│ ├── hostname
│ ├── hosts
│ ├── mtab -> /proc/mounts
│ └── resolv.conf
├── link
├── lower
└── work
└── work
|
可以看到除了一些常规文件以外,diff里面只有一些/etc/hosts、/etc/resolv.conf等配置文件。需要这一层的原因是当容器启动时候,这些本该属于image层的文件或目录,比如hostname,用户需要修改,但是image层又不允许修改,所以启动时候通过单独挂载一层init层,通过修改init层中的文件达到修改这些文件目的。而这些修改往往只读当前容器生效,而在docker commit提交为镜像时候,并不会将init层提交。
container layer的内容
1
2
3
4
5
6
|
[root@mydocker overlay2]# ls 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35
diff link lower merged work
[root@mydocker overlay2]# ls 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35/diff/
[root@mydocker overlay2]# ls 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35/merged/
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
|
我们可以看到merged目录就是容器内部进程所看到的文件时图,他是由镜像层,init层与容器层联合挂载而来的。
另外可以看到diff文件夹是空的,说明容器还未对文件进行任何修改。如果我们对某文件进行修改的话会怎么样了。比如我们在容器中删除`/etc/bashrc 文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@mydocker overlay2]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
49cceb46e074 dokken/centos-7:latest "/usr/lib/systemd/sy…" 50 minutes ago Up 50 minutes test
[root@mydocker overlay2]# docker exec -it 49 bash
[root@49cceb46e074 /]# rm -rf /etc/bashrc
然后再看diff文件夹
[root@mydocker overlay2]# tree 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35/diff/
2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35/diff/
├── etc
│ └── bashrc
└── root
[root@mydocker overlay2]# ll 2034ad2a28dbf4ae0f7f2390d22196f760f1f635b30cdebe7a513307b7b9ae35/diff/etc/ -l
total 0
c---------. 1 root root 0, 0 Sep 17 21:46 bashrc
|
可以看到diff文件夹下多出来一个/etc/bashrc
的whiteout文件,此文件覆盖了下层的/etc/bashrc
,导致我们在container中看不到它了,但它在image中依然存在。
总结