基本概念
registry
用以保存Docker
镜像,其中还包括镜像层次结构和关于镜像的元数据(Docker Hub)
repository
即由具有某个功能的Docker
镜像的所有迭代版本构成的镜像组
registry
是repository
的集合,repository
是镜像的集合
Docker
内部的image
(镜像)概念是用来存储一组镜像相关的元数据信息,主要包括镜像的架构、镜像默认配置信息、构建镜像的容器配置信息、包含所有镜像层信息的rootfs
,Docker
用rootfs
中的diff_id
计算出内容寻址的索引(chainID)来获取layer
相关信息,进而获取每一个镜像层的文件内容
layer
(镜像层)是一个Docker
用来管理镜像层的中间概念,镜像是由镜像层组成的,而单个镜像层可能被多个镜像共享,所以Docker
将layer
与image
的概念分离。Docker
镜像管理中的layer
主要存放了镜像层的diff_id
、size
、cache-id
和parent
等内容,实际的文件内容则是由存储驱动来管理,并可以通过cache-id
在本地索引到
repository元数据
/var/lib/docker/image/overlay2/repositories.json
下存放所有镜像相关元数据(多个repository下的不同版本镜像),包含repo
名称(docker-cli-dev),镜像名称和tag
(docker-cli-dev:latest),镜像id
(sha256…),有的还包含数字签名
Docker
默认采用SHA256
算法根据镜像元数据配置文件计算出镜像ID
1 | { |
image元数据
imageStore
则管理镜像ID
与镜像元数据之间的映射关系以及元数据的持久化操作,持久化文件位于/var/lib/docker/image/[graph_driver]/imagedb/content/sha256/[image_id]
中
内容包括镜像架构,构建镜像相关配置信息、创建该镜像的容器ID
和配置、创建时间、创建该镜像的Docker
版本、构建镜像的历史信息、操作系统以及rootfs
组成
Docker
会根据历史信息和rootfs
中的diff_ids
计算出构成该镜像的镜像层的存储索引chainID
layer元数据
镜像层只包含一个具体的镜像层文件包,当一个镜像层被下载后,Docker
会基于镜像层文件包和image
元数据构建本地的layer
元数据,包括diff
、parent
、size
等
Docker
中定义了Layer
和RWLayper
两种接口,分别用来定义只读层和可读写层的一些操作,又定义了roLayer
和mountedLayer
,分别实现了上述两种接口。其中,roLayer
用于描述不可改变的镜像层,mountedLayer
用于描述可读写的容器层
roLayer
位于/var/lib/docker/image/[graph_driver]/layerdb/sha256/[chainID]/
- chainID 文件夹名称,用于索引该镜像层
- 如果该镜像层是最底层(没有父镜像层),该层的
diffID
便是chainID
- 该镜像层的
chainID
计算公式为chainID(n)=SHA256(chain(n-1) diffID(n))
,也就是根据父镜像层的chainID
加上一个空格和当前层的diffID
,再计算SHA256
校验码
- 如果该镜像层是最底层(没有父镜像层),该层的
- diff 该镜像层的校验码
diffID
diffID
采用SHA256
算法,基于镜像层文件包的内容计算得到
- parent 父镜像层
chainID
- cache-id
graphdriver
存储当前镜像层文件的cacheID
cacheID
是在当前Docker
宿主机上随机生成的一个uuid
,在当前宿主机上与该镜像层一一对应,用于标示并索引graphdriver
中的镜像层文件
- size 该镜像层的大小
mountedLayer
位于/var/lib/docker/image/[graph_driver]/layerdb/mounts/[container_id]/
- container_id 对应
docker ps -a
的容器ID
- init-id 容器
init
层在graphdriver
中的ID
- mount 读写层在
graphdriver
中的ID
- parent 父层镜像的
chainID
1 | root@zeyu-desktop:/var/lib/docker/image/overlay2/layerdb/mounts/f4ce0841c0b174e4e5e4639e1ef5841a14ebe64c37f3e6cf3711501567345842# ls |
1 | root@zeyu-desktop:/var/lib/docker/image/overlay2/layerdb/sha256/efc088ed50a3b76edfce1505de41e3317d521684dc0620f1cd87af5f6f28a9ab# pwd |
graphdriver
1 | type Driver interface { |
1 | type ProtoDriver interface { |
1 | type DiffDriver interface { |
Docker
中的任何存储驱动都需要实现上述Driver
接口linux
系统下驱动的优先级被定义在graphdriver/drivier_linux.go
中
1 | priority = "btrfs,zfs,overlay2,fuse-overlayfs,aufs,overlay,devicemapper,vfs" |
驱动注册
graphdriver
会维护一个map
用于存储注册的驱动名称和对应的初始化函数
1 | var ( |
以overlay2
为例,只需要实现一个init
函数
1 | func init() { |
当overlay2
的包被包含的时候自动就会调用包中的init
函数,所有注册的驱动都在graphdriver/register
,其他模块使用register
包就会把相关的驱动注册
这里import
时在包路径前面加了一个_
,只有这样才能调用到相关包的init
函数
1 | package register // import "github.com/docker/docker/daemon/graphdriver/register" |
创建Driver
检查环境变量DOCKER_DRIVER
和配置是否提供驱动名称,如果有的话直接在map
按驱动名称调用对应驱动的初始化函数;否则就会按照优先级去查找相关的驱动
Docker
镜像管理部分与存储驱动在设计上完全分离了,镜像层或者容器层在存储驱动中拥有一个新的标示ID
,在镜像层(roLayer)中称为cacheID
,容器层(mountedLayer)中为mountID
。在Unix
环境下,mountID
是随机生成的并保存在mountedLayer
的元数据mountID
中,持久化文件在/var/lib/docker/image/overlay2/layerdb/mounts/container_id
overlay2 driver
OverlayFS
是一种新型联合文件系统(union filesystem),它允许用户将一个文件系统与另一个文件系统重叠(overlay),在上层的文件系统中记录更改,而下层的文件系统保持不变
1 | mkdir lower upper work merged |
/var/lib/docker/overlay2
中
- 容器层
mountID
1
2root@zeyu-desktop:/var/lib/docker/overlay2/89610a9bd010adaa7f2281c5b3c9d96d337ff87660411539a58f163d3cec1704# ls
diff link lower work- diff 存放容器运行时变化的文件(overlay的upper)
- link 描述该层对应的软连接 所有的链接文件都在
/var/lib/docker/overlay2/l/
,使用软连接可以防止lower
层过多时命令过长挂载失败 - lower 描述该层对应所有的
lower
层的软连接 - work
overlay
工作目录 - merged 只有在运行时创建的
overlay
挂载点
mountID-init
1
2root@zeyu-desktop:/var/lib/docker/overlay2/89610a9bd010adaa7f2281c5b3c9d96d337ff87660411539a58f163d3cec1704-init# ls
committed diff link lower work
- 镜像层
cacheID
1
2root@zeyu-desktop:/var/lib/docker/overlay2/47bdd7a31bb6ad0f91d51d1c3b340e382d4a1427243eab85e4ec6ee1d9fb6d44# ls
committed diff link
1 |
|