您的位置:首页 > 运维架构 > Docker

Docker容器和镜像存储机制—images—目录树结构

2016-02-01 00:00 627 查看
http://ju.outofmemory.cn/entry/114344

Docker的存储机制采用了非常灵活的模块化设计,目前支持5种存储引擎,分别为aufs、btrfs、device mapper、vfs和overlay。它们的共同特点都是实现了graphdriver.Driver接口:

点击(此处)折叠或打开

type ProtoDriver interface {

String() string

//创建layer

Create(id, parent string) error

//删除layer

Remove(id string) error

//mount, 获取容器挂载点

Get(id, mountLabel string) (dir string, err error)

//umount文件系统

Put(id string)

Exists(id string) bool

Status() [][2]string

Cleanup() error

}

type Driver interface {

ProtoDriver

Diff(id, parent string) (archive.Archive, error)

Changes(id, parent string) ([]archive.Change, error)

ApplyDiff(id, parent string, diff archive.ArchiveReader)(size int64,err error)

DiffSize(id, parent string) (size int64, err error)

}

所以,只要实现了存储驱动接口定义的方法,就可以扩展出一种存储引擎。想要更换存储引擎有两种方法:

1. docker daemon进程启动时指定-s参数:docker –s aufs。

2. 修改配置文件:DOCKER_OPTS=”–storage-driver=aufs”。

在Docker存储模型中,bootfs同宿主机,rootfs则是由多个镜像层和一个容器层构成,其中镜像层只读,容器层可读写,多个镜像层之间有父子关系,下层作为上层镜像的父镜像,最下面的镜像称为base images(基础镜像),相关定义可以参考官网解释





aufs是Docker最早支持的一种存储引擎,它的工作机制和优缺点在前文『aufs文件系统』中已有介绍,aufs能将不同的目录挂载到某一目录下,将各个源目录下的内容联合到目标目录下,并可对不同目录进行权限控制。这个特性非常契合Docker的存储模型:

1. 镜像分层模型对应aufs中的分支(源目录)。

2. 镜像层对应aufs的ro分支,只读;容器层对应aufs的rw分支,可读写。

默认配置下,Docker镜像和容器存储路径($DOCKROOT)位于/var/lib/docker,如果选择的是aufs文件系统作为存储引擎,那么它的子目录树结构(基于docker 1.4.1)应该如下:

点击(此处)折叠或打开

# tree .

├── aufs

│ ├── diff 镜像和容器每层的差异内容

│ ├── layers 镜像和容器每层的继承关系

│ └── mnt 容器挂载点

├── containers 容器配置文件,环境变量和日志文件

├── graph 镜像详情、大小等

└── repositories-aufs 镜像摘要

举例说明,当前本地镜像库有一个ubuntu:14.04的镜像,它的层级关系如下:

点击(此处)折叠或打开

# docker images -t

└─511136ea3c5a Virtual Size: 0 B

└─3b363fd9d7da Virtual Size: 192.5 MB

└─607c5d1cca71 Virtual Size: 192.7 MB

└─f62feddc05dc Virtual Size: 192.7 MB

└─8eaa4ff06b53 Virtual Size: 192.7 MB Tags: ubuntu:14.04

那么在aufs/diff目录(相对于$DOCKROOT,下同)下会有以各个层级id命名的目录,每个目录存储着与它父镜像之间的差异:

点击(此处)折叠或打开

# ls -l aufs/diff/

total 20

drwxr-xr-x 21 3b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a

drwxr-xr-x 2 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158

drwxr-xr-x 6 607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa

drwxr-xr-x 2 8eaa4ff06b53ff7730c4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a

drwxr-xr-x 3 f62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73

aufs/layers目录下有以各个层级id命名的文件,文件内容为该层所有的祖先镜像id。例如

点击(此处)折叠或打开

# cat aufs/layers/8eaa4ff06b53ff7730c4d7a7e21b4426a4b...

f62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73

c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa

b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a

ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158

graph目录中存储的是每一层镜像的详细信息和大小:

点击(此处)折叠或打开

# tree graph/

graph/

├── 3b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a

│ ├── json

│ └── layersize

├── 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158

│ ├── json

│ └── layersize

├── 607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa

│ ├── json

│ └── layersize

├── 8eaa4ff06b53ff7730c4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a

│ ├── json

│ └── layersize

└── f62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73

├── json

└── layersize

其中,json为该层元信息,layersize为该层大小。

此时用ubuntu:14.04镜像起一个容器:

点击(此处)折叠或打开

# docker run -it -d ubuntu:14.04 /bin/bash

b0311350933de15936136b4c9142635782f8fd1a015d2fd2d6c54ed05efb

新建容器的操作会在aufs下三个子目录中分别新建两个以容器id为名的文件/目录,例如4262b031135…和4262b031135…-
init,其中4262b031135…-init表示容器的初始层,它记录的信息和ubuntu:14.04镜像的最上层一致。所有在新建容器中的文件
操作最终都会记录到aufs/diff/4262b031135…目录中,比如:

1. 新建文件,修改文件。

2. 删除文件和目录,以.wh.{obj}标记。在联合文件系统中被称为除白(Whiteout)对象。

3. 删除目录后新建,以.wh..wh..opq标记。在联合文件系统中被称为不透明(Opaque directory)对象。

aufs/mnt目录是容器的挂载点,通过df命令和mount
-v命令进行确认,另外容器的操作日志、环境变量、元信息等也会在containers目录以容器id命名的目录中。容器运行后,可以在sysfs目录中
找到对应的从上到下的镜像层次结构,读写权限一目了然(si可以通过mount -v查询):

点击(此处)折叠或打开

# cat /sys/fs/aufs/si_13ac476258e8c5e8/br*

/var/lib/docker/aufs/diff/4262b031135...=rw

/var/lib/docker/aufs/diff/4262b031135...-init=ro

/var/lib/docker/aufs/diff/8eaa4ff06b5...=ro

/var/lib/docker/aufs/diff/f62feddc05d...=ro

/var/lib/docker/aufs/diff/607c5d1cca7...=ro

/var/lib/docker/aufs/diff/3b363fd9d7d...=ro

/var/lib/docker/aufs/diff/511136ea3c5...=ro

aufs为Docker镜像存储带来了可重用性、权限分明、层次清晰等优点后,也带来了它的固有缺陷:

1. 写时复制(Copy On Write),性能不够好。

2. 最大层数限制(127层)。

关于绕开最大层数限制,在『aufs文件系统』中已有讨论,这里针对Docker的使用场景再进行一次归纳:

1. 更换docker存储驱动类型:device mapper, btrfs …

2. 重新编译aufs: CONFIG_AUFS_BRANCH_MAX_32767=y

3. 精简Dockerfile指令:RUN指令合并,脚本化

4. docker export & docker import

–EOF–
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: