if cli.Config.MetricsAddress != "" { // metrics 地址存在的话,起一个metrics server 监听
if !d.HasExperimental() {
return fmt.Errorf("metrics-addr is only supported when experimental is enabled")
}
if err := startMetricsServer(cli.Config.MetricsAddress); err != nil {
return err
}
}
// Restart all autostart containers which has a swarm endpoint
// and is not yet running now that we have successfully
// initialized the cluster.
d.RestartSwarmContainers() // daemon/daemon.go 重启 container ,条件见函数内
......
cli.d = d
// initMiddlewares needs cli.d to be populated. Dont change this init order.
if err := cli.initMiddlewares(api, serverConfig); err != nil { // 给apiserver初始化中间件,要求cli.d必须被赋值
logrus.Fatalf("Error creating middlewares: %v", err)
}
d.SetCluster(c) // d.cluster = c
initRouter(api, d, c) // 注册api消息处理函数,daemon命令的处理可以在这里面查
cli.setupConfigReloadTrap() // 设置一个系统调用重新加载配置
// The serve API routine never exits unless an error occurs
// We need to start it as a goroutine and wait on it so
// daemon doesn't exit
serveAPIWait := make(chan error) // 等待错误的通道
go api.Wait(serveAPIWait) // 起server的协程,出现错误向serveAPIWait通道写入信息
// after the daemon is done setting up we can notify systemd api
notifySystem() // 通知系统daemon 已经起来
// Daemon is fully initialized and handling API traffic
// Wait for serve API to complete
errAPI := <-serveAPIWait // 利用通道阻塞等待 server退出
c.Cleanup() // 关闭cluster
shutdownDaemon(d) // 关闭daemon
containerdRemote.Cleanup() // 关闭 container
......