Docker Client创建与命令执行

1. 前言

如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖、便捷的软件集成测试与部署之道。在团队开发软件时,Docker可以提供可复用的运行环境、灵活的资源配置、便捷的集成测试方法以及一键式的部署方式。可以说,Docker的优势在简化持续集成、运维部署方面体现得淋漓尽致,它完全让开发者从持续集成、运维部署方面中解放出来,把精力真正地倾注在开发上。

然而,把Docker的功能发挥到极致,并非一件易事。在深刻理解Docker架构的情况下,熟练掌握Docker Client的使用也非常有必要。前者可以参阅《Docker源码分析》系列之Docker架构篇,而本文主要针对后者,从源码的角度分析Docker Client,力求帮助开发者更深刻的理解Docker Client的具体实现,最终更好的掌握Docker Client的使用方法。即本文为《Docker源码分析》系列的第二篇——Docker Client篇。

2. Docker Client源码分析章节安排

本文从源码的角度,主要分析Docker Client的两个方面:创建与命令执行。整个分析过程可以分为两个部分:

第一部分分析Docker Client的创建。这部分的分析可分为以下三个步骤:

  • 分析如何通过docker命令,解析出命令行flag参数,以及docker命令中的请求参数;
  • 分析如何处理具体的flag参数信息,并收集Docker Client所需的配置信息;
  • 分析如何创建一个Docker Client。

第二部分在已有Docker Client的基础上,分析如何执行docker命令。这部分的分析又可分为以下两个步骤:

  • 分析如何解析docker命令中的请求参数,获取相应请求的类型;
  • 分析Docker Client如何执行具体的请求命令,最终将请求发送至Docker Server。

3. Docker Client的创建

Docker Client的创建,实质上是Docker用户通过可执行文件docker,与Docker Server建立联系的客户端。以下分三个小节分别阐述Docker Client的创建流程。

以下为整个docker源代码运行的流程图:

上图通过流程图的方式,使得读者更为清晰的了解Docker Client创建及执行请求的过程。其中涉及了诸多源代码中的特有名词,在下文中会一一解释与分析。

3.1. Docker命令的flag参数解析

众所周知,在Docker的具体实现中,Docker Server与Docker Client均由可执行文件docker来完成创建并启动。那么,了解docker可执行文件通过何种方式区分两者,就显得尤为重要。

对于两者,首先举例说明其中的区别。Docker Server的启动,命令为docker -d或docker --daemon=true;而Docker Client的启动则体现为docker --daemon=false ps、docker pull NAME等。

可以把以上Docker请求中的参数分为两类:第一类为命令行参数,即docker程序运行时所需提供的参数,如: -D、--daemon=true、--daemon=false等;第二类为docker发送给Docker Server的实际请求参数,如:ps、pull NAME等。

对于第一类,我们习惯将其称为flag参数,在go语言的标准库中,同时还提供了一个flag包,方便进行命令行参数的解析。

交待以上背景之后,随即进入实现Docker Client创建的源码,位于./docker/docker/docker.go,该go文件包含了整个Docker的main函数,也就是整个Docker(不论Docker Daemon还是Docker Client)的运行入口。部分main函数代码如下:

func main() {
    if reexec.Init() {
      return
    }
    flag.Parse()
    // FIXME: validate daemon flags here
    ……
}


在以上代码中,首先判断reexec.Init()方法的返回值,若为真,则直接退出运行,否则的话继续执行。查看位于./docker/reexec/reexec.go中reexec.Init()的定义,可以发现由于在docker运行之前没有任何的Initializer注册,故该代码段执行的返回值为假。

紧接着,main函数通过调用flag.Parse()解析命令行中的flag参数。查看源码可以发现Docker在./docker/docker/flag.go中定义了多个flag参数,并通过init函数进行初始化。代码如下:

var (
  flVersion     = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
  flDaemon      = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
  flDebug       = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
  flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specified by -H when running in daemon mode use '' (the empty string) to disable setting of a group")
  flEnableCors  = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
  flTls         = flag.Bool([]string{"-tls"}, false, "Use TL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值