2.3.1 Docker Client解析请求命令
Docker Client解析请求命令的工作,在Docker命令执行部分第一个完成。创建Docker Client之后,回到main函数中,继续执行的源码如下(位于./docker/docker/docker.go#L102-L110):
if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) }
学习以上源码可以发现,正如之前所说,Docker Client首先解析存放于flag.Args()中的具体请求参数,执行的函数为cli对象的Cmd函数。Cmd函数的定义如下(位于./docker/api/client/cli.go#L51-L61):
// Cmd executes the specified command func (cli *DockerCli) Cmd(args ...string) error { if len(args) > 0 { method, exists := cli.getMethod(args[0]) if !exists { fmt.Println("Error: Command not found:", args[0]) return cli.CmdHelp(args[1:]...) } return method(args[1:]...) } return cli.CmdHelp(args...) }
由代码注释可知,Cmd函数执行具体的指令。在源码实现中,首先判断请求参数列表的长度是否大于0。若长度不大于0,则说明没有请求信息,返回docker命令的Help信息;若长度大于1,则说明有请求信息,那么Docker Client首先通过请求参数列表中的第一个元素args[0]来获取具体的请求方法method。若上述method方法不存在,则返回docker命令的Help信息,若存在,调用具体的method方法,参数为args[1]及其之后所有的请求参数。
还是以一个具体的docker命令为例,docker--daemon=false--version=false pull Image_Name。通过以上Docker Client的分析,可以总结出以下执行流程。
1)解析flag参数之后,Docker将docker请求参数"pull"和"Image_Name"存放于flag.Args()。
2)创建好的Docker Client为cli,cli执行cli.Cmd(flag.Args()…)。
3)Cmd函数中,通过args[0]也就是"pull",执行cli.getMethod(args[0]),获取method的名称。
4)在getMothod方法中,Docker通过处理最终返回method值为"CmdPull"。
5)最终执行method(args[1:]…)也就是CmdPull(args[1:]…)。