赞
踩
【Docker源码分析(三):Docker Daemon启动】Docker作为业界备受推崇的轻量级虚拟化容器管理引擎,其强大的后台能力全凭Docker Daemon。本文从源码出发,介绍了Docker Daemon的启动流程,并深入分析启动流程中每一步骤的实现细节。Docker的运行真可谓,载体为daemon,调度管理由engine,任务执行靠job。
1 前言
Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮。在这一潮流下,Google、IBM、Redhat等业界翘楚纷纷加入Docker阵营。虽然目前Docker仍然主要基于Linux平台,但是Microsoft却多次宣布对Docker的支持,从先前宣布的Azure支持Docker与Kubernetes,到如今宣布的下一代Windows Server原生态支持Docker。Microsoft的这一系列举措多少喻示着向Linux世界的妥协,当然这也不得不让世人对Docker的巨大影响力有重新的认识。
Docker的影响力不言而喻,但如果需要深入学习Docker的内部实现,笔者认为最重要的是理解Docker Daemon。在Docker架构中,Docker Client通过特定的协议与Docker Daemon进行通信,而Docker Daemon主要承载了Docker运行过程中的大部分工作。本文即为《Docker源码分析》系列的第三篇——Docker Daemon篇。
2 Docker Daemon简介
Docker Daemon是Docker架构中运行在后台的守护进程,大致可以分为Docker Server、Engine和Job三部分。Docker Daemon可以认为是通过Docker Server模块接受Docker Client的请求,并在Engine中处理请求,然后根据请求类型,创建出指定的Job并运行,运行过程的作用有以下几种可能:向Docker Registry获取镜像,通过graphdriver执行容器镜像的本地化操作,通过networkdriver执行容器网络环境的配置,通过execdriver执行容器内部运行的执行工作等。
以下为Docker Daemon的架构示意图:
3 Docker Daemon源码分析内容安排
本文从源码的角度,主要分析Docker Daemon的启动流程。由于Docker Daemon和Docker Client的启动流程有很大的相似之处,故在介绍启动流程之后,本文着重分析启动流程中最为重要的环节:创建daemon过程中mainDaemon()的实现。
4 Docker Daemon的启动流程
由于Docker Daemon和Docker Client的启动都是通过可执行文件docker来完成的,因此两者的启动流程非常相似。Docker可执行文件运行时,运行代码通过不同的命令行flag参数,区分两者,并最终运行两者各自相应的部分。
启动Docker Daemon时,一般可以使用以下命令:docker --daemon=true; docker –d; docker –d=true等。接着由docker的main()函数来解析以上命令的相应flag参数,并最终完成Docker Daemon的启动。
首先,附上Docker Daemon的启动流程图:
由于《Docker源码分析》系列之Docker Client篇中,已经涉及了关于Docker中main()函数运行的很多前续工作(可参见Docker Client篇),并且Docker Daemon的启动也会涉及这些工作,故本文略去相同部分,而主要针对后续仅和Docker Daemon相关的内容进行深入分析,即mainDaemon()的具体源码实现。
5 mainDaemon( )的具体实现
通过Docker Daemon的流程图,可以得出一个这样的结论:有关Docker Daemon的所有的工作,都被包含在mainDaemon()方法的实现中。
宏观来讲,mainDaemon()完成创建一个daemon进程,并使其正常运行。
从功能的角度来说,mainDaemon()实现了两部分内容:第一,创建Docker运行环境;第二,服务于Docker Client,接收并处理相应请求。
从实现细节来讲,mainDaemon()的实现过程主要包含以下步骤:
* daemon的配置初始化(这部分在init()函数中实现,即在mainDaemon()运行前就执行,但由于这部分内容和mainDaemon()的运行息息相关,故可认为是mainDaemon()运行的先决条件);
* 命令行flag参数检查;
* 创建engine对象;
* 设置engine的信号捕获及处理方法;
* 加载builtins;
* 使用goroutine加载daemon对象并运行;
* 打印Docker版本及驱动信息;
* Job之”serveapi”的创建与运行。
下文将一一深入分析以上步骤。
5.0 配置初始化
在mainDaemon()运行之前,关于Docker Daemon所需要的config配置信息均已经初始化完毕。具体实现如下,位于./docker/docker/daemon.go:
- var (
- daemonCfg = &daemon.Config{}
- )
- func init() {
- daemonCfg.InstallFlags()
- }
首先,声明一个为daemon包中Config类型的变量,名为daemonCfg。而Config对象,定义了Docker Daemon所需的配置信息。在Docker Daemon在启动时,daemonCfg变量被传递至Docker Daemon并被使用。
Config对象的定义如下(含部分属性的解释),位于./docker/daemon/config.go:
- type Config struct {
- Pidfile string //Docker Daemon所属进程的PID文件
- Root string //Docker运行时所使用的root路径
- AutoRestart bool //已被启用,转而支持docker run时的重启
- Dns []string //Docker使用的DNS Server地
- DnsSearch []string //Docker使用的指定的DNS查找域名
- Mirrors []string //指定的优先Docker Registry镜像
- EnableIptables bool //启用Docker的iptables功能
- EnableIpForward bool //启用net.ipv4.ip_forward功能
- EnableIpMasq bool //启用IP伪装技术
- DefaultIp net.IP //绑定容器端口时使用的默认IP
- BridgeIface string //添加容器网络至已有的网桥
- BridgeIP string //创建网桥的IP地址
- FixedCIDR string //指定IP的IPv4子网,必须被网桥子网包含
- InterContainerCommunication bool //是否允许相同host上容器间的通信
- GraphDriver string //Docker运行时使用的特定存储驱动
- GraphOptions []string //可设置的存储驱动选项
- ExecDriver string // Docker运行时使用的特定exec驱动
- Mtu int //设置容器网络的MTU
- DisableNetwork bool //有定义,之后未初始化
- EnableSelinuxSupport bool //启用SELinux功能的支持
- Context map[string][]string //有定义,之后未初始化
- }
已经有声明的daemonCfg之后&
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。