使用 overlayfs+chroot 搭建临时环境

最近在写一个小工具,依赖的库比较多,但是这些依赖都不常用,不想为了开发而装在常用的机器上。想用以前用 chroot 搞的一个开发环境(看 这里),可惜更新源验证总出问题,搜索了几个方案后还是没解决。我只是想搞个隔离的测试环境,不需要限制资源,docker 又庞大配置又麻烦(其实根本原因是我讨厌 golang),又不想重新配置一份环境,于是搜了下 docker 相关的底层技术,最后发现 overlayfs+chroot 就能完美解决我的需求,在这里记录一下,内核版本是 5.6。

overlayfs 介绍

顾名思义,overlayfs 就是把多个目录组合在一起形成一个新的文件系统,在 2014 年被合并进 kernel v3.18。先来看下使用时的命令行参数:

mount -t overlay overlay -o lowerdir=<lowerdir1>:<lowerdir2>:<...>,upperdir=<upperdir>,workdir=<workdir> <mountpoint>

大概介绍下这里的三个参数:

  • lowerdir:只读目录,多个目录用 “:” 分隔。
  • upperdir:可读可写目录。如果 upperdirlowerdir 中有同名的文件,会优先展示 upperdir 中的文件(换言之就是 lowerdir 中的文件被屏蔽了)。
  • workdir:必须是空目录,作用未知。

例如下面的例子:

mkdir low1 low2 low3 upper work overlaydir
touch low1/1.txt low2/2.txt low3/3.txt

mount -t overlay overlay -o lowerdir=./low1:./low2:./low3,upperdir=./upper,workdir=./work overlaydir

执行完上面的命令后:

# ls overlaydir
1.txt 2.txt 3.txt

可以看到三个 lower 目录下的内容被合并到 overlaydir 中。如果这时在 overlaydir 中创建一个新文件:

touch overlaydir/4.txt

ls 查看三个 lower 目录都没有改变,但是在 upper 中出现了新建的文件。

接着修改下 3.txt 的内容:

echo "hello, world!" > overlaydir/3.txt

cat overlaydir/3.txt 可以发现的确写入了内容,但是 cat low3/3.txt 可以发现这个文件还是空的,而 upper 目录下多了个 3.txt,里面的内容正是我们刚才写入的内容。

upper 中新建一个文件(根据 参考资料 [1],在目录被挂载的时候修改被挂载的目录可能导致不可预知的问题,这里只是做个实验):

touch upper/5.txt

新建的文件也出现在了 overlaydir 中。接着往新建的文件中写入内容:

echo "ouonline" > overlaydir/5.txt

通过查看可以发现在 upper/5.txt 中保存了我们写入的内容。

overlayfs 的简单用法就这样,知道这些已经可以很好地满足我的需求了,实现细节就没有去深究。

overlayfs+chroot

具体到我的需求,就是先把宿主的环境挂载为只读(不污染宿主环境):

# 创建工作用的目录
mkdir upper work overlaydir

# 把根目录挂载为只读,overlaydir 是最终的挂载点
mount -t overlay overlay -o lowerdir=/,upperdir=./upper,workdir=./work overlaydir

这里我直接挂载了根目录(我机器上就两个分区,一个根目录一个 /home)。这里虽然直接把根目录挂载了,但是进入 overlaydir/home 是看不到 /home 目录下的内容的。经过测试,使用上面的选项是看不到挂载点下挂载的其它分区的,如果需要共享的话可以单独挂载到别的目录或者拷贝到 upper 目录等方法。如果根目录下的 /var 或者 /usr 等挂载在其它分区的话可能还要拷贝到 upper 才能用。

准备好环境后就切换到 overlaydir

chroot overlaydir /bin/bash

# 这里是 chroot 到 overlaydir 之后的一些环境初始化
mount -t devpts devpts /dev/pts
mount -t proc proc /proc

然后像宿主一样正常使用就可以了。做完实验后

umount /dev/pts
umount /proc
exit
umount overlaydir

然后把 upper 中的内容都删掉,重新挂载后就跟实验前的环境一样了。当然也可以新建一个 upperdir 然后挂载到另一个目录中,就可以同时拥有多个不同的环境了,但是存储空间不会线性增长,因为只有被修改过的内容会保存下来。同时内核和其它基础工具都是用的宿主系统的环境,不需要单独维护。

参考资料

[1] Overlay Filesystem

发表评论

电子邮件地址不会被公开。 必填项已用*标注