频道栏目
首页 > 网络 > 云计算 > 正文

从aufs文件系统到docker镜像

2016-10-25 09:18:07           
收藏   我要投稿

概要

1 aufs文件下系统是什么?有什么特性?

2 aufs文件系统与docker镜像的关系。

3 dockfile如何工作?

4 docker镜像储存到哪里?储存的什么?

5 docker镜像的储存过程简介。

aufs文件下系统是什么?有什么特性?

aufs文件系统全名为advanced multi-layered unification filesystem.
它能够将不同类型的文件系统透明地层叠在一起,实现一个高效的分层文件系统。简言之,它能将不同的目录挂在到统一目录下。

我们从几个简单的实验窥探一下aufs文件系统的挂载特性。

实验系统环境

OS : Ubuntu 14.04.2 LTS (GNU/Linux 3.16.0-30-generic x86_64)

docker : client/server 1.12.1

挂载命令:mount -t aufs -o br=path/to/dir/A:path/to/dir/A none path/to/dir/uniondir

mount命令中,-t表示目标文件系统类型,-o表示挂载参数, none表示挂载的不是设备文件。这些都是mount命令的参数。br是aufs的参数,表示分支,多个分支之间用冒号分隔。

挂载实验
```
mkdir a b uniondir
echo 1 > a/1.txt
echo 2 > b/2.txt
tree
#├── a
#│   └── 1.txt
#├── b
#│   └── 2.txt
#└── uniondir
sudo mount -t aufs -o br=/home/zyf/aufstest/a:/home/zyf/aufstest/b none /home/zyf/aufstest/uniondir
tree
#├── a
#│   └── 1.txt
#├── b
#│   └── 2.txt
#└── uniondir
#    ├── 1.txt
#    └── 2.txt
```
由此可见我们将a目录的1.txt和b目录的2.txt挂载到了uniondir下。
在挂在时候,我们指定a目录在前,所以a目录是逻辑的上层。br参数没有加读写权限之前,逻辑上层(a目录)为读写权限。其余层(b目录)为制度权限。所以如果我们在uniondir创建3.txt,此文件会创建在a目录中。
```
cd uniondir
vim 3.txt
cd ../ & tree
#├── a
#│   ├── 1.txt
#│   └── 3.txt
#├── b
#│   └── 2.txt
#└── uniondir
#    ├── 1.txt
#    ├── 2.txt
#    └── 3.txt
```
同样的,我们如果在一开始在a目录中创建2.txt。在挂在时候会优先挂载2.txt。
因为读写权限的不同,修改1.txt和2.txt内容对a、b的影响也不同:
```
echo 'add sth' >> /root/test/uniondir/1.txt
echo 'add sth' >> /root/test/uniondir/2.txt
cd ../ & tree
#├── a
#│   ├── 1.txt
#|   |   2.txt
#│   └── 3.txt
#├── b
#│   └── 2.txt
#└── uniondir
#    ├── 1.txt
#    ├── 2.txt
#    └── 3.txt        
```
可见,对可读写分支(目录a),修改直接作用到分支上;
而对于只读分支(目录b),修改操作会触发一次写时复制(COW, Copy On Write)
即先将待修改文件从目录b复制到目录a,然后在目录a修改相应文件。
注意写时复制机制可能在修改大文件时带来性能损耗,虽然每个文件最多只会复制一次。

aufs文件系统与docker镜像的关系。

docker镜像在构建的时候利用了aufs文件系统的挂载原理,对文件系统进行构建。

首先,存在一个 docker 容器在启动时其内部进程可见的文件系统视角,或者称为docker 容器的根目录rootfs。目录下含有 docker 容器所需要的系统文件、工具、容器文件等。(只读属性)

接着,在特定的镜像中存在每一个镜像独有的文件系统(读写属性)

docker这时候利用aufs进行两者挂载。形成一个镜像。可以由示意图表示。

image
docker 镜像复用的增量特性
<喎"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPjxjb2RlPmRvY2tlciDW2sv51tzWqsrH0rvW1rrcyqHXytS0tcTI3cb3oaPV4tK7zNjQ1LrctPOzzLbItcPS5tPaYXVmc8+1zbPM2NDUyrm1w2RvY2tlcr61z/G9+NDQuLTTw6GjPC9jb2RlPjwvY29kZT48L3A+DQo8cD48Y29kZT48Y29kZT48aW1nIGFsdD0="image" src="http://www.2cto.com/uploadfile/Collfiles/20161025/20161025092346370.jpg" title="\" />

从上图中我们可以看到,无论是unbuntu这种OS系统,还是mysql,mongo这种具体应用。docker利用的aufs文件系统在文件系统挂载时的(COW机制)对镜像进行复用。

所以我们假设 docker build 构建出来的镜像名分别为 image 1 和 image 2,由于两个 Dockerfile 均基于ubuntu:14.04,因此,image 1 和 image 2 这两个镜像均复用了镜像 ubuntu:14.04。 假设 RUN apt-get update 修改的文件系统内容为 20 MB,最终本地三个镜像的大小关系应该如下 :

ubuntu:14.04: 200 MB
image 1:200 MB(ubuntu:14.04 的大小)+ 20 MB = 220 MB
image 2:200 MB(ubuntu:14.04 的大小)+ 100 MB = 300 MB

如果仅仅是单纯的累加三个镜像的大小,那结果应该是:200 + 220 + 300 = 720 MB,但是由于镜像复用的存在,实际占用的磁盘空间大小是:200 + 20 + 100 + 320 MB,足足节省了 400 MB 的磁盘空间。在此,足以证明镜像复用的巨大好处。

dockfile如何工作?

既然说到了image,那不妨再谈一下dockerfile。具体是如何工作的。

Dockerfile 由多条指令构成,随着深入研究 Dockerfile 与镜像的关系,会发现,Dockerfile 中的每一条指令都会对应于 Docker 镜像中的一层。

如下 Dockerfile 为例:

FROM ubuntu:14.04  
ADD run.sh /  
VOLUME /data  
CMD ["./run.sh"]  

通过 docker build 以上 Dockerfile 的时候,会在 ubuntu:14.04 镜像基础上,添加三层独立的镜像,依次对应于三条不同的命令。镜像示意图如下:
image
有了 Dockerfile 与镜像关系的初步认识之后,我们再进一步联系到每一层镜像的大小。

在层级化管理的 Docker 镜像中,有不少层大小都为 0。那些镜像层大小不为 0 的情况,归根结底的原因是:构建 Docker 镜像时,对当前的文件系统造成了修改更新。而修改更新的情况主要有两种:

ADD 或 COPY 命令:ADD 或者 COPY 的作用是在 docker build 构建镜像时向容器中添加内容,只要内容添加成功,当前构建的那层镜像就是添加内容的大小,如以上命令 ADD run.sh /,新构建的那层镜像大小为文件 run.sh 的大小。

RUN 命令:RUN 命令的作用是在当前空的镜像层内运行一条命令,倘若运行的命令需要更新磁盘文件,那么所有的更新内容都在存储在当前镜像层中。举例说明:RUN echo DaoCloud 命令不涉及文件系统内容的修改,故命令运行完之后当前镜像层的大小为 0;RUN wget http://abc.com/def.tar 命令会将压缩包下载至当前目录下,因此当前这一层镜像的大小为:对文件系统内容的增量修改部分,即 def.tar 文件的大小(在成功执行的情况下)。

docker镜像储存到哪里?储存的什么?

docker将镜像,存储到了/var/lib/docker/下面。

Docker 镜像层的内容一般在 Docker 根目录的 aufs 路径下,为 /var/lib/docker/aufs/diff/,具体情况如下:

root@hmp-pc:/var/lib/docker/aufs/diff# ls | xargs ls

0a838d1341807dc3c97008ffbbc4c97e309f8323b9a6ed44db57b5dba1e37d1c:
etc

169bc4f555486d96269d377a6c4363fc70b3f280815630123c12fed6cc077200:
etc  sbin  usr  var

1d4c362445794e698d4b115de91a610894c0038b94df399d7c6ef363ed70550c:
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

223ff0b1885840f717348ce856a6569f43476eadcc174ebfd77015159d7eaa78:

另外出了镜像文件之外,还需要对每一个镜像层储存的json文件(一般json储存在了docker/graph目录中,此系统没有找到。)在此系统储存道了/var/lib/docker/image/aufs下的imagedb中

root@hmp-pc:/var/lib/docker/image/aufs/imagedb/content/sha256# vim 0027e029bd6c37ffc292b52d447d0a44d25a03c88415090a942074cdf228e216 

{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/bash"]............

docker镜像的储存过程。

镜像储存过程在docker源码中分成了以下四部。他们分别是:

验证镜像ID 创建镜像路径储存镜像内容注册镜像ID

在创建镜像路径中使用了mount union的挂载计数。如下图所示

在储存镜像内容中,实现的是
解压镜像内容 layerData 至 diff 目录;收集镜像所占空间大小,并记录;将 jsonData 信息写入临时文件。这三部操作。

最终镜像储存到了/var/lib/docker/auf中。

上一篇:hadoopHDFS读写文件
下一篇:Bluemix公有云入华,IBM加入云大战,祭出三大杀器
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站