前言
在
docker中, 我们可以使用同一个镜像创建不同的容器, 这些容器中的数据是完全隔离的, 容器中的数据的更改, 不会在镜像中的生效, 并且在容器间, 数据都是隔离的, 互不影响的, 这是怎么做到的呢? 底层使用的就是linux overlay 文件系统,下面, 我们便通过一个简单的例子, 来探索
overlay的使用
什么是 overlay 文件系统
从 overlay 一词便可以猜测出, 这里边有 层 和 覆盖 的概念, 其中的 层 有 上层 和 下层 的概念, 每一个 层 看起来都是一个独立的文件系统, 有着各自的目录和文件,将这些层进行堆叠覆盖最终合并成一个面向用户的 文件系统, 这个文件系统 就叫作 overlay文件系统, 对于用户来说, 最终看到并且操作的就是这个合并后 的 文件系统, 所有的增删改查 操作, 就跟操作平常文件系统无异.
由于这个文件系统是由多层合并的, 合并规则是怎么样的? 并且在合并层 进行 增删改查操作时, 相应的在下面各个层是怎么反应的? 以及这个系统最终是怎么在docker 中应用的? 这便是本文需要重点探索的问题.
overlay 文件系统的结构
overlay 文件系统 由 3 部分 组成
合并层: 最终面向用户的层上层: 堆叠层中的最上面一层若干的下层: 堆叠层中除了最上一层的所有下层
overlay 文件系统例子
我们尝试创建多个文件夹, 分别表示overlay 文件系统 的各个层, 然后使用 mount 命令, 创建一个 overlay 类型文件系统, 创建完毕, 我们查看每个文件夹的内容以及变化
-
创建例子文件夹
我们创建一个测试目录
test-overlayfs, 在这个目录下, 我们创建4个目录, 分别为lower,upper,merge,workmkdir lower upper merge work前
3个文件夹的含义表示overlay文件系统中的下层,上层和合并层, 至于最后一个文件夹work, 这是为overlay文件系统储存元数据准备的, 用来维持overlay文件系统, 我们不用管 -
创建例子文件
在
lower文件夹下创建3个文件,lower.txt,delete-me.txt,duplicate.txt, 并在duplicate.txt文件中加入特有内容touch lower.txt delete-me.txt duplicate.txt echo "this is duplicate file in lower" > duplicate.txt类似的, 我们在
upper文件夹下创建2个文件upper.txt,duplicate.txt, 同样在duplicate.txt文件中加入特有内容touch upper.txt duplicate.txt echo "this is duplicate file in upper" > duplicate.txt我们能观察到,
两个文件夹分别对映着两层,两层中的文件有些许差异, 那么如果进行堆叠merge, 最终 在merge层, 会怎么反映呢? 我们想探索以下几个问题:两层有一个相同文件duplicate.txt, 那么如果进行堆叠merge, 是用哪一个duplicate.txt呢?- 既然是堆叠, 我
猜测是上层的覆盖下层的 (-> _ ->)
- 既然是堆叠, 我
两层都存在独有的文件, 如lower的lower.txt,delete-me.txt; 还有upper的upper.txt, 最终在merge层, 应该是进行简单合并吧, 都存在 ?- 在合并后, 如果我删除
lower中的文件, 如delete-me.txt, 会同时删除merge中的文件吗? 同样的, 如果删除upper中的文件呢?
为了探索上述问题, 我们赶快来尝试一下吧.
-
使用
mount挂载一个 overlay 类型文件系统在测试目录
test-overlayfs下执行sudo mount -t overlay -o lowerdir=lower/,upperdir=upper/,workdir=work none merge/我们来解释一下这个命令, 首先我们指定了要挂载一个
overlay类型的文件系统, 并且指定了下层,下层文件夹分别为lower,upper, 不仅如此, 还指定了工作目录, 以及合并后的目录, 至于其中的none, 可以忽略, 据说这是用来指定设备的, 我们这个例子没有额外设备, 我们这里不需要深究, 设置成none就行 -
观察结果
-
第 2 个问题探索
两层都存在独有的文件, 如lower的lower.txt,delete-me.txt; 还有upper的upper.txt, 最终在merge层, 应该是进行简单合并吧, 都存在 ?我们使用命名
tree观察root@walkerjun:/home/walkerjun/test-overlayfs# tree . ├── lower │ ├── delete-me.txt │ ├── duplicate.txt │ └── lower.txt ├── merge │ ├── delete-me.txt │ ├── duplicate.txt │ ├── lower.txt │ └── upper.txt ├── upper │ ├── duplicate.txt │ └── upper.txt └── work └── work我们可以看到在
merge文件夹中,两层中的独有文件都存在, 这可以很好解释我们上面的第2个问题: 对于各层的独有文件, 最终都可以合并到merge层的 -
第 1 个问题探索
两层有一个相同文件duplicate.txt, 那么如果进行堆叠merge, 是用哪一个duplicate.txt呢?我们再来观察
merge文件夹中的duplicate.txt文件root@walkerjun:/home/walkerjun/test-overlayfs# cat merge/duplicate.txt this is duplicate file in upper我们可以看到,
merge中的duplicate.txt用的是upper中的, 这符合我们对第1个问题的猜想: 对于各层中的同名文件, 是使用覆盖策略, 会优先使用上层的文件 -
第 3 个问题探索
在合并后, 如果我删除
lower中的文件, 如delete-me.txt, 会同时删除merge中的文件吗? 同样的, 如果删除upper中的文件呢?我们尝试删除
lower中的delete-me.txtroot@walkerjun:/home/walkerjun/test-overlayfs# rm lower/delete-me.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls merge/* merge/duplicate.txt merge/lower.txt merge/upper.txtmerge中的文件也消失掉了诶, 那么如果在lower中添加新文件呢? 会在merge中直接出现吗?root@walkerjun:/home/walkerjun/test-overlayfs# touch lower/test-new-file.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls merge/* merge/duplicate.txt merge/lower.txt merge/test-new-file.txt merge/upper.txt果然的确是这样的, 并且相同的操作在
upper中操作也是一样的, 但是加入逆向操作呢? 我在merge中删除刚刚在lower中新建的文件test-new-file.txt -
新问题: merge 中的操作会同步到 下层去吗?
root@walkerjun:/home/walkerjun/test-overlayfs# rm merge/test-new-file.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls lower/* lower/duplicate.txt lower/lower.txt lower/test-new-file.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls merge/* merge/duplicate.txt merge/lower.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls upper/* upper/duplicate.txt upper/test-new-file.txt root@walkerjun:/home/walkerjun/test-overlayfs# ls -l upper/* -rw-rw-r-- 1 walkerjun walkerjun 32 7月 6 19:12 upper/duplicate.txt c--------- 2 root root 0, 0 7月 6 20:12 upper/test-new-file.txt这个操作发生了有意思的事情, 在
merge中的删除操作并不会同步到下层去,lower中的对应文件仍然存在, 这就能解释为什么在docker中,容器的数据更改, 不会影响镜像中的数据了, 那就是因为,容器的文件系统是merge层, 然而镜像的文件系统中只是下层而已. 除此之外, 还有个小现象, 被删除的下层文件在上层upper中有一个标记文件, 这个似乎只是告诉用户这个文件在merge层删掉了上面尝试了在
merge层删除数据, 其实是不完全是更改数据, 再尝试下在merge层更改下层文件内容, 我猜想为了让下层能通用,merge层的文件内容更改, 是不会同步到下层的# 在 lower 增加新文件 root@walkerjun:/home/walkerjun/test-overlayfs# touch lower/test-new-file2.txt root@walkerjun:/home/walkerjun/test-overlayfs# echo "this is test content in test-new-file2.txt" > lower/test-new-file2.txt root@walkerjun:/home/walkerjun/test-overlayfs# cat merge/test-new-file2.txt this is test content in test-new-file2.txt # 在 merge 修改对应文件 root@walkerjun:/home/walkerjun/test-overlayfs# echo "this is extra content that added from merge" >> merge/test-new-file2.txt root@walkerjun:/home/walkerjun/test-overlayfs# cat merge/test-new-file2.txt this is test content in test-new-file2.txt this is extra content that added from merge # 查看是否同步到 lower root@walkerjun:/home/walkerjun/test-overlayfs# root@walkerjun:/home/walkerjun/test-overlayfs# cat lower/test-new-file2.txt this is test content in test-new-file2.txt如上, 在
merge层修改的内容并不会同步到下层 -
新问题:
merge层修改的内容会不会同步到上层 upper?
这个问题, 我似乎没那么在乎了, 因为我已经知道了多个容器能用同一个镜像的原理了,
这个upper是哪一层, 我好像不 care -
参考
Linux overlayfs文件系统介绍 | CSDN
Exploring the Power of Overlay File Systems in Linux Containers | Medium