理解Docker(7):Docker 存储 - AUFS
(2)Docker 镜像
(3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境
(4)Docker 容器的隔离性 - 使用 cgroups 限制容器使用的资源
(5)Docker 网络
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
参考链接:
理解Docker(7):Docker 存储 - AUFS的更多相关文章
- Docker镜像文件存储结构
docker相关文件存放在:/var/lib/docker目录下 镜像的存储结构主要分两部分,一是镜像ID之间的关联,一是镜像ID与镜像名称之间的关联,前者的结构体叫Graph,后者叫TagStore ...
- Docker基础技术:AUFS
AUFS是一种Union File System,所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中.UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 m ...
- [转帖]Docker五种存储驱动原理及应用场景和性能测试对比
Docker五种存储驱动原理及应用场景和性能测试对比 来源:http://dockone.io/article/1513 作者: 陈爱珍 布道师@七牛云 Docker最开始采用AUFS作为文件系统 ...
- docker改变默认存储路径到数据盘(自己实践)
一.首先将数据盘格式化分区并挂载(文章中提到的sdb(腾讯云)实践中是vdb(阿里云),文章中挂载在ssd目录下,实践中是挂载到data目录下的,后面安装docker部分以后是实践中的记录,上面数据盘 ...
- 理解Docker :Docker 网络
本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- 【Docker】Docker概述、理解docker的集装箱、标准化、隔离的思想、 docker出现解决了什么问题
整理一下 慕课网 第一个docker化的java应用 Docker环境下的前后端分离项目部署与运维 课程时所做的笔记 Docker概述 docker - https://www.docker.com/ ...
- Docker的OverlayFS存储驱动
OverlayFS存储驱动 OverlayFS是一个现代的Union Filesystem,类似于AUFS,但速度更快,实现更简单.Docker为OverlayFS提供了两个存储驱动程序:overla ...
- Docker 修改默认存储位置
首先使用 docker info 查看 docker 的基本信息 sudo docker info Containers: 0 Images: 5 Storage Driver: devicemapp ...
- 【Docker】docker /var/lib/docker/aufs/mnt 目录满了,全是垃圾数据,咋搞?
命令: #!/bin/bash # 推荐方式 docker volume ls -f dangling=true | awk '{ print $2 }' | xargs docker volume ...
随机推荐
- Vue.js入门
之前一直用的是jQuery,jQuery手动操作DOM导致性能不够好,因为DOM修改导致的页面重绘.重新排版!重新排版是用户阻塞的操作,同时,如果频繁重排,CPU使用率也会猛涨! Vue.js是数据驱 ...
- Android自定义View之圆环交替 等待效果
学习了前面两篇的知识,对于本篇实现的效果,相信大家都不会感觉太困难,我要实现的效果是什么样呢?下面请先看效果图: 看上去是不很炫的样子,它的实现上也不是很复杂,重点在与onDraw()方法的绘制. 首 ...
- CRL快速开发框架开源完全转到Github
CRL简介 CRL是一款面向对象的轻量级ORM框架,本着快速开发,使用简便的原则,设计为 无需关心数据库结构,CRL自动维护创建,即写即用(CRL内部有表结构检查机制,保证表结构一致性) 无需第三方工 ...
- Uploadify 结合 Web API 2 上传问题
最近使用jQuery.Uploadify和Web API配合来做上传,碰到问题,还木有办法解决,记录一下: 环境:jQuery 1.10.2,Uploadify 3.2.1,SWFObject 2.2 ...
- ASP.NET + EF + SQL Server搭建个人博客系统新手系列(一):界面展示
第一次写博客,可能有些地方描述的不准确,还请大家将就.本人大四学生,学了半年C#,半年.net,但是很遗憾,学完之后只会写个hello word.老师教的过程中总是会套用一些模板,特别是后台,完全封装 ...
- Ionic 简单操作
在使用 Ionic 之前要安装 Nodejs,Cordova . Java 下载Java 网站.Java 默认安装在 C:\Program Files\Java 文件目录. Android 下载And ...
- Web Service概念梳理
计算机技术难理解的很多,Web Service 对我来说就是一个很难理解的概念:为了弄清它到底是什么,我花费了两周的时间,总算有了一些收获,参考了不少网上的资料,但有些概念说法不一.我以w3c和 一些 ...
- C# - 多线程 之 信号系统
基础概览 多线程之信号系统命名空间 using System.Threading; 线程同步类的继承层次关系图 终止状态和非终止状态 在终止状态下,被WaitOne()阻塞的线程会逐个得到释放.如果一 ...
- centos下升级mysql后遇到的小问题
记录今天遇到的一个小问题, 写一个app访问接口涉及到通过存储过程反馈多个结果集,但是反回多个结果集的存储过程,调用之后只能反回一个了,而且奇怪的是,即使直接在mysql上同时执行两条查询语句,第一条 ...
- 通过JAXB完成Java对象与XML之间的转换
Java对象转换XML的过程叫marshal. XML转换到Java对象的过程叫unmarshal. 一.Java对象转化为XML 这里省略getter和setter方法 通过标注@XMLRootEl ...