Docker镜像在存储的时候实际上是按照一个个镜像层进行存储的,当不同的镜像的某一个镜像层一样的时候,这个镜像层就会被多个镜像使用。设想一下我们自己设计一个Docker的话,如果一个容器修改文件的时候会影响到其他容器我们会怎么解决呢?或许有的人会想到可以这样做,将镜像层设计为不可修改的,对容器的所有修改都在每个容器的缓冲层进行,这样的话我们看到的容器的文件系统实际上是镜像层加上容器的缓冲层叠加做一定的逻辑运算后生成的。的确,Docker也是这么做的,Docker的设计中我们看到的文件系是通过一个只读层(rootfs)加上一个读写层实现的,读写层位于只读层的上部,充当一个拦截器,该拦截器的作用是:
-
当你在Docker中删除文件的时候,会在读写层加入一个文件标志被删除的文件已经不存在了。当用于读取数据的时候,会先经过拦截器,拦截器发现该文件已经逻辑删除了,所以最终对用户呈现的就是这个文件不存在了。
-
当你在Docker中修改文件的时候,会在读写层生成一个与被修改文件完全一致的文件,这个文件的内容就是你修改之后的。
-
当你在Docker中添加文件的时候,实际生成的文件也是在读写层。
下面我们使用aufs文件系统来模拟一下上述的模型。首先在一个文件夹中执行如下的命令:
mkdir read_layer && mkdir write_layer && mkdir union
该命令会在文件夹下面生成三个子文件夹。然后在read_layer中生成一个文件,
cd read_layer/ && echo test1 > ./test
test文件中的内容为test1。然后修改read_layer的访问权限为只读,
cd .. && sudo chmod -R 555 ./read_layer
使用ll查看当前目录可以看到read_layer的访问权限和其他文件夹不一样的。
接下来可以将read_layer和write_layer共同挂在到union上了,
sudo mount -t aufs -o br=./write_layer:./read_layer none ./union
进入到union中我们可以看到read_layer中的文件也出现在union中了。
删除文件
进入到union中删除test文件会出现什么呢?
cd union/ && rm -rf test
union中的文件不在了,但是read_layer中的还在同时在write_layer中新增了一个文件用于标示test文件被删除。
将.wh.test删除后test文件又会出现在union文件夹中。
修改文件
如果我们进行修改呢,会发生什么(此时test文件还在union文件中)?
进入到union文件夹中,vi打开test文件,修改为“test1aaaaaaaaaaaaaaaaaaaa”,wq!强行退出。然后查看test分别在union和read_layer中的内容,
可以发现修改内容实际上并没有修改只读层的文件,再继续查看write_layer中的文件,
果然多了一个和test完全同名的文件,那么内容如何呢?查看后可以发现其内容和union中的是一样的。
新增文件
和修改文件的行为是类似的。
通过上面的例子,相信大家对Docker是如何实现文件管理有了一些认识,更多的资料大家可以查看下面的连接:
http://www.thegeekstuff.com/2013/05/linux-aufs/
https://github.com/docker/docker
https://en.wikipedia.org/wiki/Aufs
https://en.wikipedia.org/wiki/Union_mount
https://en.wikipedia.org/wiki/UnionFS
还有Docker提供了多种文件系统,aufs只是其中之一,更多的这里就不赘述了。
Thank you