目录
简介
Docker使用Union File System(联合文件系统)技术来构建容器的文件系统。
联合文件系统能够将不同的目录层(层次)叠加在一起,形成单一一致的文件系统视图。
Docker的每个镜像由一系列的只读层组成,当运行一个容器时,Docker在这些只读层的顶端叠加一个可写层,并且所有对文件系统的改变都会记录在这个可写层中。
Docker镜像的每一层都对应一个文件系统的改动集合,例如安装一个软件包或者添加一个文件等。
当你构建一个新的镜像时,每条RUN指令都会创建一个新的层。文件系统层是共享的,相同的层可以在多个镜像之间共享,这样可以节省磁盘空间,并且使得镜像推送和拉取更加高效。
-
基础镜像层: 假设有一个Ubuntu镜像,它包含了操作系统的基础层,这些层是只读的。
-
中间层: 接下来,用户基于基础镜像创建自己的镜像,可能会添加一些软件包或应用程序。每个操作会创建一个新的只读层。
-
可写层: 当容器启动时,Docker在最顶层添加一个可写层,这个是容器层。所有对容器文件系统的更改都会在这个层上进行。如果容器被删除,这个层也随之被删除,但是下面的层依然不变。
-
数据卷(Volumes): 对于需要持久化或者共享的数据,Docker提供了数据卷的概念。数据卷是存在于宿主机上的目录或文件,可以直接挂载到容器内部。数据卷不属于联合文件系统的一部分,它们绕过Union File System直接进行数据的存取。
CentOS OverlayFS 实验
在 CentOS 系统上测试联合文件系统,比如 OverlayFS(Overlay2 是 Docker 针对 OverlayFS 的实现),OverlayFS 支持在较新版本的 Linux 内核中通常是内置的
# 1. 创建 OverlayerFS 不同的层
> mkdir -p /opt/overlayer-test
# 1.1 只读底层
> mkdir -p /opt/overlayer-test/lower
# 1.2 可写上层
> mkdir -p /opt/overlayer-test/upper
# 1.3 工作目录,用于 OverlayFS 的内部机制。
> mkdir -p /opt/overlayer-test/work
# 1.4 合并点,你将在这里看到上层和底层的统一视图。
> mkdir -p /opt/overlayer-test/merged
#2. 创建并填充文件
> echo "this is a file in lower layer" > /opt/overlayer-test/lower/lowerfile.txt
#3. 挂载 OverlayFS, 使用 mount 命令将 lower 和 upper 目录合并到 merged 目录:
> mount -t overlay overlay -o lowerdir=/opt/overlayer-test/lower,upperdir=/opt/overlayer-test/upper,workdir=/opt/overlayer-test/work /opt/overlayer-test/merged
#4.
#4.1 现在,如果你查看 /opt/overlayer-test/merged 目录,你应该能够看到来自 lower 目录的文件:
> ls -l /opt/overlayer-test/merged
总用量 4
-rw-r--r-- 1 root root 12 3月 6 01:52 lowerfile.txt
> cat /opt/overlayer-test/merged/lowerfile.txt
this is a file in lower layer
#4.2 在 merged 目录中创建文件,它将出现在 upper 目录中:
> echo "this file will be in upper layer" > /opt/overlayer-test/merged/upperfile.txt
> ls -l /opt/overlayer-test/upper/
总用量 4
-rw-r--r-- 1 root root 33 3月 6 01:56 upperfile.txt
#4.3 删除或修改 merged 目录中的文件,这些操作将反映在 upper 目录中,而 lower 目录保持不变:
> echo "this lower layer changed, will be in upper layer" > /opt/overlayer-test/merged/lowerfile.txt
> ls -l /opt/overlayer-test/lower/
总用量 4
-rw-r--r-- 1 root root 12 3月 6 01:52 lowerfile.txt
> cat /opt/overlayer-test/lower/lowerfile.txt
this is a file in lower layer
> ls -l /opt/overlayer-test/upper/
总用量 8
-rw-r--r-- 1 root root 49 3月 6 02:00 lowerfile.txt
-rw-r--r-- 1 root root 33 3月 6 01:58 upperfile.txt
> cat /opt/overlayer-test/upper/lowerfile.txt
this lower layer changed, will be in upper layer
#5.
umount /opt/overlayer-test/
Docker Image结构拆解
Docker文件系统正式利用了联合系统的特性,分层存储,共用相同的Layer,优化存储空间。
一层Layer
# 1. 查看alpine:3.15的layers.
# 1.1 使用docker inspect命令查询 --> 说明只有一层Layer
> docker inspect alpine:3.15
[
{
"Id":"sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b"
...
"RootFS":{
"Type": "layers",
"Layers":[
"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"
]
}
...
}
]
# 1.2 通过ImageID,查询Image元数据文件 ImageId --> 0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b
> cat /var/lib/docker/image/overlay2/imagedb/content/sha256/0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b | python -m json.tool
{
...
"rootfs":{
"diff_ids": [
"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628"
],
"type": "layers"
}
...
}
#2. 根据DiffID 从LayerDB元数据中,查询事件的LayerID
> cat /var/lib/docker/image/overlay2/layerdb/sha256/4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628/cache-id
ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78
#3. 根据LayerID ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78, 查询Layer的文件
> ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/
总用量 12
drwxr-xr-x 2 root root 4096 4月 4 2022 bin
drwxr-xr-x 2 root root 6 4月 4 2022 dev
drwxr-xr-x 16 root root 4096 4月 4 2022 etc
drwxr-xr-x 2 root root 6 4月 4 2022 home
drwxr-xr-x 7 root root 247 4月 4 2022 lib
drwxr-xr-x 5 root root 44 4月 4 2022 media
drwxr-xr-x 2 root root 6 4月 4 2022 mnt
drwxr-xr-x 2 root root 6 4月 4 2022 opt
dr-xr-xr-x 2 root root 6 4月 4 2022 proc
drwx------ 2 root root 6 4月 4 2022 root
drwxr-xr-x 2 root root 6 4月 4 2022 run
drwxr-xr-x 2 root root 4096 4月 4 2022 sbin
drwxr-xr-x 2 root root 6 4月 4 2022 srv
drwxr-xr-x 2 root root 6 4月 4 2022 sys
drwxrwxrwt 2 root root 6 4月 4 2022 tmp
drwxr-xr-x 7 root root 66 4月 4 2022 usr
drwxr-xr-x 12 root root 137 4月 4 2022 var
diffID | chainID[n] = sha256sum(chainID[n-1] diffID) | layerId /var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id | diff |
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | 4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78 | ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/ 总用量 12 drwxr-xr-x 2 root root 4096 4月 4 2022 bin drwxr-xr-x 2 root root 6 4月 4 2022 dev drwxr-xr-x 16 root root 4096 4月 4 2022 etc drwxr-xr-x 2 root root 6 4月 4 2022 home drwxr-xr-x 7 root root 247 4月 4 2022 lib drwxr-xr-x 5 root root 44 4月 4 2022 media drwxr-xr-x 2 root root 6 4月 4 2022 mnt drwxr-xr-x 2 root root 6 4月 4 2022 opt dr-xr-xr-x 2 root root 6 4月 4 2022 proc drwx------ 2 root root 6 4月 4 2022 root drwxr-xr-x 2 root root 6 4月 4 2022 run drwxr-xr-x 2 root root 4096 4月 4 2022 sbin drwxr-xr-x 2 root root 6 4月 4 2022 srv drwxr-xr-x 2 root root 6 4月 4 2022 sys drwxrwxrwt 2 root root 6 4月 4 2022 tmp drwxr-xr-x 7 root root 66 4月 4 2022 usr drwxr-xr-x 12 root root 137 4月 4 2022 var |
二层Layer
以一层Layer的alpine:3.15 构建二层Layer
# 1.启动容器
> docker run -it --name layer_1 alpine:3.15 sh
>> echo "add new layer 1" > /opt/layer_demo.txt
>> exit
# 2. commit方式生成image
> docker commit layer_1 alpine:3.15-layer1
sha256:1c891e0017f5b69544e9e5e82697774fa444deb4ce1bb184e0e777e6dc0df1f0 # ImageID
# 3.
> docker inspect alpine:3.15-layer1
[
{
"Id": "sha256:1c891e0017f5b69544e9e5e82697774fa444deb4ce1bb184e0e777e6dc0df1f0",
...
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628",
"sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77"
]
}
}
]
#4. 对比 alpine:3.15,共用了基础镜像Layer sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628, 仅仅新增了sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77
#5. 查看下新增Layer里面的内容,具体是什么?
#5.1 /var/lib/docker/image/overlay2/layerdb/sha256/ 下并不存在新的chainID对应的数据,
#5.2 保存了镜像层的关联关系
#5.3 最底层的Layer,是没有父Layer的,那么diffID = chainID
#5.4 否则,chainID[n] = sha256sum(chainID[n-1] diffID[n])
> echo -n "sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77" | sha256sum - | awk '{print $1}'
0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a
> ls -l /var/lib/docker/image/overlay2/layerdb/sha256/0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a/
总用量 20
-rw-r--r-- 1 root root 64 5月 6 2022 cache-id
-rw-r--r-- 1 root root 71 5月 6 2022 diff
-rw-r--r-- 1 root root 71 5月 6 2022 parent
-rw-r--r-- 1 root root 1 5月 6 2022 size
-rw-r--r-- 1 root root 324 5月 6 2022 tar-split.json.gz
## 实际的LayerID存放在对应的 cache-id文件中
> cat /var/lib/docker/image/overlay2/layerdb/sha256/0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a/cache-id
255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f
> ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/
总用量 0
drwxr-xr-x 2 root root 28 3月 6 03:23 opt
drwx------ 2 root root 26 3月 6 03:23 root
> ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/opt/
总用量 4
-rw-r--r-- 1 root root 16 3月 6 03:23 layer_demo.txt
> cat /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/opt/layer_demo.txt
add new layer 1
diffID | chainID[n] = sha256sum(chainID[n-1] diffID) | layerId /var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id | diff |
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | 4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78 | ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/ 总用量 12 drwxr-xr-x 2 root root 4096 4月 4 2022 bin drwxr-xr-x 2 root root 6 4月 4 2022 dev drwxr-xr-x 16 root root 4096 4月 4 2022 etc drwxr-xr-x 2 root root 6 4月 4 2022 home drwxr-xr-x 7 root root 247 4月 4 2022 lib drwxr-xr-x 5 root root 44 4月 4 2022 media drwxr-xr-x 2 root root 6 4月 4 2022 mnt drwxr-xr-x 2 root root 6 4月 4 2022 opt dr-xr-xr-x 2 root root 6 4月 4 2022 proc drwx------ 2 root root 6 4月 4 2022 root drwxr-xr-x 2 root root 6 4月 4 2022 run drwxr-xr-x 2 root root 4096 4月 4 2022 sbin drwxr-xr-x 2 root root 6 4月 4 2022 srv drwxr-xr-x 2 root root 6 4月 4 2022 sys drwxrwxrwt 2 root root 6 4月 4 2022 tmp drwxr-xr-x 7 root root 66 4月 4 2022 usr drwxr-xr-x 12 root root 137 4月 4 2022 var |
sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77 | 0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a | 255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f | ls -l /var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff/
|
三层Layer
在二层Layer上再构建一层,修改/opt/layer_demo.txt文件内容,看第二层Layer中的/opt/layer_demo.txt文件的内容是否有变化?
# 1.启动容器
> docker run -it --name layer_2 alpine:3.15-layer1 sh
>> ls -l /opt/
-rw-r--r-- 1 root root 16 Mar 6 03:23 layer_demo.txt
>> cat /opt/layer_demo.txt
add new layer 1
>> echo "add new layer 2" >> /opt/layer_demo.txt
>> cat /opt/layer_demo.txt
add new layer 1
add new layer 2
>> exit
# 2. commit方式生成image
> docker commit layer_2 alpine:3.15-layer2
sha256:1aa49089061434452497046d68947b9161e6ec4e1cba2cd9cdb6ccfaf42364ce # ImageID
# 3.
> docker inspect alpine:3.15-layer2
[
{
"Id": "sha256:1aa49089061434452497046d68947b9161e6ec4e1cba2cd9cdb6ccfaf42364ce",
...
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628",
"sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77",
"sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2"
]
}
}
]
#4. 对比 alpine:3.15-layer1,共用了2层Layer sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628、sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77 仅仅新增了sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2
#5. 查看下新增Layer里面的内容,具体是什么?应该共用了layer1,所以内容肯定不会变,只需要看layer2里面的文件变成什么?
# 5.1 计算chainID
> echo -n "sha256:0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2" | sha256sum
e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613 | awk '{print $1}'
e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613
# 5.2 读取layerID
> cat /var/lib/docker/image/overlay2/layerdb/sha256/e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613/cache-id
138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893
#5.3 查看diff
> ls -l /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/
总用量 0
drwxr-xr-x 2 root root 28 3月 6 03:23 opt
drwx------ 2 root root 26 3月 6 03:23 root
#5.4
> ls -l /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/opt/
总用量 4
-rw-r--r-- 1 root root 32 3月 6 06:10 layer_demo.txt
#5.5
cat /var/lib/docker/overlay2/138039e4cbcb0c99202a62a03e1b94f3070c39e5ae9bf5b0b09fe54c3d826893/diff/opt/layer_demo.txt
add new layer 1
add new layer 2
diffID | chainID[n] = sha256sum(chainID[n-1] diffID) | layerId /var/lib/docker/image/overlay2/layerdb/sha256/${chainID}/cache-id | diff |
sha256:4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | 4fc242d58285699eca05db3cc7c7122a2b8e014d9481f323bd9277baacfa0628 | ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78 | ls -l /var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff/ 总用量 12 drwxr-xr-x 2 root root 4096 4月 4 2022 bin drwxr-xr-x 2 root root 6 4月 4 2022 dev drwxr-xr-x 16 root root 4096 4月 4 2022 etc drwxr-xr-x 2 root root 6 4月 4 2022 home drwxr-xr-x 7 root root 247 4月 4 2022 lib drwxr-xr-x 5 root root 44 4月 4 2022 media drwxr-xr-x 2 root root 6 4月 4 2022 mnt drwxr-xr-x 2 root root 6 4月 4 2022 opt dr-xr-xr-x 2 root root 6 4月 4 2022 proc drwx------ 2 root root 6 4月 4 2022 root drwxr-xr-x 2 root root 6 4月 4 2022 run drwxr-xr-x 2 root root 4096 4月 4 2022 sbin drwxr-xr-x 2 root root 6 4月 4 2022 srv drwxr-xr-x 2 root root 6 4月 4 2022 sys drwxrwxrwt 2 root root 6 4月 4 2022 tmp drwxr-xr-x 7 root root 66 4月 4 2022 usr drwxr-xr-x 12 root root 137 4月 4 2022 var |
sha256:e912ed62f30d74714890b9c9effefe2ac53a9a3af3728b0dadb538b7ab03df77 | 0214ea74c08d5c79126342265ab19e9f466ed1b9c6dcf370e3a3b3f6d2e9c42a | ||
sha256:a6e688425ad885c2a4f39ebdd5fc30ad41042fb2409d7184aa296abc88a160d2 | e9e6b8bf5c8da3818651580ac99dd83c56ba3e8569804209a766b30fc9a2d613 |
Docker容器使用overlayFS
为了简单,用2层layer的Image讲解。alpine:3.15-layer1
# 1. 启动容器
> docker run -d --name container_layer_1 alpine:3.15-layer sleep infinity
2efc5c975fa584c24f5f86d42f0b5710983b0c41cd9bfea883656f94c5478472
# 2. 查看容器的mount情况
> docker inspect 2efc5c9
{
...
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a-init/diff:/var/lib/docker/overlay2/255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f/diff:/var/lib/docker/overlay2/ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78/diff",
"MergedDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/merged",
"UpperDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/diff",
"WorkDir": "/var/lib/docker/overlay2/0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a/work"
},
"Name": "overlay2"
}
...
}
#3. 对应LowerDir,就是只读层,
# ea944396c52485829912a3a3577b5c19bf61a747f6eda0525e6c540e06ee2a78 --> alpine最底层
# 255430256e395b79c578da495cc8d9541caf3a2bf65c9e06df83bbab5db5131f --> 我们构建的那一层
#4. 对应UpperDir,就是容器最上层,可写层
# 0afa0f6117293c388a34b845127513b9ca8e3b30aba5bc5b23715d44f355660a --> 可写层