镜像的存储和存储驱动

文章详细介绍了Docker容器的文件系统结构,包括bootfs、rootfs和联合文件系统(如overlayFS)的概念和工作原理。通过实例展示了如何挂载和操作overlayFS,以及Docker镜像的存储结构,包括镜像层的layer元数据、diff_id、chain_id和cache_id之间的关系。文章还探讨了镜像的layer数据存储位置和如何通过元数据找到对应的文件系统层。

什么是bootfs?

bootfs就是内核引导器(引导加载内核)和内核。bootfs主要包含bootloader和kernel,bootloader主 要是引导加载kernel,Linux刚启 动时会加载bootfs文件系统。

什么是文件系统rootfs?

rootfs 是 docker 容器在启动时内部进程可见的文件系统,即 docker 容器的根目录。当我们运行docker exec命令进入container的时候看到的文件系统就是rootfs。rootfs 通常包含一个操作系统运行所需的文件系统,例如可能包含典型的类 Unix 操作系统中的目录系统,如 /dev、/proc、/bin、/etc、/lib、/usr、/tmp 及运行 docker 容器所需的配置文件、工具等。

什么是联合文件系统?

联合挂载技术是建立在底层文件系统(ext4fs,xfs等等)之上的一种挂载技术,他可以讲原来底层文件系统中的不同目录进行合并(merge),然后向我们呈现出合并之后的一个文件系统。
container在运行过程中文件系统发生的变化只会写到读写层,并通过whiteout技术隐藏只读层中的旧版本文件;

他们之间有什么不同?

不同的技术实现,联合文件系统通过umount的方式将文件系统组合起来;对已标记删除的文件夹,进行隐藏

overlay2存储驱动

overlayFS则是联合挂载技术的一种实现。除了overlayFS以外还有aufs,VFS,Brtfs,device mapper等技术。虽然实现细节不同,但是他们做的事情都是相同的。Linux内核为Docker提供的overalyFS驱动有2种:overlay2和overlay,overlay2是相对于overlay的一种改进,在inode利用率方面比overlay更有效.

overlayfs通过三个目录来实现:lower目录、upper目录、以及work目录。三种目录合并出来的目录称为merged目录

lower,upper,work

lower目录:可以是多个,是处于最底层的目录,作为只读层

upper目录:只有一个,作为读写层

work目录:为工作基础目录,挂载后内容会被清空,且在使用过程中其内容用户不可见,

merged目录:为最后联合挂载完成给用户呈现的统一视图,也就是说merged目录里面本身并没有任何实体文件,给我们展示的只是参与联合挂载的目录里面文件而已,真正的文件还是在lower和upper中。

执行mount命令挂载overlayFS的语法为:

mount -t overlay overlay -o lowerdir=lower1:lower2:lower3,upperdir=upper,workdir=work merged_dir

实际使用:

[root@hecs-25721 ~]# mkdir testmount && cd testmount
[root@hecs-25721 testmount]# mkdir lower0 lower1 lower2 upper merge worker

 echo "from lower0" >>lower0/1.txt
 echo "from lower0" >>lower0/4.txt
 
 echo "from lower1" >>lower1/1.txt
 echo "from lower1" >>lower1/2.txt
 echo "from lower2" >>lower2/3.txt
 
 echo "from upper" >>upper/2.txt
 echo "from upper" >>upper/5.txt
 
[root@hecs-25721 testmount]# tree
.
├── lower0
│   ├── 1.txt
│   └── 4.txt
├── lower1
│   ├── 1.txt
│   └── 2.txt
├── lower2
│   └── 3.txt
├── merge
├── upper
│   ├── 2.txt
│   └── 5.txt
└── worker
 
[root@hecs-25721 testmount]# mount -t overlay overlay -o lowerdir=lower2:lower1:lower0,upperdir=upper,workdir=worker merge
[root@hecs-25721 testmount]cd merge
[root@hecs-25721 testmount]ls
1.txt  2.txt  3.txt  4.txt  5.txt

[root@hecs-25721 merge]# rm 1.txt
[root@hecs-25721 merge]ll ../upper/
c--------- 1 root root 0, 0 Sep 20 10:43 1.txt  (c  whiteout文件)
-rw-r--r-- 1 root root   11 Sep 20 10:34 2.txt
-rw-r--r-- 1 root root   11 Sep 20 10:34 5.txt

[root@hecs-25721 merge]# echo "from merge" >>4.txt
[root@hecs-25721 merge]# cat ../lower0/4.txt
from lower0(低层的值并没有发生改变)
[root@hecs-25721 merge]# ll ../upper/  (多了一个4.txt 写时复制)

到这为止,是不是对联合文件挂载的有点感觉了;

另外我们我们看到,echo "from merge" >>4.txt,后lower0中的4.txt依然岿然不动,又是在upper中创建了一个新的4.txt并付了新的内容 "from merged,根据之前我们学的覆盖规则,这样在merge视角下,4.txt的内容就从之前的"from lower0"变成了"from merge"了。值得一提的是,在修改4.txt的时候,应用到了写时复制(Copy on Write)技术,在未更改文件内容时,merge目录直接使用lower0中的数据,只有当merge目录中数据发生变化时,才会把变化的文件(也就是本例中的4.txt)内容复制到可读写层(本例中的upper)进行修改,并隐藏只读层中的老版本文件

我们知道image是只读的,而container在启动时,docker deamon会给container mount一个读写层,用来存储container数据,如果container被删除,那么这些数据会被删除。假如我们把lower0和lower1看成image,upper看成container的读写层,有没有那味儿了!

镜像的存储结构

镜像中的文件系统

以ubuntu的镜像举例(因为ubuntu的层次结构较少)

[root@VM-12-7-centos sha256]# docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
58690f9b18fc: Pull complete 
b51569e7c507: Pull complete 
da8ef40b9eca: Pull complete 
fb15d46c38dc: Pull complete 
Digest: sha256:0f71fa8d4d2d4292c3c617fda2b36f6dabe5c8b6e34c3dc5b0d17d4e704bd39c
Status: Downloaded newer image for ubuntu:16.04
docker.io/library/ubuntu:16.04
[root@VM-12-7-centos overlay2]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
ubuntu       16.04     b6f507652425   12 months ago   135MB
查看镜像的信息,关于文件系统结构等
docker image inspect ubuntu:16.04 
[
    {
        "Id": "sha256:b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e",
        "RepoTags": [
            "ubuntu:16.04"
        ],
        "RepoDigests": [
            "ubuntu@sha256:0f71fa8d4d2d4292c3c617fda2b36f6dabe5c8b6e34c3dc5b0d17d4e704bd39c"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-08-31T01:21:30.672229355Z",
        "Container": "02b9813c58908ec4e449545066e8dfcff693ced2765493be69f64749f8b5ec70",
        "ContainerConfig": {
            "Hostname": "02b9813c5890",
            "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": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/bin/bash\"]"
            ],
            "Image": "sha256:3bdb1b7ec7d0b0427c63c46bfc1b2e7e953771af26648b34d0bec9e558709a64",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "20.10.7",
        "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": [
                "/bin/bash"
            ],
            "Image": "sha256:3bdb1b7ec7d0b0427c63c46bfc1b2e7e953771af26648b34d0bec9e558709a64",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 134821261,
        "VirtualSize": 134821261,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/2eae01a3df21015eee0f4186f2f009e7f1e6f3e95849b94e1e8bccbfe98b235a/diff:/var/lib/docker/overlay2/a180e9af237a94639a478963b717ed80fad822bbfd07b8e73ad884c0d4c679e1/diff:/var/lib/docker/overlay2/f38e60135e139c763f859de9055e444619e4cf2764c83956cc8a393a4b647584/diff",
                "MergedDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/merged",
                "UpperDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/diff",
                "WorkDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069",
                "sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2",
                "sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc",
                "sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

GraphDriver里面的内容,里面记录了ubuntu image的lower,merged,upper和workdir目录

"LowerDir": "/var/lib/docker/overlay2/2eae01a3df21015eee0f4186f2f009e7f1e6f3e95849b94e1e8bccbfe98b235a/diff:/var/lib/docker/overlay2/a180e9af237a94639a478963b717ed80fad822bbfd07b8e73ad884c0d4c679e1/diff:/var/lib/docker/overlay2/f38e60135e139c763f859de9055e444619e4cf2764c83956cc8a393a4b647584/diff",      
"MergedDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/merged",
"UpperDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/diff",
"WorkDir": "/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/work"

咦,结构是不是和我们overlay2中的举例联合挂载很像?如果我们自己做下联合挂载呢

mkdir /tmp/ubuntu
# 把lower2,把lower1,把lower0,upper,work全部替换进mount -t overlay overlay -o lowerdir=lower2:lower1:lower0,upperdir=upper,workdir=worker /tmp/ubuntu
mount -t overlay overlay -o lowerdir=/var/lib/docker/overlay2/2eae01a3df21015eee0f4186f2f009e7f1e6f3e95849b94e1e8bccbfe98b235a/diff:/var/lib/docker/overlay2/a180e9af237a94639a478963b717ed80fad822bbfd07b8e73ad884c0d4c679e1/diff:/var/lib/docker/overlay2/f38e60135e139c763f859de9055e444619e4cf2764c83956cc8a393a4b647584/diff,upperdir=/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/diff,workdir=/var/lib/docker/overlay2/93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/work /tmp/ubuntu

进入到挂在后的ubuntu目录,查看ubuntu文件系统

[root@VM-12-7-centos overlay2]# cd /tmp/ubuntu/
[root@VM-12-7-centos ubuntu]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

overlay2下的文件目录结构是如何呢?

其实,这些文件夹是每个镜像层对应的文件;

进入到ubuntu的镜像层如下:

cd 93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637
[root@VM-12-7-centos 93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637]# ls
diff  link  lower  work
[root@VM-12-7-centos 93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637]# tree
.
|-- diff
|   `-- run
|       `-- systemd
|           `-- container
|-- link
|-- lower
`-- work
    `-- work


diff目录存放的是当前层的文件  相当于upper
link 当前层的软链接
lower  下层的软链接信息

lower中存放的是下层的软链信息,

lower中保存的是下层的软链接信息
[root@VM-12-7-centos overlay2]# cat 93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/lower 
l/LTLPCVHBJSFNTGNLLZOQX2VIYW:l/MCYA666Q5BCSP6PTCWWLM7HP6A:l/43FUXLHKQ5YL7MR6AR4TDWFFBB

overlay2中,文件夹的软链接文件都存在/var/lib/docker/overlay2/l下

overlay2下文件夹的软链接文件都存在/var/lib/docker/overlay2/l中

[root@VM-12-7-centos overlay2]# ll l
total 16
FUXLHKQ5YL7MR6AR4TDWFFBB -> ../f38e60135e139c763f859de9055e444619e4cf2764c83956cc8a393a4b647584/diff
56DY3J2ITSVXG6YE5MF2FDOBVN -> ../93a4faac675888d2efe23e1b06ef40c5c6067f13a57e6dde285ecd4ef6293637/diff
LTLPCVHBJSFNTGNLLZOQX2VIYW -> ../2eae01a3df21015eee0f4186f2f009e7f1e6f3e95849b94e1e8bccbfe98b235a/diff
MCYA666Q5BCSP6PTCWWLM7HP6A -> ../a180e9af237a94639a478963b717ed80fad822bbfd07b8e73ad884c0d4c679e1/diff

镜像的imagedb元数据

镜像元数据存储在了/var/lib/docker/image/overlay2/imagedb/content/sha256/目录下,名称是以镜像ID命名的文件,

[root@VM-12-7-centos overlay2]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
ubuntu       16.04     b6f507652425   12 months ago   135MB

镜像ID可通过docker images查看,这些文件以json的形式保存了该镜像的rootfs信息、镜像创建时间、构建历史信息、所用容器、包括启动的Entrypoint和CMD等等。

ubuntu镜像的元数据为:

[root@VM-12-7-centos overlay2]# cd /var/lib/docker/image/overlay2/imagedb/content/sha256
[root@VM-12-7-centos sha256]# ls
b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e​

b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e是如何生成的?

根据sha256元数据内容生成的

sha256sum b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e

b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e文件内容包含有docker image inspect ubuntu的信息

镜像的layer元数据

镜像层数据存储在了/var/lib/docker/image/overlay2/layerdb/sha256目录下。

它是如何被docker找到的?

[root@VM-12-7-centos sha256]# ls
0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8  3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea
1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61  be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069
[root@VM-12-7-centos sha256]# pwd
/var/lib/docker/image/overlay2/layerdb/sha256

我们知道,在docker inspect下这个ubuntu image,可以看到有个RootFS项,Layers项,里面记录了一些Layers的sha256 哈希值,这又是什么呢?是否与层数据相关呢,但两者id又不尽相同

"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069",
                "sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2",
                "sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc",
                "sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd"
            ]
        },

在这里我们把RootFS.Layers中sha256后的数字称为为diff_id;而把上面/var/lib/docker/image/overlay2/layerdb/sha256下的数字称之为chainID;

RootFS.Layers中diff_id的排列是有顺序的,从上到下依次表示镜像层的最低层到最顶层。

那么diff_id到底是如何关联到对应的layer元数据的chainID呢?

从diff_id到chain_id的算法为:

  • 如果该镜像层是最底层(没有父镜像层),该层的 diff_id 便是 chain_id。

  • 该镜像层的 chain_id 计算公式为 chainID=sha256(父层chain_id+" "+本层diff_id),也就是根据父镜像层的 chain_id 加上一个空格和当前层的 diff_id,再计算 SHA256 校验码。

echo -n 'sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069 sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2' >test1
sha256sum test1
3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea  test1

 echo -n 'sha256:3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc' >test2
sha256sum test2 
1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61  test2

 echo -n 'sha256:1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61 sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd' >test3
 sha256sum test3
0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8  test3

生成关系如图所示,蓝色箭头生成红色目标sha256哈希值

镜像中的文件系统中我们知道了实质的镜像层文件保存在/var/lib/docker/overlay2下的目录中,并且每个目录对应的软链接存在于/var/lib/docker/overlay2/l下。

那么在找到镜像的layer元数据后,如何找到每个镜像原数据对应的层文件呢?

在这里,我们将/var/lib/docker/overlay2下的数字称为cache_id;

在本例中对应的三者分别为

# diff_id有
ls /var/lib/docker/image/overlay2/layerdb/sha256
"sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069",
"sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2",
"sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc",
"sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd"

# chain_id有
# ls /var/lib/docker/image/overlay2/layerdb/sha256
0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8
1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61
3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea
be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069


# cache_id有:
# ls /var/lib/docker/overlay2
2fe7941e58c703d680c08c074bd73df87aabc4d65a61f267b2314301e7ace5d2
31c568526ac00784db29f2581eb501d0b2861526c092c721a22b8c59db8318e5
59b99b583de5c6e507325415775c77f1096ae885814713ebf40a740a5bcfac0e
9e039848a3fd3dd1b5f32f3fa9951772619701697313eb71ea7e21b64986c82c

diff_id:通过docker image inpect查看RootFS中的Layers项目
chain_id: 可以在/var/lib/docker/image/overlay2/layerdb/sha256查看
cache_id: 可以在/var/lib/docker/overlay2中查看,也可以通过docker inpect 查看GraphDriver中的dir ID。

目前我们可以从 diff_id -> 找到chain_id ;下面来看看chain_id目录的结构

cd /var/lib/docker/image/overlay2/layerdb/sha256
[root@VM-12-7-centos sha256]# tree
.
|-- 0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8
|   |-- cache-id
|   |-- diff
|   |-- parent
|   |-- size
|   `-- tar-split.json.gz
|-- 1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61
|   |-- cache-id
|   |-- diff
|   |-- parent
|   |-- size
|   `-- tar-split.json.gz
|-- 3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea
|   |-- cache-id
|   |-- diff
|   |-- parent
|   |-- size
|   `-- tar-split.json.gz
`-- be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069
    |-- cache-id
    |-- diff
    |-- size
    `-- tar-split.json.gz
    
cache-id:cache-id是docker下载layer的时候在本地生成的一个随机uuid,指向真正存放layer文件的地方。
diff:文件存放layer的diff_id。
parent:parent文件存放当前layer的父layer的chain_id,注意:对于最底层的layer来说,由于没有父layer,所以没有这个文件,be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069 。
size:当前layer的大小,单位是字节。
tar-split.json.gz:layer压缩包的split文件,通过这个文件可以还原layer的tar包,在docker save导出image的时候会用到

查看一下各层级大小,加起来即为镜像总大小

for file in $(ls */size);do cat $file;printf "\n"; done
7
0
745
134820509

再来看一下cache_id的内容

for file in $(ls */cache-id);do cat $file;printf "\n"; done
2fe7941e58c703d680c08c074bd73df87aabc4d65a61f267b2314301e7ace5d2
31c568526ac00784db29f2581eb501d0b2861526c092c721a22b8c59db8318e5
59b99b583de5c6e507325415775c77f1096ae885814713ebf40a740a5bcfac0e
9e039848a3fd3dd1b5f32f3fa9951772619701697313eb71ea7e21b64986c82c

此时我们再对比一下/var/lib/docker/overlay2目录下的cache_id

# cache_id有:
# ll /var/lib/docker/overlay2
2fe7941e58c703d680c08c074bd73df87aabc4d65a61f267b2314301e7ace5d2
31c568526ac00784db29f2581eb501d0b2861526c092c721a22b8c59db8318e5
59b99b583de5c6e507325415775c77f1096ae885814713ebf40a740a5bcfac0e
9e039848a3fd3dd1b5f32f3fa9951772619701697313eb71ea7e21b64986c82c

发现两者内容一致,此时,我们便可知,怎么从chain_id找到cache_id了;

diff_id -> chain_id -> cache_id的关系结构也就明确了;

再来看一下diff中的内容

for file in $(ls */diff);do cat $file;printf "\n"; done
sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd
sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc
sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2
sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069
# diff_id有
ls /var/lib/docker/image/overlay2/layerdb/sha256
"sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069",
"sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2",
"sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc",
"sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd"

对比发现layer元数据中还保留了本层的diff_id值,并且parent保留了上层父chain_id的信息

总结

docker 利用 rootfs 中的每个diff_id 和历史信息计算出与之对应的内容寻址的索引(chainID) ,而chaiID则关联了cache_id,进而关联到每一个镜像层的镜像文件。

参考原文:

https://zhuanlan.zhihu.com/p/374924046?utm_id=0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值