Docker Client是Docker架构中用户与Docker Daemon建立通信的客户端。本文基于Docker 18.02.0-ce的源码分析Docker Client的内容。主要包括两个部分,分别是:
- Docker Client的创建
- Docker Client对命令的执行
1、Docker Client的创建
对于Docker这样一个C/S架构,客户端的存在意味着Docker相应任务的发起。用户首先要创建一个Docker Client,然后将特定的请求类型与参数传递至Docker Client,最终由Docker Client转义成Docker Server能识别的形式,并发送至Docker Server。
Docker Client的main函数位于docker-ce/components/cli/cmd/docker/docker.go,代码如下。
func main() {
// Set terminal emulation based on platform as required.
stdin, stdout, stderr := term.StdStreams()
logrus.SetOutput(stderr)
// 创建Cli,返回一个DockerCli实例
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
// 创建cmd,配置一定的参数并添加所有子命令
cmd := newDockerCommand(dockerCli)
// 执行cmd
if err := cmd.Execute(); err != nil {
if sterr, ok := err.(cli.StatusError); ok {
if sterr.Status != "" {
fmt.Fprintln(stderr, sterr.Status)
}
// StatusError should only be used for errors, and all errors should
// have a non-zero exit status, so never exit with 0
if sterr.StatusCode == 0 {
os.Exit(1)
}
os.Exit(sterr.StatusCode)
}
fmt.Fprintln(stderr, err)
os.Exit(1)
}
}
1)NewDockerCli方法位于docker-ce/components/cli/cli/command/cli.go文件,它返回一个DockerCli类型的对象实例。代码如下:
// DockerCli is an instance the docker command line client.
// Instances of the client can be returned from NewDockerCli.
type DockerCli struct {
configFile *configfile.ConfigFile
in *InStream
out *OutStream
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
}
// ServerInfo stores details about the supported features and platform of the server
type ServerInfo struct {
HasExperimental bool
OSType string
}
// ClientInfo stores details about the supported features of the client
type ClientInfo struct {
HasExperimental bool
DefaultVersion string //api.defaultVersion or DOCKER_API_VERSION
Orchestrator Orchestrator
}
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err.
func NewDockerCli(in io.ReadCloser, out, err io.Writer) *DockerCli {
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err} // 创建并初始化DockerCli类型的对象实例
}
2)newDockerCommand与main函数同在docker-ce/components/cli/cmd/docker/docker.go文件中,它根据DockerCli类型的对象实例,返回cobra.Command对象实例。
先了解几个库:
"github.com/sirupsen/logrus" //结构话的log库
"github.com/spf13/cobra" //命令行的库
"github.com/spf13/pflag" //用于替代go自身的flag包
newDockerCommand的代码如下:
// DockerCli实现了Command.Cli接口
func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
opts := cliflags.NewClientOptions() //配置