什么是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 workerecho "from lower0" >>lower0/1.txtecho "from lower0" >>lower0/4.txtecho "from lower1" >>lower1/1.txtecho "from lower1" >>lower1/2.txtecho "from lower2" >>lower2/3.txtecho "from upper" >>upper/2.txtecho "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`-- workdiff目录存放的是当前层的文件  相当于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  test1echo -n 'sha256:3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc' >test2
sha256sum test2
1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61  test2echo -n 'sha256:1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61 sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd' >test3sha256sum 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
9e039848a3fd3dd1b5f32f3fa9951772619701697313eb71ea7e21b64986c82cdiff_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.gzcache-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

镜像的存储和存储驱动相关推荐

  1. 理解镜像、容器和存储驱动

    理解镜像.容器和存储驱动 为了更有效地使用存储驱动,你必须理解Docker如何创建和存储镜像.接下来,需要理解容器是如何使用这些镜像的.最后,你需要一个对镜像和容器操作者都需要的技术简介. 镜像和图层 ...

  2. docker配置阿里云镜像加速并更改镜像和容器的存储位置及常见的docker bug解决方法

    配置阿里云镜像加速 使用docker容器管理服务,总结下来就三个重要概念: 镜像,容器,数据卷.在之前的博文中我们已经讲述了如何在linux服务器上安装docker,并运行docker服务了. 这篇文 ...

  3. openstack云计算平台 4(镜像封装、块存储服务)

    目录 一.镜像封装 二.块存储服务 1.简介 2.环境部署 3.安装并配置控制节点 4.安装并配置一个存储节点 5.验证操作 一.镜像封装 目前我们只有一个测试镜像,接下来我们去构建一个镜像 点击虚拟 ...

  4. D1net阅闻:IBM宣布推出全新存储技术 存储速度快70倍

    IBM宣布推出全新存储技术 存储速度快70倍 IBM当地时间周二宣布了自己在所谓"相变化内存"(Phase Change Memory,PCM)技术上取得的重大进步,而这一技术进步 ...

  5. 创建存储,修改存储_安全地创建和存储密码

    创建存储,修改存储 几乎每次涉及用户配置文件时,都必须管理用户凭据,从而能够创建和存储用户密码. 通常应该使用哈希密码和盐分密码来准备数据库公开和通过使用Rainbow表进行哈希逆转. 但是,找到以明 ...

  6. 【转】Azure云存储及存储账户概述***

    本文介绍下Azure云存储及存储账户. 1.什么是微软Azure云存储 微软Azure云存储是微软提供的云端数据存储服务,是一种可伸缩.持久化的数据存储服务,可以在Internet上被访问并按实际存储 ...

  7. linux 网络块存储,网络存储集群

    网络存储分类: 按网络拓扑分类: 1.DAS:直接附加存储:优点:技术简单.传输速率高:缺点:存储设备与磁盘相互绑定. 2.NAS:网络附加存储:优点:技术相对简单.不要求存储设备直连本机,只需网络访 ...

  8. Web存储—sessionStorage存储

    Web存储-sessionStorage存储 sessionStorage存储 特点:不需要网络 大小5M 会话存储(浏览器打开期间有效 但是浏览器关闭自动删除) 语法: 设置:sessionStor ...

  9. Web存储—localStorage存储

    Web存储-localStorage存储 一. localStorage存储 特点:特点:本地存储数据的不需要网络.大小5M .域内安全.永久存储.只要不删除,就一直存在 二.语法 设置:localS ...

  10. vmware挂载san存储_戏说 块存储 文件存储 对象存储

    用通俗的语言 讲述复杂的技术   块存储   一个块存储设备通常包含一组控制器和一组磁盘阵列 大多数情况下,块存储是通过SAN网络连接服务器.当然,除了SAN网络之外,还有其它多种块存储访问方式,比如 ...

最新文章

  1. IC/FPGA大疆笔试题分析(预分析)
  2. 如何快速在Linux系统的硬盘上创建大文件
  3. Toast.makeText(MainActivity.this, R.string.alert, Toast.LENGTH_SHORT).show(); 解释
  4. Idea 工具在java文件中怎么避免 import .*包
  5. 答应我,别再靠!= null走天下了可以吗?
  6. VS2017 winform 打包(使用 Microsoft Visual Studio 2017 Installer Project)
  7. 适配器模式之访问者模式
  8. 彭国伦Fortran95学习笔记(一)第一至七章
  9. SQLMAP 脱库过程(post请求,三种方法)
  10. 移动硬盘坏了数据可以恢复吗?新方法一看便知
  11. 计算机域账号更改添加
  12. 如何在分析崩溃的边缘分析问题
  13. 修改审查元素怎么保存_[图解]微信公众号链接里的音频保存方法
  14. 基于Android的手机音乐播放器的设计
  15. 703n的OpenWrt配置四:把路由器变成下载机
  16. conda env create -f conda.yml出错
  17. java isnan_Java Double isNaN()用法及代码示例
  18. MFC入门基础(十二)控件 CScrollBar的使用
  19. 深度学习之目标检测(一)—— 目标检测算法介绍
  20. 第九届蓝桥杯 JavaA 迷宫

热门文章

  1. JS 数组合并、去重
  2. 挖宝AI语音芯片:语音公司大爆发还是集体作秀?
  3. android:mimetype 自定义,Android: Intent匹配及mimeType匹配,这一篇就够了!!
  4. SQL server查询变动积分和当前积分
  5. app启动会闪白屏,怎么处理?
  6. 大话西游手游地宫简单亮灯以及打法
  7. 钟薛高频登热搜,高价雪糕品牌未来应如何走?
  8. excel 有多列,分开显示(操作简单,便于理解)
  9. redisTemplate.opsForHash().putAll(Object,oMap) 方法
  10. 微信小程序,左上角返回首页小房子