docker源码分析(1)(持续更新)
- daemon
- docker DaemonClient的启动
- 内部函数分析
- newAPIServerConfig
- loadListeners
- initContainerD
daemon
docker DaemonClient的启动
代码位于cmd\dockerd\daemon.go
func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
stopc := make(chan bool)
defer close(stopc)
opts.SetDefaultOptions(opts.flags)
if cli.Config, err = loadDaemonCliConfig(opts); err != nil {
return err
}
warnOnDeprecatedConfigOptions(cli.Config)
if err := configureDaemonLogs(cli.Config); err != nil {
return err
}
logrus.Info("Starting up")
cli.configFile = &opts.configFile
cli.flags = opts.flags
if cli.Config.Debug {
debug.Enable()
}
if cli.Config.Experimental {
logrus.Warn("Running experimental build")
}
if cli.Config.IsRootless() {
logrus.Warn("Running in rootless mode. This mode has feature limitations.")
}
if rootless.RunningWithRootlessKit() {
logrus.Info("Running with RootlessKit integration")
if !cli.Config.IsRootless() {
return fmt.Errorf("rootless mode needs to be enabled for running with RootlessKit")
}
}
if runtime.GOOS == "linux" && os.Geteuid() != 0 {
return fmt.Errorf("dockerd needs to be started with root. To see how to run dockerd in rootless mode with unprivileged user, see the documentation")
}
system.InitLCOW(cli.Config.Experimental)
if err := setDefaultUmask(); err != nil {
return err
}
if err := daemon.CreateDaemonRoot(cli.Config); err != nil {
return err
}
if err := system.MkdirAll(cli.Config.ExecRoot, 0700); err != nil {
return err
}
potentiallyUnderRuntimeDir := []string{cli.Config.ExecRoot}
if cli.Pidfile != "" {
pf, err := pidfile.New(cli.Pidfile)
if err != nil {
return errors.Wrap(err, "failed to start daemon")
}
potentiallyUnderRuntimeDir = append(potentiallyUnderRuntimeDir, cli.Pidfile)
defer func() {
if err := pf.Remove(); err != nil {
logrus.Error(err)
}
}()
}
if cli.Config.IsRootless() {
if _, err := homedir.StickRuntimeDirContents(potentiallyUnderRuntimeDir); err != nil {
logrus.WithError(err).Warn("cannot set sticky bit on files under XDG_RUNTIME_DIR")
}
}
serverConfig, err := newAPIServerConfig(cli)
if err != nil {
return errors.Wrap(err, "failed to create API server")
}
cli.api = apiserver.New(serverConfig)
hosts, err := loadListeners(cli, serverConfig)
if err != nil {
return errors.Wrap(err, "failed to load listeners")
}
ctx, cancel := context.WithCancel(context.Background())
waitForContainerDShutdown, err := cli.initContainerD(ctx)
if waitForContainerDShutdown != nil {
defer waitForContainerDShutdown(10 * time.Second)
}
if err != nil {
cancel()
return err
}
defer cancel()
signal.Trap(func() {
cli.stop()
<-stopc
}, logrus.StandardLogger())
preNotifySystem()
pluginStore := plugin.NewStore()
if err := cli.initMiddlewares(cli.api, serverConfig, pluginStore); err != nil {
logrus.Fatalf("Error creating middlewares: %v", err)
}
d, err := daemon.NewDaemon(ctx, cli.Config, pluginStore)
if err != nil {
return errors.Wrap(err, "failed to start daemon")
}
d.StoreHosts(hosts)
if err := validateAuthzPlugins(cli.Config.AuthorizationPlugins, pluginStore); err != nil {
return errors.Wrap(err, "failed to validate authorization plugin")
}
cli.d = d
if err := startMetricsServer(cli.Config.MetricsAddress); err != nil {
return errors.Wrap(err, "failed to start metrics server")
}
c, err := createAndStartCluster(cli, d)
if err != nil {
logrus.Fatalf("Error starting cluster component: %v", err)
}
d.RestartSwarmContainers()
logrus.Info("Daemon has completed initialization")
routerOptions, err := newRouterOptions(cli.Config, d)
if err != nil {
return err
}
routerOptions.api = cli.api
routerOptions.cluster = c
initRouter(routerOptions)
go d.ProcessClusterNotifications(ctx, c.GetWatchStream())
cli.setupConfigReloadTrap()
serveAPIWait := make(chan error)
go cli.api.Wait(serveAPIWait)
notifySystem()
errAPI := <-serveAPIWait
c.Cleanup()
shutdownDaemon(d)
cancel()
if errAPI != nil {
return errors.Wrap(errAPI, "shutting down due to ServeAPI error")
}
logrus.Info("Daemon shutdown complete")
return nil
}
内部函数分析
newAPIServerConfig
func newAPIServerConfig(cli *DaemonCli) (*apiserver.Config, error) {
serverConfig := &apiserver.Config{
Logging: true,
SocketGroup: cli.Config.SocketGroup,
Version: dockerversion.Version,
CorsHeaders: cli.Config.CorsHeaders,
}
if cli.Config.TLS {
tlsOptions := tlsconfig.Options{
CAFile: cli.Config.CommonTLSOptions.CAFile,
CertFile: cli.Config.CommonTLSOptions.CertFile,
KeyFile: cli.Config.CommonTLSOptions.KeyFile,
ExclusiveRootPools: true,
}
if cli.Config.TLSVerify {
tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
}
tlsConfig, err := tlsconfig.Server(tlsOptions)
if err != nil {
return nil, err
}
serverConfig.TLSConfig = tlsConfig
}
if len(cli.Config.Hosts) == 0 {
cli.Config.Hosts = make([]string, 1)
}
return serverConfig, nil
}
loadListeners
func loadListeners(cli *DaemonCli, serverConfig *apiserver.Config) ([]string, error) {
var hosts []string
seen := make(map[string]struct{}, len(cli.Config.Hosts))
for i := 0; i < len(cli.Config.Hosts); i++ {
var err error
if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, honorXDG, cli.Config.Hosts[i]); err != nil {
return nil, errors.Wrapf(err, "error parsing -H %s", cli.Config.Hosts[i])
}
if _, ok := seen[cli.Config.Hosts[i]]; ok {
continue
}
seen[cli.Config.Hosts[i]] = struct{}{}
protoAddr := cli.Config.Hosts[i]
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
if len(protoAddrParts) != 2 {
return nil, fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
}
proto := protoAddrParts[0]
addr := protoAddrParts[1]
if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting --tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
}
ls, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
if err != nil {
return nil, err
}
if proto == "tcp" {
if err := allocateDaemonPort(addr); err != nil {
return nil, err
}
}
logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr)
hosts = append(hosts, protoAddrParts[1])
cli.api.Accept(addr, ls...)
}
return hosts, nil
}
initContainerD
unc (cli *DaemonCli) initContainerD(ctx context.Context) (func(time.Duration) error, error) {
var waitForShutdown func(time.Duration) error
if cli.Config.ContainerdAddr == "" {
systemContainerdAddr, ok, err := systemContainerdRunning(honorXDG)
if err != nil {
return nil, errors.Wrap(err, "could not determine whether the system containerd is running")
}
if !ok {
logrus.Debug("Containerd not running, starting daemon managed containerd")
opts, err := cli.getContainerdDaemonOpts()
if err != nil {
return nil, errors.Wrap(err, "failed to generate containerd options")
}
r, err := supervisor.Start(ctx, filepath.Join(cli.Config.Root, "containerd"), filepath.Join(cli.Config.ExecRoot, "containerd"), opts...)
if err != nil {
return nil, errors.Wrap(err, "failed to start containerd")
}
logrus.Debug("Started daemon managed containerd")
cli.Config.ContainerdAddr = r.Address()
waitForShutdown = r.WaitTimeout
} else {
cli.Config.ContainerdAddr = systemContainerdAddr
}
}
return waitForShutdown, nil
}
觉得有帮助的可以支持下!谢谢!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)