(1)Docker 安装及基本用法

(2)Docker 镜像

(3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境

(4)Docker 容器的隔离性 - 使用 cgroups 限制容器使用的资源

(5)Docker 网络

(6)若干企业生产环境中的容器网络方案

(7)Docker 存储 - AUFS

Docker 存储可以分为分层文件系统和卷,本文将介绍 AUFS 分层文件系统。

1. 基础知识

1.1 Linux 的 rootfs 和 bootfs

一个典型的 Linux 系统要能运行的话,它至少需要两个文件系统:

  • boot file system (bootfs):包含 boot loader 和 kernel。用户不会修改这个文件系统。实际上,在启动(boot)过程完成后,整个内核都会被加载进内存,此时 bootfs 会被卸载掉从而释放出所占用的内存。同时也可以看出,对于同样内核版本的不同的 Linux 发行版的 bootfs 都是一致的。
  • root file system (rootfs):包含典型的目录结构,包括 /dev, /proc, /bin, /etc, /lib, /usr, and /tmp 等再加上要运行用户应用所需要的所有配置文件,二进制文件和库文件。这个文件系统在不同的Linux 发行版中是不同的。而且用户可以对这个文件进行修改。

Linux 系统在启动时,roofs 首先会被挂载为只读模式,然后在启动完成后被修改为读写模式,随后它们就可以被修改了。

1.2 AUFS

AUFS 是一种 Union File System(联合文件系统),又叫 Another UnionFS,后来叫Alternative UnionFS,再后来叫成高大上的 Advance UnionFS。所谓 UnionFS,就是把不同物理位置的目录合并mount到同一个目录中。UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起,然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)。

举个例子,在 Ubuntu 14.04 系统上现有如下目录结构:

$ tree
.
├── fruits
│ ├── apple
│ └── tomato
└── vegetables
├── carrots
└── tomato

输入以下几个命令:

# 创建一个mount目录
$ mkdir mnt # 把水果目录和蔬菜目录union mount到 ./mnt目录中
$ sudo mount -t aufs -o dirs=./fruits:./vegetables none ./mnt # 查看./mnt目录
$ tree ./mnt
./mnt
├── apple
├── carrots
└── tomato

我们可以看到在./mnt目录下有三个文件,苹果apple、胡萝卜carrots和蕃茄tomato。水果和蔬菜的目录被union到了./mnt目录下了。

我们来修改一下其中的文件内容:

$ echo mnt > ./mnt/apple
$ cat ./mnt/apple
mnt
$ cat ./fruits/apple
mnt

上面的示例,我们可以看到./mnt/apple的内容改了,./fruits/apple的内容也改了。

$ echo mnt_carrots > ./mnt/carrots
$ cat ./vegetables/carrots $ cat ./fruits/carrots
mnt_carrots

关于 AUFS 的几个特点:

  • AUFS 是一种联合文件系统,它把若干目录按照顺序和权限 mount 为一个目录并呈现出来
  • 默认情况下,只有第一层(第一个目录)是可写的,其余层是只读的。
  • 增加文件:默认情况下,新增的文件都会被放在最上面的可写层中。
  • 删除文件:因为底下各层都是只读的,当需要删除这些层中的文件时,AUFS 使用 whiteout 机制,它的实现是通过在上层的可写的目录下建立对应的whiteout隐藏文件来实现的。
  • 修改文件:AUFS 利用其 CoW (copy-on-write)特性来修改只读层中的文件。AUFS 工作在文件层面,因此,只要有对只读层中的文件做修改,不管修改数据的量的多少,在第一次修改时,文件都会被拷贝到可写层然后再被修改。
  • 节省空间:AUFS 的 CoW 特性能够允许在多个容器之间共享分层,从而减少物理空间占用。
  • 查找文件:AUFS 的查找性能在层数非常多时会出现下降,层数越多,查找性能越低,因此,在制作 Docker 镜像时要注意层数不要太多。
  • 性能:AUFS 的 CoW 特性在写入大型文件时第一次会出现延迟。

本部分内容主要应用自 Docker基础技术:AUFS

2. Docker 文件系统

2.1 Docker 镜像的 rootfs

前面基础知识部分谈到过,同一个内核版本的所有 Linux 系统的 bootfs 是相同的,而 rootfs 则是不同的。在 Docker 中,基础镜像中的 roofs 会一直保持只读模式,Docker 会利用 union mount 来在这个 rootfs 上增加更多的只读文件系统,最后它们看起来就像一个文件系统即容器的 rootfs。

 (图片来源

可见在一个Linux 系统之中,

  • 所有 Docker 容器都共享主机系统的 bootfs 即 Linux 内核
  • 每个容器有自己的 rootfs,它来自不同的 Linux 发行版的基础镜像,包括 Ubuntu,Debian 和 SUSE 等
  • 所有基于一种基础镜像的容器都共享这种 rootfs

以 training/webapp 镜像为例,

root@docker1:/var/lib/docker/aufs/diff/b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa# docker history training/webapp
IMAGE CREATED CREATED BY SIZE COMMENT
6fae60ef3446 months ago /bin/sh -c #(nop) CMD ["python" "app.py"] B
<missing> months ago /bin/sh -c #(nop) EXPOSE /tcp B
<missing> months ago /bin/sh -c #(nop) WORKDIR /opt/webapp B
<missing> months ago /bin/sh -c #(nop) ADD dir:9b2a69f6f30d18b02b5 B
<missing> months ago /bin/sh -c pip install -qr /tmp/requirements. 4.363 MB
<missing> months ago /bin/sh -c #(nop) ADD file:c59059439864153904 B
<missing> months ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt 135.3 MB
<missing> months ago /bin/sh -c apt-get update 20.8 MB
<missing> months ago /bin/sh -c #(nop) MAINTAINER Docker Education B
<missing> months ago /bin/sh -c #(nop) CMD ["/bin/bash"] B
<missing> months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
<missing> months ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
<missing> 17 months ago /bin/sh -c #(nop) ADD file:f4d7b4b3402b5c53f2 188.1 MB

它是基于 Ubuntu Docker 基础镜像。在基础镜像层中,我们能看到完整的 Ubuntu rootfs:

root@docker1:/var/lib/docker/aufs/diff/b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa# ls -l
total
drwxr-xr-x root root Apr bin
drwxr-xr-x root root Apr boot
drwxr-xr-x root root Apr dev
drwxr-xr-x root root Apr etc
drwxr-xr-x root root Apr home
drwxr-xr-x root root Apr lib
drwxr-xr-x root root Apr lib64
drwxr-xr-x root root Apr media
drwxr-xr-x root root Apr mnt
drwxr-xr-x root root Apr opt
drwxr-xr-x root root Apr proc
drwx------ root root Apr root
drwxr-xr-x root root Apr run
drwxr-xr-x root root Apr sbin
drwxr-xr-x root root Apr srv
drwxr-xr-x root root Mar sys
drwxrwxrwt root root Apr tmp
drwxr-xr-x root root Apr usr
drwxr-xr-x root root Apr var

我们来看两种典型的文件:

(1)bin 目录中的文件会被直接使用

root@docker1:/var/lib/docker/aufs/diff# find -iname mountpoint
./b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa/bin/mountpoint

(2)在基础镜像层中 proc 目录为空,也就是说容器中看到的 proc 目录中的文件是后来生成的。

2.2 Docker 使用的 AUFS 文件系统

关于 Docker的分层镜像,除了 aufs,docker还支持btrfs, devicemapper和vfs,你可以使用 -s 或 –storage-driver= 选项来指定相关的镜像存储。在Ubuntu 14.04下,Docker 默认 Ubuntu的 AUFS。因为 AUFS 还没有进入Linux 内核主干的原因,RedHat 上使用的是 devicemapper。

我们可以在 docker info 命令的输出中查看所使用的存储驱动:

Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs:
Dirperm1 Supported: false

以一个正在运行着的 Docker 容器为例,其镜像有13层:

"RootFS": {
"Type": "layers",
"Layers": [
"sha256:1154ba695078d29ea6c4e1adb55c463959cd77509adf09710e2315827d66271a",
"sha256:528c8710fd95f61d40b8bb8a549fa8dfa737d9b9c7c7b2ae55f745c972dddacd",
"sha256:37ee47034d9b78f10f0c5ce3a25e6b6e58997fcadaf5f896c603a10c5f35fb31",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:b75c0703b86b8ccbdc1f1b28b4982774768861ac250f83bdb940b1e90291f302",
"sha256:5c121779bb29172c628a21087ea8ced766959da2f223c8b6bd4ffe943ace43d8",
"sha256:3ee91c5cb95b01496b4afdc721ba7fd3c22e0e5e2f3e9e70d3f8579b5082d4f3",
"sha256:6bbb1d0f845289217e20b66697fa7d651394d89983b0f5a89b88f037194476fe",
"sha256:b44b0832d4c6bf33122ce3aa896b133df88275e6d20663a9bf2d941f764ac1fd",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
]
}

从 AUFS 的角度,可以看到有一个可写的容器层和14个只读的镜像层:

root@docker1:/sys/fs/aufs/si_ab487e40195df24f# cat *
/var/lib/docker/aufs/diff/2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab=rw #可写的容器层
/var/lib/docker/aufs/diff/2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab-init=ro+wh #本层及以下是只读的镜像层
/var/lib/docker/aufs/diff/5472f8388f9a61f6bd84498201a5ad71a2ec88cda16c42a3a1da7c30da45f102=ro+wh
/var/lib/docker/aufs/diff/61dcf0881e790bf52ec555727b58641791adeefadcc7abc2a77fd228bde1371a=ro+wh
/var/lib/docker/aufs/diff/f68672aaf17dd158aabc635b2d8d459d79db1cd5ff38bf3834fe8f9c7a05235e=ro+wh
/var/lib/docker/aufs/diff/45818d286499870412357d66eb6af951699f89db785c7c6a242d2e1ac99734f9=ro+wh
/var/lib/docker/aufs/diff/b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa=ro+wh
/var/lib/docker/aufs/diff/85cb840562788e1b458e68265e62fd2da9d0d7e737256500e8a276bcb237183c=ro+wh
/var/lib/docker/aufs/diff/c18ba8efcb455e97f6aabe3985b147f6a37b8f5ad090373e88ddd326b4f90896=ro+wh
/var/lib/docker/aufs/diff/25de7dcc3a06f0caa3c701d4ed6c62f03e0757f6d477cc822db6e884bb366441=ro+wh
/var/lib/docker/aufs/diff/ad9e831217594cdfecd5e824690b0e52f2e16d6e2bb39b7143e66d467150cfe8=ro+wh
/var/lib/docker/aufs/diff/56d37c8eecd8be9ba13e07e1486e7a6ac2f0aa01f8e865ee6136137369d8d8a0=ro+wh
/var/lib/docker/aufs/diff/31bc6290457af4e560a3103020c85fbb5dfcfb201b0662a33165260529f87c07=ro+wh
/var/lib/docker/aufs/diff/e104672666119006648d0b82988c49527e52c64629750c5c9adde88acc790682=ro+wh
/var/lib/docker/aufs/diff/7a085e415855435121fb7837c26a5e951f622bc69364d9228d409a4929b627e1=ro+wh

根据上面 AUFS 的定义,容器的文件系统是从 14 个只读镜像层和1个可写容器层通过 AUFS mount 出来的。示意图如下:

图片来源

这种分层文件系统可以通过官网的图来清晰的展示出来:

做一些实验:

(1)在容器中创建一个文件,该文件会被创建在可写的容器层中

root@docker1:/var/lib/docker/aufs/diff# find -iname createdbysammy
./2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab/opt/webapp/createdbysammy
root@docker1:/var/lib/docker/aufs/diff# ls -lt
total
drwxr-xr-x root root Oct : 2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab
drwxr-xr-x root root Oct : 2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab-init

(2)修改一个镜像层中的文件

修改前,文件 /etc/apt/sources.list 出现在两个层中:

root@docker1:/var/lib/docker/aufs/diff# find -iname sources.list
./f68672aaf17dd158aabc635b2d8d459d79db1cd5ff38bf3834fe8f9c7a05235e/etc/apt/sources.list
./b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa/etc/apt/sources.list

在容器中对它进行修改后,它被拷贝到了容器层然后被修改了:

root@docker1:/var/lib/docker/aufs/diff# find -iname sources.list
./f68672aaf17dd158aabc635b2d8d459d79db1cd5ff38bf3834fe8f9c7a05235e/etc/apt/sources.list
./2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab/etc/apt/sources.list
./b2188d5c09cfe24acd6da5ce67720f81138f0c605a25efc592f1f55b3fd3dffa/etc/apt/sources.list

而另外两个层中的文件保持了不变。这说明了 AUFS 的 CoW 特性。

(3)删除容器层中的文件

容器中的文件 ./usr/local/lib/python2.7/dist-packages/itsdangerous.py 位于 56d37c8eecd8be9ba13e07e1486e7a6ac2f0aa01f8e865ee6136137369d8d8a0 层中,这是一个只读层。

在容器内删除它:

root@fa385836d5b9:/# find -iname itsdangerous.py
./usr/local/lib/python2./dist-packages/itsdangerous.py
root@fa385836d5b9:/# rm ./usr/local/lib/python2./dist-packages/itsdangerous.py
root@fa385836d5b9:/# find -iname itsdangerous.py

然后,容器层中出现了一个 .wh 文件,而镜像层中的文件保持不变:

root@docker1:/var/lib/docker/aufs/diff# find -iname *itsdangerous.py
./56d37c8eecd8be9ba13e07e1486e7a6ac2f0aa01f8e865ee6136137369d8d8a0/usr/local/lib/python2./dist-packages/itsdangerous.py
./2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab/usr/local/lib/python2./dist-packages/.wh.itsdangerous.py

在手工将 .wh 文件删除后,文件就会再次回到容器中。

 rm ./2ee58d81e4ac6811bbc78beb4b46bf213c79c9e2dc7e441741afc8c4349c6bab/usr/local/lib/python2./dist-packages/.wh.itsdangerous.py
root@fa385836d5b9:/# find -iname itsdangerous.py
./usr/local/lib/python2./dist-packages/itsdangerous.py

参考链接:

最新文章

  1. nginx:文件下载指定保存文件名的配置
  2. 02 key concept
  3. C++学习30 重载++和--(自增自减运算符)
  4. discuzx完全自定义设计模板门户首页,栏目,专题模板方法
  5. C语言运算符表
  6. iOS 获取通讯录里边的电话号码AddressBook
  7. 怎样导入SDWebImage
  8. CentOS 7 之安装X Window System
  9. C#函数以及应用
  10. es6 Moduel 默认名与非默认名
  11. Java常用类库 读书笔记 二
  12. Leetcode 125.验证回文串 By Python
  13. Educational Codeforces Round 47 (Rated for Div. 2) 题解
  14. 20155217《网络对抗》Exp01 PC平台逆向破解(5)M
  15. Scala进阶之路-Scala的基本语法
  16. js 获取json对象的Key、value(js遍历json对象的key和value)
  17. Appium原理及版本变化细节
  18. Git修改子模块的路径
  19. 4. python 修改字符串实例总结
  20. (一)Linux实操之——权限、任务调度、磁盘分区

热门文章

  1. 无需编译、快速生成 Vue 风格的文档网站
  2. Laravel 5.3 登录注册底层实现详解
  3. 《ES6基础教程》之 map、forEach、filter indexOf 用法
  4. 计算机程序的思维逻辑 (44) - 剖析TreeSet
  5. MySQL关于exists的一个bug
  6. 读书笔记--SQL必知必会16--更新和删除数据
  7. 账号密码管理系统Access版本
  8. ASP.NET WebApi 文档Swagger深度优化
  9. Linq to SQL 语法查询(链接查询,子查询 &amp; in操作 &amp; join,分组统计等)
  10. vs2013\2015UML系列之-类图