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

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

本文CSDN博客链接:http://blog.csdn.net/screscent/article/details/51314497

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日

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

时间: 2024-08-30 15:52:12

【原创】docker源码分析(3)---镜像(1)的相关文章

docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储

前段时间一直忙些其他事情,docker源码分析的事情耽搁了,今天接着写,上一章了解了docker client 和 docker daemon(会启动一个http server)是C/S的结构,client端发出的命令由docker daemon接收并处理. 我们在运行docker的时候,可能会使用到docker run命令(当然通过Dockerfile运行docker build命令也是一样的)时,如果本地没有你需要的镜像,docker daemon首先会去下载你需要的docker镜像,然后存

Docker源码分析(九):Docker镜像

1.前言 回首过去的2014年,大家可以看到Docker在全球刮起了一阵又一阵的“容器风”,工业界对Docker的探索与实践更是一波高过一波.在如今的2015年以及未来,Docker似乎并不会像其他昙花一现的技术一样,在历史的舞台上热潮褪去,反而在工业界实践与评估之后,显现了前所未有的发展潜力. 究其本质,“Docker提供容器服务”这句话,相信很少有人会有异议.那么,既然Docker提供的服务属于“容器”技术,那么反观“容器”技术的本质与历史,我们又可以发现什么呢?正如前文所提到的,Docke

Docker源码分析——互动出版网

这篇是计算机类的优质预售推荐>>>><Docker源码分析> 编辑推荐 国内首部Docker源码分析著作 从源码角度全面解析Docker设计与实现 填补Docker理论与实践之间的鸿沟 内容简介 本书是一本引导读者深入了解Docker实现原理的技术普及读物,主要目标是通过对Docker架构和源代码的详细讲解和解剖,帮助读者对Docker的底层实现有一个全面的理解.本书的内容主要集中于三部分:Docker的架构.Docker的模块,以及Docker的三驾马车Swarm.M

docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;

最近在研究golang,也学习一下比较火的开源项目docker的源代码,国内比较出名的docker源码分析是孙宏亮大牛写的一系列文章,但是基于的docker版本有点老:索性自己就git 了一下最新的代码研读: docker是c/s的架构,分为docker client 和 docker daemon,client端发送命令,daemon端负责完成client发送过来的命令(如获取和存储镜像.管理容器等).两者之间可以通过TCP,HTTP和UNIX SOCKET来进行通信: docker的启动入口

Docker源码分析(一):Docker架构

[编者按]在<深入浅出Docker>系列文章的基础上,InfoQ推出了<Docker源码分析>系列文章.<深入浅出Docker>系列文章更多的是从使用角度出发,帮助读者了解Docker的来龙去脉,而<Docker源码分析>系列文章通过分析解读Docker源码,来让读者了解Docker的内部实现,以更好的使用Docker.总之,我们的目标是促进Docker在国内的发展以及传播.另外,欢迎加入InfoQ Docker技术交流群,QQ群号:272489193. 1

Docker源码分析(三):Docker Daemon启动

1 前言 Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮.在这一潮流下,Google.IBM.Redhat等业界翘楚纷纷加入Docker阵营.虽然目前Docker仍然主要基于Linux平台,但是Microsoft却多次宣布对Docker的支持,从先前宣布的Azure支持Docker与Kubernetes,到如今宣布的下一代Windows Server原生态支持Docker.Microsoft的这一系列举措多少喻示着向Linux世界的妥协,当然这也不得不让世人对Docker的巨大影响

Docker源码分析(四):Docker Daemon之NewDaemon实现

1. 前言 Docker的生态系统日趋完善,开发者群体也在日趋庞大,这让业界对Docker持续抱有极其乐观的态度.如今,对于广大开发者而言,使用Docker这项技术已然不是门槛,享受Docker带来的技术福利也不再是困难.然而,如何探寻Docker适应的场景,如何发展Docker周边的技术,以及如何弥合Docker新技术与传统物理机或VM技术的鸿沟,已经占据Docker研究者们的思考与实践. 本文为<Docker源码分析>第四篇——Docker Daemon之NewDaemon实现,力求帮助广

Docker源码分析(二):Docker Client创建与命令执行

1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置.便捷的集成测试方法以及一键式的部署方式.可以说,Docker的优势在简化持续集成.运维部署方面体现得淋漓尽致,它完全让开发者从持续集成.运维部署方面中解放出来,把精力真正地倾注在开发上. 然而,把Docker的功能发挥到极致,并非一件易事.在深刻理解Docker架构的情况下,熟练掌握Docker C

Docker源码分析(八):Docker Container网络(下)

1.Docker Client配置容器网络模式 Docker目前支持4种网络模式,分别是bridge.host.container.none,Docker开发者可以根据自己的需求来确定最适合自己应用场景的网络模式. 从Docker Container网络创建流程图中可以看到,创建流程第一个涉及的Docker模块即为Docker Client.当然,这也十分好理解,毕竟Docker Container网络环境的创建需要由用户发起,用户根据自身对容器的需求,选择网络模式,并将其通过Docker Cl

Docker源码分析(六):Docker Daemon网络

1. 前言 Docker作为一个开源的轻量级虚拟化容器引擎技术,已然给云计算领域带来了新的发展模式.Docker借助容器技术彻底释放了轻量级虚拟化技术的威力,让容器的伸缩.应用的运行都变得前所未有的方便与高效.同时,Docker借助强大的镜像技术,让应用的分发.部署与管理变得史无前例的便捷.然而,Docker毕竟是一项较为新颖的技术,在Docker的世界中,用户并非一劳永逸,其中最为典型的便是Docker的网络问题. 毋庸置疑,对于Docker管理者和开发者而言,如何有效.高效的管理Docker