上一篇分析了daemon对于start的处理,之前的文章是对整个容器启动过程的简要分析,这篇分析libnetwork的执行流程。
源码阅读基于docker version1.17.05.x。
对libnetwork的工作流做一个梗概。
而上面的这部分工作分别在daemon初始化和docker创建时执行,所以下面分别按这两方面再详细分析。
上一篇介绍了daemon端对container create的处理,这一章将详细介绍daemon端对container start的处理,也就是r.postContainersStart函数
源码阅读基于docker version1.17.05.x。
r.postContainersCreate()的实现位于moby/api/server/router/container/container_routes.go#L133#L172,代码的主要内容是:
func (s *containerRouter) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
//获取hostConfig配置信息
var hostConfig *container.HostConfig
checkpoint := r.Form.Get("checkpoint")
checkpointDir := r.Form.Get("checkpoint-dir")
//调用ContainerStart进一步启动容器,2.详细分析
err := s.backend.ContainerStart(vars["name"], hostConfig, checkpoint, checkpointDir)
}
上一篇介绍了apiserver路由到具体的命令执行函数,这一章将详细介绍daemon端对container create的处理,也就是r.postContainersCreate函数
源码阅读基于docker version1.17.05.x。
r.postContainersCreate()的实现位于moby/api/server/router/container/container_routes.go,代码的主要内容是:
func (s *containerRouter) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
//从http的form表单中获取名字,应该就是"/containers/create"吧?
name := r.Form.Get("name")
//获取从client传过来的Config、hostConfig和networkingConfig配置信息
config, hostConfig, networkingConfig, err := s.decoder.DecodeConfig(r.Body)
if err != nil {
return err
}
//传入配置信息,调用ContainerCreate进一步创建容器
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
Name: name,
Config: config,
HostConfig: hostConfig,
NetworkingConfig: networkingConfig,
AdjustCPUShares: adjustCPUShares,
})
//给client返回结果
return httputils.WriteJSON(w, http.StatusCreated, ccr)
}
上一篇介绍了docker daemon到serverapi的初始化过程,这一篇介绍从serverapi到docker run的调用;
上文分析到initRouter(api, d, c),它初始化了client发来的各种命令的路由,在其中可以追踪到对于create和start命令;
源码阅读基于docker version1.17.05.x。
initRouter的实现位于moby/cmd/dockerd/daemon.go,代码的主要内容是:
func initRouter(s *apiserver.Server, d *daemon.Daemon, c *cluster.Cluster) {
decoder := runconfig.ContainerDecoder{}//获取解码器
routers := []router.Router{
...
//与container的路由,例如/containers/create,/containers/{name:.*}/start
container.NewRouter(d, decoder),
...
}
//如果允许网络控制,则添加network相关的路由
if d.NetworkControllerEnabled() {
routers = append(routers, network.NewRouter(d, c))
}
//如果是experimental模式将所有路由数据项中的experimental模式下的api路由功能激活
if d.HasExperimental() {
for _, r := range routers {
for _, route := range r.Routes() {
if experimental, ok := route.(router.ExperimentalRoute); ok {
experimental.Enable()
}
}
}
}
//根据设置好的路由表routers来初始化apiServer的路由器
s.InitRouter(debug.IsEnabled(), routers...)
}
上文分析了docker client段对于docker run命令的处理,client将create和start命令发送给daemon;
本文主要分析daemon的启动过程,以及对create和start命令的处理;
源码阅读基于docker version1.17.05.x。
docker daemon的main函数位于moby/cmd/dockerd/docker.go,代码的主要内容是:
func main() {
//看有没有注册的初始化函数,如果有,就直接return,这个函数似乎与dockerinit有关
if reexec.Init() {
return
}
//构建一个docker服务器命令行接口对象,命令行接口包含了docker服务器所有可以执行的命令,并通过每一个命令结构体对象中的Run等成员函数来具体执行
cmd := newDaemonCommand()
cmd.Execute()
newDaemonCommand()
调用的地方:1.cmd/dockerd/docker.go的main函数;2.cmd/docker/docker.go的newDockerCommand()
中也有调用,这里的调用是为了启动daemon。
开始阅读docker源码,最终目的是了解docker network的实现;
本文从docker run –net bridge ubuntu 追踪docker network初始化的过程,同时了解docker对网络数据包的处理流程;
源码阅读基于docker version1.17.05.x。
docker client的main函数位于moby/cmd/docker/docker.go,代码的主要内容是:
func main() {
...
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
cmd := newDockerCommand(dockerCli)
if err := cmd.Execute();
...
}
这部分代码的主要工作是:
生成一个带有输入输出的客户端对象
根据dockerCli客户端对象,解析命令行参数,生成带有命令行参数及客户端配置信息的cmd命令行对象
根据输入参数args完成命令执行