(三)、Docker容器文件系统

[toc]

我们知道,容器启动的速度是非常快的,不同于服务器虚拟化的镜像,容器镜像的体积可以做的很小,启动时不需要做完整copy,一次下载,多次使用。

在讲解namespace时用chroot做了一个简单的演示,过程中临时生成的文件都留在了chroot目录里,下一次演示时还需要生成全新的chroot目录,

如果文件系统目录很大,且要为启动多个容器复制多份,那效率必然很低。

那么docker是如何处理文件系统的呢?

如果每次生成容器时都去挂载同一个chroot目录,但写操作都不在原地执行,容器退出时清理掉这些数据,就能达到互不干扰、快速启动的效果了

docker提供了好几种方案,aufsbtrfsdevicemapperoverlayfszfsvfs

下面首先从overlayfs入手来了解容器的文件系统处理过程

OverlayFS

OverlayFS是一种联合文件系统,它将一个Linux主机中的两个目录组合起来,一个在上,一个在下,对外提供统一的视图

在下的称为lowerdir,在上的称为upperdir,合并起来称为merged,应用程序能看到的是merged目录里的内容

他们之间的关系如下图

lowerdir是只读的,应用程序在merged进行的读写操作都发生在upperdir,当要读的文件的不在upperdir中时,会去lowerdir查找

当要修改的文件在lowdir层时,会通过中间目录将文件拷贝至upperdir再操作, 这个中间目录称为workdir

下面通过实践来看看具体效果

环境准备
% cd /tmp
% mkdir mkdir lower upper work merged

在只读层lower目录里生成测试数据

% mkdir lower/{a,b,c,d}
% date > lower/date
% tree lower
lower/
├── a
├── b
├── c
├── d
└── date
4 directories, 1 file

联合挂载

% mount -t overlay overlay -o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work /tmp/merged
% tree /tmp/merged
/tmp/merged
├── a
├── b
├── c
├── d
└── date
4 directories, 1 file

可以看到,merged目录的内容和lower目录的一致,这是因为upper目录是空的

读操作

在读操作发生时

  • 文件在upper层存在,直接读取,忽略lower层
  • 文件不在upper层,从lower层查找
  • 也就是说,文件查找层级只有2层,对比aufs的多层要简单明了的说,将节省大量时间
写操作

在写操作发生时

  • 如果upper层有此文件,直接在upper层写
  • 如果lower层和upper层都没有此文件,则直接在upper层写
  • 如果文件只在lower层有,通过copy-up,将文件经过work层拷贝至upper层进行写操作

此操作只发生一次,因为下一次写操作会发现在upper层有此文件

% date > merged/date
% ls -l -i */date
20722267 -rw-r--r-- 1 root root 43 1月   4 22:43 lower/date
 5534205 -rw-r--r-- 1 root root 43 1月   4 23:10 merged/date
 5534205 -rw-r--r-- 1 root root 43 1月   4 23:10 upper/date

% touch merged/a/newfile
% ll -i */a/newfile
5534181 -rw-r--r-- 1 root root 0 1月   4 23:11 merged/a/newfile
5534181 -rw-r--r-- 1 root root 0 1月   4 23:11 upper/a/newfile

可以看到,写操作在upper层,并在merged层做了硬链接

删除操作

在删除操作发生时

  • 文件只在upper层存在,直接删除
  • 文件在upper层和lower层都存在,将在upper层创建同名的字符设备文件
  • 文件只在lower层存在,将在upper层创建同名的字符设备文件
% rm -f merged/a/newfile
% ls -l */a/newfile
ls: 无法访问*/a/newfile: 没有那个文件或目录

% rm -f merged/date
% ls -l */date
-rw-r--r-- 1 root root   43 1月   4 22:43 lower/date
c--------- 1 root root 0, 0 1月   4 23:19 upper/date

% rm -f merged/d
% ls -ld */d
drwxr-xr-x 2 root root    6 1月   4 22:43 lower/d
c--------- 1 root root 0, 0 1月   4 23:24 upper/d

因为本机测试环境是3.10内核,删除时文件变为了字符设备

效果是一样的,merged层看不到删除的文件,lower层的文件从未发生改变

% tree merged/
merged/
├── a
├── b
└── c
3 directories, 0 files
订阅
提醒
0 评论
在线反馈
查看全部评论