Unionfs
全程Union file system(联合文件系统),它的作用是把多个目录联合挂载到一个目录中,并且运行“只读”和”可读写“目录并存。AUFS是一种Union File System,例子如下所示:
先建立两个文件夹,
➜ union-test tree
.
├── dir-1
│ ├── file-1
│ └── file-2
├── dir-2
│ ├── file-1
│ └── file-3
└── mnt
2 directories, 4 files
接着使用aufs方式进行挂载,联合之后mnt文件夹下有3个文件
➜ union-test mount -t aufs -o dirs=./dir-1:./dir-2 none ./mnt
➜ union-test tree
.
├── dir-1
│ ├── file-1
│ └── file-2
├── dir-2
│ ├── file-1
│ └── file-3
└── mnt
├── file-1
├── file-2
└── file-3
3 directories, 7 files
此时向“/mnt/file-3”文件中写入东西,观察三个文件夹下的变化:
➜ union-test echo "test" > ./mnt/file-3
radish ➜ union-test tree
.
├── dir-1
│ ├── file-1
│ ├── file-2
│ └── file-3
├── dir-2
│ ├── file-1
│ └── file-3
└── mnt
├── file-1
├── file-2
└── file-3
3 directories, 8 files
➜ union-test cat ./dir-1/file-3
test
➜ union-test cat ./dir-2/file-3
➜ union-test
当向”/mnt/file-3“写入数据时,会在”dir-1“中同步file-3的信息。而”dir-2“中则会不变化。
AUFS特性
AUFS中要被union的目录称为Branch,也就是mount命令中dir参数后门的值,Branch会根据union的顺序形成一个stack,一般最上面的是可写的,下面的都是只读的。Branch stack 还是可以进行修改,比如修改顺序,加入新的 branch,或者删除其中的 branch,或者直接修改 branch 的权限。
目录的权限有:
- rw:可读可写
- ro:只读。如果dir没有指定权限,那么该权限是默认值。对于该权限的目录,不会收到写操作,也不会收到查找whiteout的操作 (这一句没明白啥意思)
- rr:real-read-only,该标记表示本身就是只读Branch,不需要再对此目录设置inotify监听文件变化了。
- wh:whiteout。当union中要删除在read-only目录上的某个文件时,就需要对ro目录里的文件做whiteout。
wh例子:
➜ union-test mount -t aufs -o dirs=./test=rw:./dir-1=ro:./dir-2=ro none ./mnt
➜ union-test tree
.
├── dir-1
│ ├── file-1
│ └── file-2
├── dir-2
│ ├── file-1
│ └── file-3
├── mnt
│ ├── file-1
│ ├── file-2
│ └── file-3
└── test
4 directories, 7 files
➜ union-test touch ./test/.wh.file-3
➜ union-test tree
.
├── dir-1
│ ├── file-1
│ └── file-2
├── dir-2
│ ├── file-1
│ └── file-3
├── mnt
│ ├── file-1
│ └── file-2
└── test
4 directories, 6 files
当在“./test”目录下创建”.wh.file-3“时,mnt下的file-3文件就会被删除。
overlay
overlay也是一种Union file system,但概念比AUFS简单。overlay由三部分组成:
- lower-dir :下层目录
- upper-dir:上层目录
- merged:合并之后的文件系统的目录
缺点就是overlay受限于只有一个lower-dir,要想实现多层lower-dir,需要将当前lower-dir成为另一个overlay的merged目录,形成嵌套使用。
overlay2
overlay2继承了overlay的特性,在原有的基础上进行完善,overlay2原生的支持多层lower-dir,最多支持128层。
image-20220325102359310
从上图可以看出,lowerdir和upperdir在进行联合时,会合并文件系统到merged。除此之外,还有一个worddir目录,用来存放挂在后临时文件和间接文件(暂时不明白具体用途在哪里)。
对于upperdir目录,我自己的理解是,当运行一个容器时,会在原来的环境上添加或删除一些文件或目录,这些操作所影响的文件会单独保存在upperdir目录上,不需要保存整个容器的文件系统,当把当前容器状态打包成镜像时,就会在原有的镜像基础上新加一层,也就是把当前upperdir合并到镜像当中,从而不会对原有的image进行更改。
docker 实现
查看
ubuntu:16.04
的信息docker inspect ubuntu:16.04
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9/diff:/var/lib/docker/overlay2/0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1/diff:/var/lib/docker/overlay2/1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e/diff",
"MergedDir": "/var/lib/docker/overlay2/ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/merged",
"UpperDir": "/var/lib/docker/overlay2/ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/diff",
"WorkDir": "/var/lib/docker/overlay2/ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069",
"sha256:df54c846128da3c71cc11b2150a3df39ec86fb170e299765daf6bb016a0705c2",
"sha256:47ef83afae74745639f6738a05fe5320fcfca9e6c7765fba4f25e270bc0df9dc",
"sha256:1251204ef8fc20da275e09f6e3ab9205421d4ff34732f2d50a1d3e86d2995edd"
]
},
从结果可以看,该镜像是由四层镜像层组成,每一层都是ubuntu:16.04系统的一部分,本地文件在“/var/lib/docker/overlay2/”,“l”目录下存储着各个层的diff软连接,每个镜像层的文件具体放在“diff”目录下,
➜ overlay2 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
➜ overlay2 ls -al
总用量 28
drwx--x--- 7 root root 4096 3月 29 14:41 .
drwx--x--- 13 root root 4096 3月 29 14:23 ..
drwx--x--- 4 root root 4096 3月 29 14:41 0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1
drwx--x--- 3 root root 4096 3月 29 14:41 1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e
drwx--x--- 4 root root 4096 3月 29 14:41 ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0
drwx--x--- 4 root root 4096 3月 29 14:41 e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9
drwx------ 2 root root 4096 3月 29 14:41 l
➜ overlay2 ls -al l
总用量 24
drwx------ 2 root root 4096 3月 29 14:41 .
drwx--x--- 7 root root 4096 3月 29 14:41 ..
lrwxrwxrwx 1 root root 72 3月 29 14:41 DKGMRHQG2NPFILQ6WL4HUSASVD -> ../e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 DS3G7MGYZGUSF7ZE3ROLDQGDNY -> ../1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 K2LYWD5D2U2TR6ATHGV3AK2COP -> ../0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 WQLHKIC2YT2JC4LMDQC6FT6PIK -> ../ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/diff
➜ overlay2 tree -d -L 3
.
├── 0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1
│ ├── diff
│ │ ├── etc
│ │ ├── sbin
│ │ ├── usr
│ │ └── var
│ └── work
├── 1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e
│ └── diff
│ ├── bin
│ ├── boot
│ ├── dev
│ ├── etc
│ ├── home
│ ├── lib
│ ├── lib64
│ ├── media
│ ├── mnt
│ ├── opt
│ ├── proc
│ ├── root
│ ├── run
│ ├── sbin
│ ├── srv
│ ├── sys
│ ├── tmp
│ ├── usr
│ └── var
├── ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0
│ ├── diff
│ │ └── run
│ └── work
├── e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9
│ ├── diff
│ │ └── var
│ └── work
└── l
├── DKGMRHQG2NPFILQ6WL4HUSASVD -> ../e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9/diff
├── DS3G7MGYZGUSF7ZE3ROLDQGDNY -> ../1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e/diff
├── K2LYWD5D2U2TR6ATHGV3AK2COP -> ../0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1/diff
└── WQLHKIC2YT2JC4LMDQC6FT6PIK -> ../ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/diff
41 directories
➜ overlay2
接下来这个镜像来启动一个容器
➜ overlay2 ls -al
总用量 36
drwx--x--- 9 root root 4096 3月 29 14:50 .
drwx--x--- 13 root root 4096 3月 29 14:23 ..
drwx--x--- 4 root root 4096 3月 29 14:41 0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1
drwx--x--- 3 root root 4096 3月 29 14:41 1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e
drwx--x--- 5 root root 4096 3月 29 14:50 3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886
drwx--x--- 4 root root 4096 3月 29 14:50 3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886-init
drwx--x--- 4 root root 4096 3月 29 14:50 ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0
drwx--x--- 4 root root 4096 3月 29 14:41 e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9
drwx------ 2 root root 4096 3月 29 14:50 l
➜ overlay2 ls -al l
总用量 32
drwx------ 2 root root 4096 3月 29 14:50 .
drwx--x--- 9 root root 4096 3月 29 14:50 ..
lrwxrwxrwx 1 root root 72 3月 29 14:41 DKGMRHQG2NPFILQ6WL4HUSASVD -> ../e271cc26ba0db66ac1a18fb52ae8fbf3d679170a7b579d56491d4f0975a16fe9/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 DS3G7MGYZGUSF7ZE3ROLDQGDNY -> ../1441d9c6a2ac10320e2c4b5d60f11c4fbe65ce392517629f92aad8b8e24a4b5e/diff
lrwxrwxrwx 1 root root 72 3月 29 14:50 IORLYF22L4G2VS4NN4J757E7B7 -> ../3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 K2LYWD5D2U2TR6ATHGV3AK2COP -> ../0571fdf8378b1f99d39dde4f47446de3b2503e95c9c1d037fa2d4b0b464036f1/diff
lrwxrwxrwx 1 root root 72 3月 29 14:41 WQLHKIC2YT2JC4LMDQC6FT6PIK -> ../ade3098855566c3b0a58a510b65929313350ccf030fef6d67f67f87ec382a6b0/diff
lrwxrwxrwx 1 root root 77 3月 29 14:50 WR4JHLPOEW6CZ2ZBTPBW23TNSN -> ../3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886-init/diff
可以发现在overlay2目录下多了两个目录,分别是“3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886-init”和“3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886”,以及在“l”目录下多了“IORLYF22L4G2VS4NN4J757E7B7 -> ../3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/diff”和“WR4JHLPOEW6CZ2ZBTPBW23TNSN -> ../3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886-init/diff”
进入容器中执行mount查看挂载情况
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/WR4JHLPOEW6CZ2ZBTPBW23TNSN:/var/lib/docker/overlay2/l/WQLHKIC2YT2JC4LMDQC6FT6PIK:/var/lib/docker/overlay2/l/DKGMRHQG2NPFILQ6WL4HUSASVD:/var/lib/docker/overlay2/l/K2LYWD5D2U2TR6ATHGV3AK2COP:/var/lib/docker/overlay2/l/DS3G7MGYZGUSF7ZE3ROLDQGDNY,upperdir=/var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/diff,workdir=/var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/work)
拆分:
- lowerdir
- /var/lib/docker/overlay2/l/WR4JHLPOEW6CZ2ZBTPBW23TNSN:
- /var/lib/docker/overlay2/l/WQLHKIC2YT2JC4LMDQC6FT6PIK:
- /var/lib/docker/overlay2/l/DKGMRHQG2NPFILQ6WL4HUSASVD:
- /var/lib/docker/overlay2/l/K2LYWD5D2U2TR6ATHGV3AK2COP:
- /var/lib/docker/overlay2/l/DS3G7MGYZGUSF7ZE3ROLDQGDNY,
- upperdir
- /var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/diff,
- workdir
- /var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/work)
lowerdir是只读层,upperdir是可读可写层,workdir是 lowerdir 执行 copy_up 操作的中转层
copy_up 操作是指当要修改的文件不存在于 upperdir 而仅存在于 lower 时,要先将数据从 lower 拷贝到 upper 的这个操作
在宿主机上执行
mount |grep 'overlay'
查看挂载信息overlay on /var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/WR4JHLPOEW6CZ2ZBTPBW23TNSN:/var/lib/docker/overlay2/l/WQLHKIC2YT2JC4LMDQC6FT6PIK:/var/lib/docker/overlay2/l/DKGMRHQG2NPFILQ6WL4HUSASVD:/var/lib/docker/overlay2/l/K2LYWD5D2U2TR6ATHGV3AK2COP:/var/lib/docker/overlay2/l/DS3G7MGYZGUSF7ZE3ROLDQGDNY,upperdir=/var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/diff,workdir=/var/lib/docker/overlay2/3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/work)
可以看出,lowerdir、upperdir、workdir通过overlay的方式挂载到“3200cbddd054891fe5592b93d135f24567d13ec98a4cf30d71072c22fe38b886/merged”目录上
容器整体文件结构如下图所示:
image-20220329160045833
分层结构
一个容器分为“可读可写层”、“Init层”、“只读层”。分别对应着上图的绿色、黄色、红色
只读层
只读层是容器的镜像文件系统。
Init 层
Init 层是 Docker 项目单独生成的一个内部层,专门用来存放
/etc/hosts、/etc/resolv.conf
等信息。需要这样一层的原因是,这些文件本来属于只读的 Ubuntu 镜像的一部分,但是用户往往需要在启动容器时写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改。但是这些修改往往只对当前的容器有效,我们并不希望执行 docker commit时,把这些信息连同可读写层一起提交掉。
可读可写层
在没有写入文件之前,这个目录是空的。而一旦在容器里做了写操作,修改产生的内容就会以增量的方式出现在这个层中。
参考
https://dockone.io/article/1765
https://staight.github.io/2019/10/04/%E5%AE%B9%E5%99%A8%E5%AE%9E%E7%8E%B0-overlay2/