第2章 Docker Client创建与命令执行

来二两敌敌畏 · · 1063 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

2.1 引言

本章基于Docker 1.2.0的源码,分析Docker Client的内容。主要包括两个部分,分别是Docker Client的创建与Docker Client对命令的执行。两部分分析的具体内容如下。

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

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

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

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

2.2 创建Docker Client

2.2.1 Docker命令的flag参数解析

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

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

部分main函数代码如下:

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

以上源码实现中,首先判断reexec.Init()方法的返回值,若为真,则直接退出运行,否则将继续执行。reexec.Init()函数的定义位于./docker/reexec/reexec.go,可以发现由于在docker运行之前没有任何Initializer注册,故该代码段执行的返回值为假。reexec存在的作用是:协调execdriver与容器创建时dockerinit这两者的关系。

判断reexec.Init()之后,Docker的main函数通过调用flag.Parse()函数,解析命令行中的flag参数。Docker在./docker/docker/flag.go中定义了多个flag参数,并通过init函数进行部分flag参数初始化。代码如下:

var (
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specifby -H when running in daemon modeuse '' (the empty string) to disable setting of a group")
flEnableCors = flag.Bool([]string{"tls"}, false, "Use TLS; implied by tls-verify flags")
flTls = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon")
// these are initialized in init() below since their default valus depend on dockerCertPath which isn't fully initialized until init() runs
flCa string
flCert
string
flKey *string
flHosts []string
)

func init() {
flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust only remotes providing a certficate signed by the CA given here")
flCert = flag.String([]string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file")
flKey = flag.String([]string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file)
opts.HostListVar(&flHosts, []string{"H", "-host"}, "The socket(s) to bind to in daemon mode\nspecified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd:socketfd.")
}

关于Golang中的init函数,深入分析可以得出以下特性:

  • init函数用于程序执行前包的初始化工作,比如初始化变量等;
  • 每个包可以有多个init函数;
  • 包的每一个源文件也可以有多个init函数;
  • 同一个包内的init函数的执行顺序没有明确的定义;
  • 不同包的init函数按照包导入的依赖关系决定初始化的顺序;
  • init函数不能被调用,而是在main函数调用前自动被调用。

2.2.2 如何创建Docker Client

Docker Client的创建其实就是在已有配置参数信息的情况下,通过Client包中的NewDockerCli方法创建一个Docker Client实例cli。

2.3 Docker命令执行

main函数执行到这个阶段,有以下内容需要为Docker命令的执行服务:创建完毕的Docker Client,docker命令中的请求(经flag解析后存放于flag.Arg())。也就是说,程序需要使用Docker Client来分析Docker命令中的请求参数,得出请求的类型,转义为Docker Server可以识别的请求之后,最终发送给Docker Server。

Docker Client主要完成两方面的工作:解析请求命令,得出请求类型;执行具体类型的请求。

2.3.1 Docker Client解析请求命令

Docker Client解析请求命令的工作,在Docker命令执行部分第一个完成。

2.3.2 Docker Client执行请求命令

不同的Docker尽管请求内容不同,但是请求执行流程大致相同,故本节依旧以一个例子来阐述其中的流程,例子为docker pull Image_Name。该命令的作用为:Docker Client发起下载镜像的请求,最终由Docker Server接收请求,由Docker Daemon完成镜像的下载与存储。

Docker Client在执行docker pull Image_Name请求命令时,执行CmdPull函数,传入参数为args[1:]...,即Image_Name。

若用户没有制定Docker Registry的地址,则Docker默认地址为Docker Hub地址https://index.docker.io/v1/。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:来二两敌敌畏

查看原文:第2章 Docker Client创建与命令执行

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1063 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传