码迷,mamicode.com
首页 > 其他好文 > 详细

【原创】docker源码分析(3)---镜像(1)

时间:2016-05-06 15:30:28      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:

本文QQ空间链接:http://user.qzone.qq.com/29185807/blog/1462342295


1、简介

镜像无疑是docker中的一个重要角色。在分析源码之前,我们先要了解下image的一些概念。可以参考 http://www.sel.zju.edu.cn/?p=549

 

       docker中,为了复用image,将image做成,可继承的方式。子image可以继承父image的rootfs,通过分层的方式一层一层的进行继承复用,减少镜像的大小,提高存储复用。

       这里有几个概念

1、rootfs,是容器启动的时候,其所可以用到的是文件系统目录。

2、image,是一个只读的文件系统。通过继承父image的文件系统,然后union mount到一起,形成一个rootfs。

3、layer,image的各个分层就属于layer,由于所有的image中的文件系统都是只读的。所以另外再在最顶层的image上面再添加一个read-write层。整个构成容器的运行环境。

 

       在源代码中是怎么实现这些的呢。通过graphdriver与作为中间模块,实现与底层的layer的文件系统打交道。而graph模块通过graphdriver来对image进行管理。下面我们来看源码。

 

2、graphdriver

源码在docker\docker\daemon.go

mainDaemon中初始化

d, err := daemon.NewDaemon(daemonCfg, eng)

我们继续跟进

源码在docker\daemon\daemon.go

技术分享

NewDaemonFromDirectory函数中

技术分享

初始化了graphdriver,初始化流程到这里。下面我们具体的去看下graphdriver源码。

2.1 driver接口

driver一共有两部分的接口

技术分享

protodriver,是比较基础部分的,直接与文件存储打交道。从上面的函数名我们就能看出来提供的作用。如

Create:用于创建一个新的layer。

Remove:删除一个layer。

就不一一解释了,其英文的注释已经说明了

 技术分享

driver接口其实是继承了protodriver接口,另外还提供了image与父image直接的一些操作,如diff用于获取image与父image之间的差别,等就不一一介绍。

 

2.2 插件注册与获取

driver通过插件形式来设计的。(这个也是golang设计中,经常用到的模式)

技术分享

技术分享

首先在init中初始化了一个map,用于保存插件的入口。然后提供了Register函数,用于插件的注册

技术分享

另外提供了一个获取插件的函数。

 

那我们看看是如何New的

技术分享

通过环境变量DOCKER_DRIVER,driver的类型,然后查找插件列表,然后通过GetDriver获取Driver。

那我们看看docker中都提供了哪些类型的driver

技术分享

有aufs,btrfs,devmapper,overlay,vfs一共五种方式的driver。

 

2.3 vfs

这里我们就以一个最简单的模块来做演示vfs

代码在docker\daemon\graphdriver\vfs\driver.go

首先是注册

技术分享

这里通过init注册了vfs方式的driver,初始函数为Init

 

我们来看看这个driver的具体情况(这个比较简单比较适合于演示)

技术分享

以上不做解释

 技术分享

这里是Create,这里其实就是一个拷贝动作。

 

另外vfs并没有实现Driver接口,其只实现了protoDriver接口。是通过再封装了一层来实现的Driver接口的

docker\daemon\graphdriver\fsdiff.go

技术分享

这里就不再详细介绍了。

 

2.4 小结

graphdriver通过插件的方式,提供了多种的底层drvier。

 

3、image

这里的image指的是源码里面的image

代码在docker\image\image.go

先看结构体

技术分享

很明显这是一个json结构体

 

我们看看LoadImage

技术分享

通过读取json文件,然后解析获取image结构体信息。

下面给一个示例

{

  "Size": 0,

  "os": "linux",

  "id": "fef924a0204a00b3ec67318e2ed337b189c99ea19e2bf10ed30a13b87c5e17ab",

  "parent": "9a163e0b8d138ec700b5a5f7e62509012f7eb34b9f86cd3bbeb3d183958114a9",

  "created": "2016-02-16T22:59:37.407805421Z",

  "container": "d23509cd0189de02bef382544ebfab515f29094f3c0e2f161fa7ce09afa8974e",

  "container_config": {

    "Labels": {},

    "OnBuild": null,

    "MacAddress": "",

    "NetworkDisabled": false,

    "Entrypoint": null,

    "WorkingDir": "",

    "PublishService": "",

    "ExposedPorts": null,

    "AttachStderr": false,

    "AttachStdout": false,

    "AttachStdin": false,

    "User": "",

    "Domainname": "",

    "Hostname": "13709f13afe1",

    "Tty": false,

    "OpenStdin": false,

    "StdinOnce": false,

    "Env": null,

    "Cmd": [

      "/bin/sh",

      "-c",

      "#(nop) CMD [\"sh\"]"

    ],

    "Image": "9a163e0b8d138ec700b5a5f7e62509012f7eb34b9f86cd3bbeb3d183958114a9",

    "Volumes": null,

    "VolumeDriver": ""

  },

  "docker_version": "1.9.1",

  "config": {

    "Labels": {},

    "OnBuild": null,

    "MacAddress": "",

    "NetworkDisabled": false,

    "Entrypoint": null,

    "WorkingDir": "",

    "PublishService": "",

    "ExposedPorts": null,

    "AttachStderr": false,

    "AttachStdout": false,

    "AttachStdin": false,

    "User": "",

    "Domainname": "",

    "Hostname": "13709f13afe1",

    "Tty": false,

    "OpenStdin": false,

    "StdinOnce": false,

    "Env": null,

    "Cmd": [

      "sh"

    ],

    "Image": "9a163e0b8d138ec700b5a5f7e62509012f7eb34b9f86cd3bbeb3d183958114a9",

    "Volumes": null,

    "VolumeDriver": ""

  },

  "architecture": "amd64"

}

 

以上这个是我在网上下载的一个image

 

下面是StoreImage

技术分享

将image的信息,通过json编码保存到文件。

 

另外还提供了一些操作,就不一一做解读。

 

4、Graph

源码在docker\daemon\daemon.go

在初始化graphdriver之后,便初始化了graph

技术分享

 

下面我们看看graph

代码在docker\graph\graph.go

技术分享

主要保存了一个driver

技术分享

graph目录中保存了image信息

 

我们看看

技术分享

restore的时候,会扫描所有的目录,并将imageid给记录下来

 

那我们挑选几个提供的接口看看

 技术分享

get通过name来获取image id,然后通过imageid,来loadImage,从而获取image的信息

 技术分享

以上是整个create的过程,先构建image结构体,然后调用Register。

技术分享

先查找是否存在,存在则直接返回。

技术分享

如果不存在则将其他多余无用的重复信息删除,然后最后调用了driver进行Create。

 

graph还提供其他的很多操作,不再做分析了。

 

由于csdn博客显示不全所以分成两篇,继续请看下一篇

 

龚浩华

QQ 月牙寂 29185807

2016年5月4日

(版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。)


【原创】docker源码分析(3)---镜像(1)

标签:

原文地址:http://blog.csdn.net/screscent/article/details/51314497

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!