docker镜像的目录存储

关系概念

diffID:该镜像层的校验码ID,包含镜像层每层次内容的摘要,反映了单个层次内容的信息

chainID:docker内容寻址机制采用的索引ID,唯一标识了一组(像糖葫芦一样的串的底层)diffID的hash值,包含了这一层和它的父层(底层),当然这个糖葫芦可以有一颗山楂,也就是chainID(layer0)==diffID(layer0);对于多颗山楂的糖葫芦,ChainID(layerN) = SHA256hex(chainID(layerN-1) + " " + diffID(layerN))。镜像层次的重用需要chainID相同,如果只是diffID相同则不能命中。

cacheID:docker随机生成的uuid,内容是保存镜像层的目录索引,可以找到镜像内容实际存放的位置。

目录结构

/var/lib/docker/image/overlay2:存储镜像管理数据的目录,以使用的存储驱动命名

其中repositories.json文件相当于SAP UI5里的manifest.json, 以及nodejs项目中的project.json

这里的c549ccf8d472是layerID。因为pull下来的是压缩的数据,layerID是压缩数据的sha256的值(Layer ID指Distribution根据layer compressed data计算的)。下面的Digest:aba80b其实是manifest内容的sha256值。

而inspect rootfs中的值是解压后,对解压的内容进行sha256的值他们是diffID,是在本地由Docker根据layer uncompressed data计算的。

从远程拉取下来的layerID和解压后的diffID之间的对应关系存储在/var/lib/docker/image/overlay2/distribution中。


/var/lib/docker/image/overlay2/distribution:从远端拉到本地的镜像相关元数据

diffid-by-digest保存了digest(layerID)->diffID的映射关系,即distribution hashes和Content hashes的映射关系。也即是正向查询。

v2metadata-by-diffid保存了diffid -> (digest,repository)的映射关系,这可以方便查找layer的digest及其所属的repository。也即是反向查询,可以从diffID->layerID(其实就是digest)。


/var/lib/docker/image/overlay2/repositories.json:

里面存放的是每个repository的名字(ubuntu)以及每个repository下所有版本镜像的名字一起tag(ubuntu:latesta)和该镜像的ImageID(cd6d8154f1e...)


/var/lib/docker/image/overlay2/imagedb:镜像数据库

        /content:构成镜像的每层的配置数据

                /sha256/:每个镜像层的配置digest,也就是ImageID(唯一标志一个镜像,其数值根据该镜像的元数据配置文件采用sha256算法的计算获得)。

              (参考源码:github.com/docker/docker/image/store.go:store.Create(config[]byte)(ID, error))

        /metadata:

                /sha256/:具有父镜像的层次ID,没有父镜像的基础镜像在此目录没有内容

                        /parent:父镜像ImageID。(参考源码:github.com/docker/docker/daemon/build.go:Daemon.CreateImage(config[]byte,parent string,platform string)(builder.Image, error))


/var/lib/docker/image/overlay2/layerdb:镜像每层元数据

        /mounts:容器的读写层信息

                /:

                        /init-id:读写层的cache-ID

                        /cache-id:读写层的mount-ID

                        /parent:父镜像的chainID

        /sha256:

               每层的chainID/:

                        /cache-ID:本layer在/var/lib/docker/overlay2所对应的cache-ID(由宿主机随机生成的一个uuid,根镜像层文件一一对应,用于宿主机标志和索引镜像层文件)

                        /diff:本层次的diffID(镜像层校验ID、根据该镜像层的打包文件校验获得)

                        /size:本层次的大小

                        /parent:父 镜像 的 chainID(docker内容寻址机制采用的索引ID,其值根据当前层和所有祖先层的diffID算得:该镜像层是最底层,那么其chainIDdiffID 相同。否则,chainID=sha256(父层chainID+" "+本层diffID

                        tar-split.json.gz:layer压缩包的split文件,通过这个文件可以还原layer的tar包,在 docker save 导出image的时候会用到。详情可参考 GitHub - vbatts/tar-split: checksum-reproducible tar archives (utility/library)


/var/lib/docker/overlay2:镜像的所有layer和容器rwlayer的位置 

        /l:符号链接目录,每一个符号链接文件链接向下面的cache-ID,一一对应,使用这个符号链接的目的是因为mount args最大限制为一个pagesize.

        /cache-id:layer的cache-id为一个随机值(参考源码:moby/layer/layer_unix.go:layerStore.mountID(namestring)string)

                /diff:本layer所包含的实际文件系统数据

                link:存储本cache-id所对应的符号链接

                lower:本layer的所有父layer所对应的符号链接

                /megerd:本layer及所有父layer共同呈现的目录

                /work:overlay2文件系统使用的目录

         /cache-id-init:容器的init层目录


各ID之间关系和计算

1、layerID ---> diffID(通过/var/lib/docker/image/overlay2/distribution/下的diffid-by-digest和v2metadata-by-diffid可以知道layerID和diffID的对应关系)

2、diffID ---> chainID(chainID(n)=SHA256(chain(n-1) diffID(n)))

3、chainID ---> cacheID (通过cache-id文件)

4、cacheID ---> 找到最终的磁盘文件


镜像构建


镜像导入

镜像导出的逆过程。参考代码:image/tarexport/load.go:Load

过程:

1、创建临时目录(/tmp/XRFMG/docker-import-),对镜像压缩包进行解压

2、读取manifest.json文件,获取config文件名,文件名为.json

3、从配置文件中获取所有层的diffIDS,遍历所有diffIDS,依次加载

如果layer的chainID已经存在,则不再导入

如果layer的chainID不存在,则导入

导入后判断导入layer的diffID与配置文件中是否相等,不相等则报错

镜像pull流程

  1. docker发送image的名称+tag(或者digest)给registry服务器,服务器根据收到的image的名称+tag(或者digest),找到相应image的manifest,然后将manifest返回给docker
  2. docker得到manifest后,读取里面image配置文件的digest(sha256),这个sha256码就是imageID
    {
      "schemaVersion": 2,
      "config": {
        "mediaType": "application/vnd.oci.image.config.v1+json",
        "size": 7023,
        "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
      },
      "layers": [
        {
          "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
          "size": 32654,
          "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"
        },
        {
          "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
          "size": 16724,
          "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
        },
        {
          "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
          "size": 73109,
          "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
        }
      ],
      "annotations": {
        "com.example.key1": "value1",
        "com.example.key2": "value2"
      }
    }
    
    这里layer的sha256和image config文件中的diff_ids有可能不一样,比如这里的layer文件格式是tar+gzip,那么这里的sha256就是tar+gzip包的sha256码,而diff_ids是tar+gzip解压后tar文件的sha256码
  3. 根据imageID在本地找有没有存在同样ID的image,有的话就不用继续下载了
  4. 如果没有,那么会给registry服务器发请求(里面包含配置文件的sha256和media type),拿到image的配置文件(Image Config)
    {
        "created": "2015-10-31T22:22:56.015925234Z",
        "author": "Alyssa P. Hacker <alyspdev@example.com>",
        "architecture": "amd64",
        "os": "linux",
        "config": {
            "User": "alice",
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "FOO=oci_is_a",
                "BAR=well_written_spec"
            ],
            "Entrypoint": [
                "/bin/my-app-binary"
            ],
            "Cmd": [
                "--foreground",
                "--config",
                "/etc/my-app.d/default.cfg"
            ],
            "Volumes": {
                "/var/job-result-data": {},
                "/var/log/my-app-logs": {}
            },
            "WorkingDir": "/home/alice",
            "Labels": {
                "com.example.project.git.url": "https://example.com/project.git",
                "com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b"
            }
        },
        "rootfs": {
          "diff_ids": [
            "sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
            "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
          ],
          "type": "layers"
        },
        "history": [
          {
            "created": "2015-10-31T22:22:54.690851953Z",
            "created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
          },
          {
            "created": "2015-10-31T22:22:55.613815829Z",
            "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
            "empty_layer": true
          }
        ]
    }
    
  5. 根据配置文件中的diff_ids,在本地找对应的layer是否存在
  6. 如果layer不存在,则根据manifest里面layer的sha256(也就是前面说的layerID)和media type去服务器拿相应的layer(相当去拿压缩格式的包)
  7. 拿到后进行解压,并检查解压后tar包的sha256(也就是前面说的diffID)能否和配置文件(Image Config)中的diff_id对的上,对不上说明有问题,下载失败
  8. 根据docker所用的后台文件系统类型,解压tar包并放到指定的目录
  9. 等所有的layer都下载完成后,整个image下载完成,就可以使用了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值