上一篇文章咱们分析了docker run命令在Docker client中的处理,这一篇文章咱们分析在Docker daemon中的处理。
Docker client发送容器管理请求,由Docker daemon接收并处理。源码基于Docker-ce17.09
1、所谓“运行docker”,即运行Docker daemon。其主要有两方面的作用:
-
接收并处理 Docker Client 发送的请求。
-
管理所有的 Docker 容器。
Docker Daemon 运行时,会在后台启动一个 Server Se er 负责接收 Docker Client 发送 的请求;接收请求后, Server 通过路由与分发调度,找到相应的 Handler 来处理请求。
2、Docker daemon的结构分布:
Docker Server、Docker Engine 和 Docker Job。
2.1、Docker Server
Docker Server Docker 架构中专门服务于 Docker Client ,它的功能是接收并调度分发 Docker Client 发送的请求。
2.2、Docker Engine
Engine Docker 架构中的运行引擎,同时也是 Docker 运行的核心模块。 Engine 存储着 大量的容器信息,同时管理着 Docker 大部分 Job 的执行。在Docker 源码中,有关 Engine 的数据结构定义中含有一个名为 handlers 的对象。该 handlers 对象存储的是关于众多特定 Job 各自的处理方式 handler。
2.3、Docker Job
Job 可以认为是 Docker 架构中 Engine 内部最基本的工作执行单元。DockerDaemon 以完成的每一项工作都会呈现为一个Job 。例如,在 Docker 容器内部运行一个进程,这是 一个 Job; 创建一个新的容器,这是一个 Job; 在网络上下载一个文档,这是一个 Job; 包括 之前在 Docker Server 部分谈及的,创建 Server 服务于 HTTP 协议的 API ,这也是一个 Job 等等。
对于 Job 而言,定义完毕之后,运行才能完成 Job 自身真正的使命。 Job 的运行函数 RunO 则用以执行 Job 本身。
3、
在上一篇中,ContainerCreate()
和ContainerStart()
分别向daemon发送了create和start命令。还是从docker engine的main()函数开始:
2.2、源码:newDaemonCommand()
func newDaemonCommand() *cobra.Command {
//获取配置信息
opts := newDaemonOptions(config.New())
//docker daemon命令行对象,与docker client分析的一样
cmd := &cobra.Command{
Use: "dockerd [OPTIONS]",
Short: "A self-sufficient runtime for containers.",
SilenceUsage: true,
SilenceErrors: true,
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
opts.flags = cmd.Flags()
//daemon command执行时,执行该函数
return runDaemon(opts)
},
}
cli.SetupRootCommand(cmd)
//解析命令
flags := cmd.Flags()
//设置docker daemon启动的时候是否使用了version等一些命令
flags.BoolVarP(&opts.version, "version", "v", false, "Print version information and quit")
flags.StringVar(&opts.configFile, "config-file", defaultDaemonConfigFile, "Daemon configuration file")
opts.InstallFlags(flags)
installConfigFlags(opts.daemonConfig, flags)
installServiceFlags(flags)
return cmd
}
func runDaemon(opts *daemonOptions) error {
if opts.version {
showVersion()
return nil
}
//创建daemon客户端对象
daemonCli := NewDaemonCli()
// Windows specific settings as these are not defaulted.
if runtime.GOOS == "windows" {
if opts.daemonConfig.Pidfile == "" {
opts.daemonConfig.Pidfile = filepath.Join(opts.daemonConfig.Root, "docker.pid")
}
if opts.configFile == "" {
opts.configFile = filepath.Join(opts.daemonConfig.Root, `config\daemon.json`)
}
}
// On Windows, this may be launching as a service or with an option to
// register the service.
stop, runAsService, err := initService(daemonCli)
if err != nil {
logrus.Fatal(err)
}
if stop {
return nil
}
// If Windows SCM manages the service - no need for PID files
if runAsService {
opts.daemonConfig.Pidfile = ""
}
//启动daemonCli
err = daemonCli.start(opts)
notifyShutdown(err)
return err
}
// NewDaemonCli returns a daemon CLI
func NewDaemonCli() *DaemonCli {
return &DaemonCli{}
}
// DaemonCli represents the daemon CLI.
type DaemonCli struct {
*config.Config //配置信息
configFile *string //配置文件
flags *pflag.FlagSet //flag参数信息
api *apiserver.Server //APIServer:提供api服务,定位在/engine/api/server/server.go
d *daemon.Daemon //Daemon对象,结构体定义在/engine/daemon/daemon.go
authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins
}