Docker镜像的相关目录

No Subtitle :>

Posted by PYQ on November 10, 2023

docker pull的基本流程

这里暂不对源码进行分析,只介绍基本流程

cv from docker 在本地如何管理 image(镜像)?

  • docker发送image的名称+tag(或者digest)给registry服务器,服务器根据收到的image的名称+tag(或者digest),找到相应image的manifest,然后将manifest返回给docker
  • docker得到manifest后,读取里面image配置文件(config)的 digest(sha256),这个sha256码就是 image的ID
  • 根据ID在本地找有没有存在同样ID的image,有的话就不用继续下载了
  • 如果没有,那么会给registry服务器发请求(里面包含配置文件的digest(sha256)和media type),拿到 image的配置文件(Image Config)
  • 根据配置文件中的diff_ids(每个diffid对应一个layer tar包的sha256),在本地找对应的layer是否存在
  • 如果layer不存在,则根据manifest里面layer的digest(sha256)和media type去服务器拿相应的layer(区别于config中的diffid,manifest中的digest通常是对manifest中记录的layer的mediatype做sha256计算所得,通常来说这个mediatype一般为tar的压缩格式即tar.gzip)。
  • 拿到后进行解压,并检查解压后tar包的sha256是否与配置文件(Image Config)中的diff_id一致,不一致说明文件被篡改,下载失败
  • 根据docker所用的后台文件系统类型,解压tar包并放到指定的目录
  • 所有的layer都下载完成后,整个image下载完成

manifest文件仅用于镜像文件的下载,镜像下载完成后被删除。

/var/lib/docker/image/overlay2

docker中镜像元数据存储的路径一般是/var/lib/docker/image/<union-fs-name><union-fs-name>指主机上docker使用的联合文件系统类型,主要为overlay2,此外还有aufs等。

此目录下主要包括如下内容:

1
2
root@debian:/var/lib/docker/image/overlay2# ls
distribution  imagedb  layerdb  repositories.json

distribution

distribution目录中存储manifest中layer的digest_id与config中layer的diff_id的映射关系。

1
2
3
4
5
6
7
8
root@debian:/var/lib/docker/image/overlay2/distribution# ls
diffid-by-digest  v2metadata-by-diffid
root@debian:/var/lib/docker/image/overlay2/distribution# ls -l diffid-by-digest/
total 16
drwxr-xr-x 2 root root 16384 Nov  9 10:11 sha256
root@debian:/var/lib/docker/image/overlay2/distribution# ls -l v2metadata-by-diffid/
total 20
drwxr-xr-x 2 root root 20480 Nov  9 10:11 sha256

diffid-by-digest

diffid-by-digest存储digest对应的diff_id。

1
2
root@debian:/var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256# cat ff63b82a42d3d44071011eb2a1262a77c15520b940511c05ebd7a7c3019fdff6 
sha256:60af18e613ad753f3b25da7242ae2f8ee3481f6768bc22c23be352f9906157df

v2metadata-by-diffid

v2metadata-by-diffid存储diffid对应的digest_id以及layer的其他元数据。

1
2
3
4
5
6
7
8
root@debian:/var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256# cat 60af18e613ad753f3b25da7242ae2f8ee3481f6768bc22c23be352f9906157df | jq
[
  {
    "Digest": "sha256:ff63b82a42d3d44071011eb2a1262a77c15520b940511c05ebd7a7c3019fdff6",
    "SourceRepository": "docker.io/library/golang",
    "HMAC": ""
  }
]

imagedb

imagedb目录主要存储镜像的配置信息:

1
2
3
4
root@debian:/var/lib/docker/image/overlay2/imagedb# ls -l
total 8
drwx------ 3 root root 4096 Jun 22  2022 content
drwx------ 3 root root 4096 Jun 22  2022 metadata

content

content目录存储镜像的config文件,文件数量和主机上的镜像数量一致,文件以对应的镜像id(也就是config文件的sha256值)命名:

1
2
3
4
5
root@debian:/var/lib/docker/image/overlay2/imagedb/content/sha256# ls
c6b84b685f35f1a5d63661f5d4aa662ad9b7ee4f4b8c394c022f25023c907b65
root@debian:/var/lib/docker/image/overlay2/imagedb/content/sha256# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED         SIZE
ubuntu                              latest    c6b84b685f35   2 months ago    77.8MB

文件的内容为镜像的config内容。

metadata

没找到太多资料,说的是里面存放的是本地image的一些信息,从服务器上pull下来的image不会存数据到这个目录。

layerdb

layerdb目录存储容器和镜像层的相关数据:

1
2
3
4
5
root@debian:/var/lib/docker/image/overlay2/layerdb# ls -l
total 40
drwxr-xr-x   5 root root  4096 Nov  9 10:24 mounts
drwxr-xr-x 174 root root 28672 Nov  9 10:18 sha256
drwxr-xr-x   2 root root  4096 Nov  9 10:18 tmp

mounts

mounts目录存储容器的相关元数据,文件以容器的id命名,数量与当前主机上的容器数量一致:

1
2
3
4
5
root@debian:/var/lib/docker/image/overlay2/layerdb/mounts# ls
6e9d18b4213dbd02abfb392ee14c3d00c103a4b21701495cf70eb9c91dbb49cc  
root@debian:/var/lib/docker/image/overlay2/layerdb/mounts# docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED        STATUS                      PORTS     NAMES
6e9d18b4213d   ubuntu            "/bin/bash"              4 days ago     Exited (137) 43 hours ago             youthful_ganguly

单个文件主要包含以下内容,用于定位真正的镜像层数据(位于/var/lib/docker/overlay2/)

1
2
3
4
5
6
7
8
9
10
11
root@debian:/var/lib/docker/image/overlay2/layerdb/mounts/6e9d18b4213dbd02abfb392ee14c3d00c103a4b21701495cf70eb9c91dbb49cc# ls
init-id  mount-id  parent

root@debian:/var/lib/docker/image/overlay2/layerdb/mounts/6e9d18b4213dbd02abfb392ee14c3d00c103a4b21701495cf70eb9c91dbb49cc# cat init-id 
983919beba7649a2c10150782c4025b83643c9c058bbb35330083b9d731a0045-init

root@debian:/var/lib/docker/image/overlay2/layerdb/mounts/6e9d18b4213dbd02abfb392ee14c3d00c103a4b21701495cf70eb9c91dbb49cc# cat mount-id 
983919beba7649a2c10150782c4025b83643c9c058bbb35330083b9d731a0045

root@debian:/var/lib/docker/image/overlay2/layerdb/mounts/6e9d18b4213dbd02abfb392ee14c3d00c103a4b21701495cf70eb9c91dbb49cc# cat parent 
sha256:dc0585a4b8b71f7f4eb8f2e028067f88aec780d9ab40c948a8d431c1aeadeeb5
  • mount-id:存储在/var/lib/docker/overlay2/的目录名称,其中的merged目录为容器运行的目录(镜像层、init层和容器层的联合挂载)
  • init-id:init-id是在mount-id后加了一个-init,同时init-id就是存储在/var/lib/docker/overlay2/的目录名称,存储/etc/hosts、/etc/resolv.conf等配置文件,为容器的init层
  • parent:容器所基于的镜像的最上层的chain_id

sha256

sha256目录存储镜像层的元文件信息,以layer的chain-id命名。

chain-id是由diff-id转换而来的,具体可见oci-image-spec中的解释。

简单来说最底层的layer的chain-id等于其diff-id;

高层的layer的chain-id等于上一层的chain-id与其diff-id的sha256值,例如第二层b的chain-id为sha256(chain-id(a) + diff-id(b)) = sha256(diff-id(a) + diff-id(b)) = sha256sum “sha256:xxxxx sha256:xxx”

单个文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@debian:/var/lib/docker/image/overlay2/layerdb/sha256/fc0c41d1a2e2d77359e7e8ce875933293ef769d32feb2cd3dc79b61f3edbbe6c# ls -l
total 144
-rw-r--r-- 1 root root     64 Jul 21 17:31 cache-id
-rw-r--r-- 1 root root     71 Jul 21 17:31 diff
-rw-r--r-- 1 root root     71 Jul 21 17:31 parent
-rw-r--r-- 1 root root      7 Jul 21 17:31 size
-rw-r--r-- 1 root root 127848 Jul 21 17:31 tar-split.json.gz

root@debian:/var/lib/docker/image/overlay2/layerdb/sha256/fc0c41d1a2e2d77359e7e8ce875933293ef769d32feb2cd3dc79b61f3edbbe6c# cat cache-id 
24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5

root@debian:/var/lib/docker/image/overlay2/layerdb/sha256/fc0c41d1a2e2d77359e7e8ce875933293ef769d32feb2cd3dc79b61f3edbbe6c# cat diff 
sha256:c00acf6f4f58f29b845ee034bf403750e0735ebcfcd2500427f5fa131033366b

root@debian:/var/lib/docker/image/overlay2/layerdb/sha256/fc0c41d1a2e2d77359e7e8ce875933293ef769d32feb2cd3dc79b61f3edbbe6c# cat parent 
sha256:21e7914e06fb3d26ac5cd44a4c2782a2dc524c9efaa1eed3b144b7b34e7948df

root@debian:/var/lib/docker/image/overlay2/layerdb/sha256/fc0c41d1a2e2d77359e7e8ce875933293ef769d32feb2cd3dc79b61f3edbbe6c# cat size
7518792
  • cache-id:docker下载layer的时候在本地生成的一个随机uuid,指向真正存放layer文件的地方(/var/lib/docker/overlay2/<cache-id>)
  • diff:当前layer的diff_id。
  • parent:当前layer的父layer的diff_id,最底层的layer不含此文件
  • size:当前layer的大小,单位是字节
  • tar-split.json.gz:layer压缩包的split文件,通过这个文件可以还原layer的tar包,在docker save导出image的时候会用到

/var/lib/docker/overlay2/<cache-id>

此目录用于存储镜像层的实际数据:

1
2
3
4
5
6
7
8
root@debian:/var/lib/docker/overlay2/24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5# ls
committed  diff  link  lower  work
root@debian:/var/lib/docker/overlay2/24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5# ls diff/
etc  harbor  home  run  usr  var
root@debian:/var/lib/docker/overlay2/24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5# cat link
GXXH6DHT3KL47AJ55XB3GQWO5B
root@debian:/var/lib/docker/overlay2/24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5# ls -l /var/lib/docker/overlay2/l/GXXH6DHT3KL47AJ55XB3GQWO5B
lrwxrwxrwx 1 root root 72 Jul 21 17:31 /var/lib/docker/overlay2/l/GXXH6DHT3KL47AJ55XB3GQWO5B -> ../24268712204d9aef7a10308a577cf6c149506f7414ff367a4ff869cf27c5fcf5/diff
  • diff:存储该层的实际内容
  • link:层的标识符(更短的符号链接,位于/var/lib/docker/overlay2/l,指向此目录的diff)
  • lower:父层镜像的符号链接,当启动容器时会将link以及lower的符号链接指向的目录联合挂载到merged目录,构建出整个容器的层次结构
  • merged:容器的工作目录,只有在容器启动时存在
  • work:用于cow