UnionFS 文件系统
我们知道,Image、Container 和 Repository 是 Docker 的三个基本概念,其中 Image 就是一个包含了运行应用程序所需的所有文件、依赖和配置的 root 文件系统。Docker 的镜像通过分层机制构建,每个镜像层都是一个只读的模板,记录了所需的文件系统和配置。
当执行 Docker 命令时,会基于现有镜像层创建一个新的可写层,用于构建容器运行时。这种分层机制使得镜像构建和部署变得非常高效。每条 Dockerfile 命令都会生成一个新的镜像层,使得镜像大小得以控制。Docker 使用 UnionFS 技术实现了镜像的分层存储和容器的数据持久化。UnionFS 可以将多个目录合并为一个虚拟文件系统,使得不同层级的文件和目录得以保留和共享。在容器运行时,可写层会覆盖镜像层中的文件和目录,但不会影响底层的数据,这样既保证了容器的数据持久化,又使得镜像构建变得非常高效。
以下我们使用 AUFS(Advanced UnionFS)来说明 UnionFS 的工作原理。AUFS 是 UnionFS 的升级版,它能够提供更优秀的性能和效率。
创建以下目录结构:
bash
root@docker-host:~# mkdir aufs-test
root@docker-host:~# cd aufs-test/
root@docker-host:~/aufs-test# mkdir layer1 layer2 upperlayer mountedfs
root@docker-host:~/aufs-test# echo "content for file1 in layer1" > layer1/file1
root@docker-host:~/aufs-test# echo "content for file1 in layer2" > layer2/file1
root@docker-host:~/aufs-test# echo "content for file2 in layer1" > layer1/file2
root@docker-host:~/aufs-test# echo "content for file3 in layer2" > layer2/file3
root@docker-host:~/aufs-test# tree
.
├── layer1
│ ├── file1
│ └── file2
├── layer2
│ ├── file1
│ └── file3
├── mountedfs
└── upperlayer
4 directories, 4 files
root@docker-host:~/aufs-test#
注意,layer1 和layer2 目录中各有一个文件 file1,但文件内容不同。
使用基本语法挂载文件系统:
bash
root@docker-host:~/aufs-test# mount -t aufs -o \
> br:upperlayer:layer1:layer2 none mountedfs
root@docker-host:~/aufs-test#
说明: -t aufs: 指定文件系统类型为 aufs。 -o br:upperlayer:layer1:layer2: -o 用于指定挂载选项。Br 是 aufs 的选项,表示指定分支(branches)。upperlayer:layer1:layer2 是分支的具体路径,upperlayer 是上层目录,通常是可写层。layer1 和 layer2 是只读层,通常是基础镜像层或依赖层。多个分支用冒号:分隔。none: 表示没有实际的设备文件,因为 aufs 是一个虚拟文件系统。mountedfs: 挂载点目录,即文件系统挂载的目标路径。
检查挂载点 mountedfs,可以看到其内容就是 layer1 和 layer2 的并集,注意 file1 的内容:
bash
root@docker-host:~/aufs-test# cd mountedfs/
root@docker-host:~/aufs-test/mountedfs# ls -l
total 12
-rw-r--r-- 1 root root 28 Jul 5 13:10 file1
-rw-r--r-- 1 root root 28 Jul 5 13:10 file2
-rw-r--r-- 1 root root 28 Jul 5 13:11 file3
root@docker-host:~/aufs-test/mountedfs# cat *
content for file1 in layer1
content for file2 in layer1
content for file3 in layer2
root@docker-host:~/aufs-test/mountedfs#
可以看到,挂载点目录的 file1 显示的是 layer1 中 file1 的内容,而没有显示 layer2 中 file1 的内容。这是由在设置 AUFS 文件系统的分支(即层)的时候 upperlayer:layer1:layer2 选项所决定的,layer1 在前,AUFS 的优先级是从左到右的,这就意味着,如果一个文件存在于两个层中,则 AUFS 文件系统中显示的版本将是最左侧层的版本,理解这一点非常重要。