DOCKER源码分析1 docker client命令行执行流程
源码阅读基于docker 19.03
1. docker client的入口main
1.1 源码
docker client的main函数位于cli/cmd/docker/docker.go,代码的主要内容是:
funcmain(){...dockerCli:=command.NewDockerCli(stdin,stdout,stderr)cmd:=newDockerCommand(dockerCli)iferr:=cmd.Execute();...}
这部分代码的主要工作是:
- 生成一个带有输入输出的客户端对象
- 根据dockerCli客户端对象,解析命令行参数,生成带有命令行参数及客户端配置信息的cmd命令行对象
- 根据输入参数args完成命令执行
1.2 流程图
我们需要追踪的是docker run的执行流程,从流程图中可以看到,从cmd := newDockerCommand(dockerCli)的一步步进行下去,可以追踪到runContainer(dockerCli,opts,copts,contianerConfig),而这里就是run命令的执行函数。 在具体了解runContainer()的具体执行之前,先了解一下cobra.Command结构体。
1.3 cobra.Command
1.3.1 首先介绍cobra这个库的简单使用:
packagemainimport("fmt""github.com/spf13/cobra")funcmain(){//1.定义主命令varVersionboolvarrootCmd=&cobra.Command{Use:"root [sub]",Short:"My root command",//命令执行的函数Run:func(cmd*cobra.Command,args[]string){fmt.Printf("Inside rootCmd Run with args: %v\n",args)ifVersion{fmt.Printf("Version:1.0\n")}},}//2.定义子命令varsubCmd=&cobra.Command{Use:"sub [no options!]",Short:"My subcommand",//命令执行的函数Run:func(cmd*cobra.Command,args[]string){fmt.Printf("Inside subCmd Run with args: %v\n",args)},}//添加子命令rootCmd.AddCommand(subCmd)//3.为命令添加选项flags:=rootCmd.Flags()flags.BoolVarP(&Version,"version","v",false,"Print version information and quit")//执行命令_=rootCmd.Execute()}
基本用法大概就是四步:
- 定义一个主命令(包含命令执行函数等)
- 定义若干子命令(包含命令执行函数等,根据需要可以为子命令定义子命令),并添加到主命令
- 为命令添加选项
- 执行命令
1.3.2 docker中cobra.Command的使用
docker中Command的使用就体现在commands.AddCommands()。在commands.AddCommands(cmd, dockerCli)中,将run、build等一些命令的执行函数添加到commands中。
2. runContainer()
2.1 源码
runContainer()的代码位于cli/command/container/run.go代码的主要部分为:
funcrunContainer(dockerCli*command.DockerCli,opts*runOptions,copts*containerOptions,containerConfig*containerConfig)error{config:=containerConfig.ConfighostConfig:=containerConfig.HostConfig...createResponse,err:=createContainer(ctx,dockerCli,containerConfig,opts.name)//向daemon发送create...client.ContainerStart(ctx,createResponse.ID,types.ContainerStartOptions{})////向daemon发送post}
2.2 流程图
在ContainerCreate()和ContainerStart()中分别向daemon发送了create和start命令。下一步,就需要到docker daemon中分析daemon对create和start的处理。
结语
本文分析了docker client对于docker run命令的处理流程,从上文的分析中的最后可以看到,client向daemon分别发送了create和start两个命令,这是容易创建的两个步骤,在下一篇文章中将分析daemon的处理流程。
参考