0、概念

参考: https://www.wumingx.com/k8s/docker-rootfs.html https://coolshell.cn/articles/17061.html

1、目录划分

如图所示,aufs主要有三个目录(默认三个目录都是空的):
image.png
diff:当我们pull一个镜像之后,docker会自动将镜像解压完成为目录并放置到diff目录(每一层一个目录)
mnt:挂载点。mount diff多个目录之后的挂载点
layers:保存了每个镜像的layers依赖信息

2、ubuntu example

2.1、pull ubuntu镜像

可以看到pull之前,mnt/diff/layers均为空。pull完成之后如下图:
image.png
且mnt/diff/layers文件如下:
image.png

2.2、aufs目录下文件详细信息

image.png
可以看到1是根镜像,2是基于1制作的镜像,3是基于1、2做的镜像
1、2、3镜像内容如下,可以看到镜像之间是有文件重复的情况,这种情况下,联合目录时上层镜像会覆盖下层镜像
image.png
mnt目录下面则全是空
image.png

2.3、启动ubuntu镜像

image.png
可以看到如下信息:
1、镜像3的run目录被联合到了docker里面
2、看一下关于信息覆盖的问题,如图,1和2的diversions文件不同,2比1多了内容。而容器联合目录的内容和镜像2一致,如图3:
图1
image.png
图2
image.png
图3
image.png

2.4、启动之后的目录变化

可以看到启动之后3个目录均增加了两个目录且有一个是init结尾的
image.png
查看新增的文件的layers依赖关系,可以看到init结尾的目录要联合ubuntu默认的3个层,而非init结尾的需要联合4个层
image.png
而容器内部的视图是以非init的目录为准的,就是联合1、2、3+init4个layers,如图所示,两个视图内容一模一样
a043218f56e2de2bd576d9923121bdaf5ba159dd41a21dc0776d0d5c236a45cb目录视图:
image.png
容器内部视图:
image.png

2.4.1、init层的作用

init层里面是我们启动容器的时候docker自动帮我们生成的,内容如下。主要就是dev/etc。之所以要单独生成是因为在制作镜像的时候,hostname、hosts这种配置每个容器都是不一样的,因此commit镜像的时候无需提交到镜像里面,启动的时候根据参数自动生成并填充到init层的配置文件里面
image.png
image.png

3、镜像制作(run命令体验)

我们知道每一条run命令都会生成单独的层,我们通过不同的run命令来体验一下

3.1、RUN echo “hello”

dockerfile如下:
image.png
执行记录如下:
image.png
mnt/diff/layers目录如下:
image.png
docker images如下:
image.png
两个镜像的layers信息
image.png
可以看到mnt/diff/layers并未发生任何变化,可以得出两个结论:
1、当使用RUN命令的时候并不是一定会发层的新建,比如一个命令并未产生任何目录或者文件
2、若Dockerfile并未对基础镜像产生任何层的叠加,不会产生新的层,底层都是基础镜像,laters依赖是一样的

3.2、RUN echo “hello” > /tmp/text.txt

执行记录和Dockerfile内容如下:
image.png
mnt/diff/layers目录如下,可以看到产生了一个新的层:
image.png
diff目录内容:
image.png
mnt目录内容:
image.png
layers内容如下:
image.png
可以看到新的层产生并且依赖ubuntu:latest的所有层
启动新的镜像,看一下镜像内部的视图。可以看到text.txt文件已经进入了容器内部视图
image.png

3.2.1、对text.txt文件进行变更

3.2.1.1、变更tmp目录下面的text.txt文件

向文件里面追加了一句话
image.png
可以看到diff层的镜像并没有发生变化,如下图:
image.png
但是mnt。也就是挂载点的视图发生了变更:
image.png

3.2.1.2、在root目录下面touch一个文件

在容器视图/root目录touch一个文件text.txx
image.png
可以看到mnt挂载点视图已经有了此文件(符合预期)
image.png
但是我们发现diff层也发生了变更
image.png

3.2.1.3、变更原理

联合挂载的目录其实是有权限之分的。对于2d3c6b3ddae9d3ccfcb6360d762a8b853dddc18a15d50a216b6f628f31fd0ace目录,这个是docker在启动docker的时候为进程创建的读写层,但是39d72ad3dede57eb6207e3fb2850f84cdb0f57e0aed539a1bb70d47cfe5db929层是只读层。当对只读层进行文件变更的时候会触发写时拷贝,将文件从layers层拷贝到容器层然后在进行变更,不会被layers层产生任何影响,因此会出现上述现象。然后我们查询一下联合目录各个目录的权限。可以看到2d3c6b3ddae9d3ccfcb6360d762a8b853dddc18a15d50a216b6f628f31fd0ace权限为rw,而其他层为只读层
image.png