从docker pull开始,看 docker image 的存储过程
# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
5ba4f30e5bea: Pull complete
6874f9870f5f: Pull complete
4c876570bd7d: Pull complete
10fb34ebccea: Pull complete
Digest: sha256:f1b592e2de671105255a0c0b7b2f71a92b829403e8fc845e3482667ecc301780
Status: Downloaded newer image for ubuntu:latest
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 12543ced0f6f 2 weeks ago 122.4 MB
其中image名字是ubuntu,image的id是12543ced0f6f,在docker中,几乎所有的ID都是通过UUID或者sha256等方式计算出来的
1. /var/lib/docker结构
/var/lib/docker/
├── aufs
│ ├── diff
│ ├── layers
│ └── mnt
├── containers
├── image
│ └── aufs
├── network
│ └── files
├── tmp
├── trust
└── volumes
其中aufs和具体的graphdriver相关,如果使用的是overlay,则目录名是overlay,docker支持多种不同的graphdriver作为image + layers的存储引擎。由于docker的Image是支持差分机制的,所以它的image相当于是layers【也叫diff】的集合
2. Image元数据存储
Image元数据中包含了Image的信息,以及layers的层级结构
/var/lib/docker/image/
└── aufs
├── distribution
│ ├── diffid-by-digest
│ └── v2metadata-by-diffid
├── imagedb
│ ├── content
│ └── metadata
├── layerdb
│ ├── sha256
│ └── tmp
└── repositories.json
ubuntu的镜像ID是12543ced0f6f,对应的Image元数据文件是:/var/lib/docker/image/aufs/imagedb/content/sha256/12543ced0f6f754223eff4cca67b56cbf9f384456ab9deaa824ba9ff28bcfdd6
image中的内容包含image的rootfs结构:
“rootfs”:{“type”:”layers”,”diff_ids”:[“sha256:9436069b92a3ec23351313d6decc5fba2ce1cd52aac77dd8da3b03b3dfcb5382″,”sha256:fac4a4c59f33e5253337dca335b8b6661ea06c7aa10f68d9fee12b5bf1dc9a42″,”sha256:8bcab4108495b75fe97c181dc2d988ad932dc8068de074c879a290cfecdcd4dd”,”sha256:30abc4102690be1fedfe42ffe026375f2c1b919156d2aa38f7ce75cfb83eca1e”]}
rootfs包含4个layers,分别是:
9436069b92a3ec23351313d6decc5fba2ce1cd52aac77dd8da3b03b3dfcb5382
fac4a4c59f33e5253337dca335b8b6661ea06c7aa10f68d9fee12b5bf1dc9a42
8bcab4108495b75fe97c181dc2d988ad932dc8068de074c879a290cfecdcd4dd
30abc4102690be1fedfe42ffe026375f2c1b919156d2aa38f7ce75cfb83eca1e
这些ID是原始的diffid
备注:image的元数据中也有一个Image的字段,具体还不清楚这个字段所代表的含义是什么
3. layers元数据存储
路径:/var/lib/docker/image/aufs/layerdb
/var/lib/docker/image/aufs/layerdb/sha256/
├── 2830735b3fba6e472060c9fb5cb206be1938f481f8393de125436c7ace6eab00
├── 4affe30ad1bd872c60e76cf0c2be1154a604fc5f30a6c778bdef02d95753166c
├── 9436069b92a3ec23351313d6decc5fba2ce1cd52aac77dd8da3b03b3dfcb5382
└── f72060fe66563780220ad83e804de2dd23d9b6fa3b9f3cf491ed5652b25e6f45
每个layer包含4个信息:
1. cache-id: 本地缓存的layerid
2. diff: 原始的diffid,对应到image元数据中rootfs字段的信息
3. size: layer的大小,单位字节
4. tar-split.json.gz
layer中的目录名也叫chainid,chainid是通过diffid和父亲的chainid计算出来的:
if layer.parent == nil {
layer.chainID = ChainID(layer.diffID)
} else {
layer.chainID = createChainIDFromParent(layer.parent.chainID, layer.diffID)
}
以ubuntu中的第一个layer:9436069b92a3ec23351313d6decc5fba2ce1cd52aac77dd8da3b03b3dfcb5382为例,对应的元数据信息是:
1. cache-id: 69f386ef6b5558308ccf24d8ec0f84682a2eb751929aef547e96a8ae0d8a248c
2. diff: sha256:9436069b92a3ec23351313d6decc5fba2ce1cd52aac77dd8da3b03b3dfcb5382
3. size: 121987092
4. layers数据存储
layer元数据中的cache-id其实是指在本地缓存的ID,这个ID不具备唯一性,只限localhost域
路径:
/var/lib/docker/aufs/
├── diff
├── layers
└── mnt
diff和layers中的目录都是以layerid命名,其中:
1. diff中存储的是每个layer中的文件系统数据
2. layers的分层结构
docker通过不同的layer来组成成一个完整的rootfs,例如通过aufs/overlayfs等文件系统技术,具体可以参考内核文档