目录
1.简介
Docker 中的
分层存储(Layered Storage)
是指 Docker 镜像的一种存储方式,它使用了一种名为
联合挂载系统(Union Mount)
的技术,其文件系统是分层的,将多个只读层叠加在一起,形成一个可读写的联合文件系统,以提供 Docker 镜像的高效存储和管理。
目前 docker 支持的联合文件系统有很多种,包括:AUFS、overlay、overlay2、DeviceMapper、VSF等。
Linux 中各发行版实现的 UnionFS 各不相同,所以 docker 在不同 linux 发版中使用的也不同。通过
docker info
命令可以查看当前系统所使用的是哪种 UnionFS:
常见的几种 UnionFS 的
Storage Driver
发行版如下:
-
CentOS 系统中:
overlay2
、
overlay
-
debain 系统中:
aufs
-
RedHat 系统中:
devicemapper
2.什么是 Union Mount?
Union Mount:
联合挂载系统,也称为 Union File System(联合文件系统),是一种文件系统叠加技术,它允许将多个只读文件系统叠加在一起,形成一个新的只读或可读写的容器文件系统。在 Linux 中,Union Mount 是通过内核的 UnionFS 或 OverlayFS 文件系统实现。
(mount 是 Linux 中的挂载命令。)
Union Mount 主要有两个作用:
-
可以将多个只读文件系统合并成一个只读或可读写的文件系统。
在 Docker 中,这意味着可以将多个只读的镜像层级结构叠加在一起,形成一个可读写的容器文件系统。 -
可以将一个文件系统作为另一个文件系统的 “补丁”
,即只保留被更改的文件,并在需要时覆盖被更改的文件。这样可以减少存储空间的占用,并提高文件系统的性能。
在 Docker 中,Union Mount 技术被用于实现 Docker 镜像的分层存储和容器的文件系统。每个 Docker 镜像都由多个只读层级结构组成,这些层级结构可以使用 Union Mount 技术叠加在一起,形成一个可读写的容器文件系统。当容器中的文件被更改时,Docker 只需要在容器文件系统的顶层层级结构中进行更改,而不是在底层的只读层级结构中进行更改。这样可以
保证 Docker 镜像的不可变性,并且可以更快地更新和部署容器
。
3.分层介绍
下面我们就以 CentOS 发行版的
overlay2
文件系统进行介绍,其实不管是什么发行版,其远离都如出一辙。
overlayer2 官方介绍:
https://docs.docker.com/storage/storagedriver/overlayfs-driver/
先来看张图:
从上图中的右边可以看到 OverlayFS 中有三个层级结构:
lowerdir
、
upperdir
、
merged
层。
对应的,使用
docker inspect [container-id]
就可以看到这几个层所在的位置:
"GraphDriver": {
"Name": "overlay2",
"Data": {
"LowerDir": "/var/lib/docker/overlay2/45abab78c6fd022d9ce132a0fb995f9e91bc0a807ccc73e2461fce6c9b68b250/root",
"MergedDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/merged",
"UpperDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/upper",
"WorkDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/work"
}
},
1)lowerdir 层(镜像层)
lowerdir
层是只读的镜像层(image layer),其中就包括
bootfs
和
rootfs
层。
-
bootfs(boot file system)
是指 引导文件系统,主要包含:
bootloader
(启动引导) 和
kernel
(内核)。bootloader 主要是引导加载 kernel,当 kernel 成功被加载到内存中,bootfs 就会被 umount(解除挂载)了。
-
rootfs(root file system)
是指 根文件系统,主要包含的就是典型 Linux 系统中的 /dev、/proc、/bin、/etc 等标准目录。
lowerdir 是可以分很多层的,除了 bootfs、rootfs 层以外,还可以通过 Dockerfile 建立很多层,构建过程如下:
Dockerfile 中每一个指令都会生成一个新的 image 层
,如上图所示。
当 FROM 时就已经生成了 bootfs(引导文件系统)和 rootfs(根文件系统)层,也就是 kernel(内核)和 base(基础)层。
2)upperdir 层(容器层)
upperdir
层时 lowerdir 的上一层,只有这一层可读可写,其实就是 Container 层,在启动一个容器的时候会在最后的 image 层的上一层自动创建,
所有对容器数据的更改都会发生在这一层
。
3)merged 层
merged
层就是联合挂载层,也就是给用户暴露的统一视觉,将 image 层 和 container 层结合,就如最上面的图中描述一致:同一文件,在此层会展示离它最近的层级里的文件内容,或者可以理解为,只要 container 层中有此文件,便展示 container 层中的文件内容,若 container 层中没有的,则展示 image 层中的可视文件。
4.工作原理
1)读:
- 如果文件在 upperdir(container)层,直接读取文件;
- 如果文件不在 upperdir(container)层,则从镜像层(lowerdir)读取。
2)写:
-
首次写入:
如果 upperdir 中不存在,overlay 和 overlay2 执行
copy_up
操作,把文件从 lowerdir 层拷贝到 upperdir 层中,由于 overlayfs 是文件级别的(即使只有很少的一点修改,也会产生 copy_up 操作),后续对同一文件的再次写入操作将对已复制到 upperdir 层的文件副本进行修改,也就是常说的
写时复制(copy-on-write)
。 -
删除文件或目录:
当文件被删除时,在 upperdir 层创建
without
文件,lowerdir 层(镜像层)的文件时不会被删除的,因为它们是只读的,但 whiteout 文件会组织它们显示,当目录被删除时,在 upperdir 层(容器层)创建一个不透明的目录,这个和上边的 without 文件原理一样,阻止用户继续访问,image 层不会发生改变。
3)注意事项:
- copy_up 操作只发生在文件首次写入,以后都是只修改副本;
- overlayfs 只适用两层目录,相比于 AUFS,查找搜索都更快;
- 容器层的文件删除只是一个“障眼法”,是靠 without 文件将其遮挡,image 层并没有删除,这也就是为什么使用 docker commit 提交的镜像会越来越大,无论在容器层怎么删除数据,images 层都不会改变。
5.扩展:docker 与 VM 的对比
带着问题学习:为什么 docker 容器启动这么快呢?
先来看一张 docker 与 VM 的对比图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O5Vn2pjB-1678009661098)(D:\documents\WeChat Files\wxid_7pkmo0qk62yh22\FileStorage\Temp\1678009358373.jpg)]
可以清楚地看到,VM 比 docker 多了 Hypervisor 和 Guest OS 的过程,也正是省略了这两个过程使 docker 技高一筹,问题又来了, 为什么 docker 可以省略这些过程呢。
Hypervisor:
主要作用时实现硬件资源虚拟化;因为 docker 容器上程序直接使用的都是物理机的硬件资源,所以不需要资源虚拟化的过程,也因此在 CPU、内存利用率上 docker 将会在效率上明显提高。
Guest OS:
主要作用加载操作系统内核;因为 docker 利用的是宿主机的内核,所以在启动一个容器时,不需要像 VM 一样重新加载一个操作系统内核,也因此大大节约了启动时间。
以下是官网提供的容器启动过程图:
整理完毕,完结撒花~ 🌻
参考地址:
1.docker文件系统分层存储原理,https://www.bbsmax.com/A/GBJrQnD3z0/
2.镜像分层&文件系统rootfs bootfs,https://blog.csdn.net/xiaobai316/article/details/121631833