newDaemonCommand
cmd.Flags()
func (c *Command) Flags() *flag.FlagSet {
if c.flags == nil {
c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
if c.flagErrorBuf == nil {
c.flagErrorBuf = new(bytes.Buffer)
}
c.flags.SetOutput(c.flagErrorBuf)
}
return c.flags
}
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{
name: name,
errorHandling: errorHandling,
argsLenAtDash: -1,
interspersed: true,
SortFlags: true,
}
return f
}
type FlagSet struct {}
runDaemon(opts)
func runDaemon(opts *daemonOptions) error {
daemonCli := NewDaemonCli()
return daemonCli.start(opts)
}
func NewDaemonCli() *DaemonCli {
return &DaemonCli{}
}
func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
opts.setDefaultOptions()
if cli.Config, err = loadDaemonCliConfig(opts); err != nil {
return err
}
if err := checkDeprecatedOptions(cli.Config); err != nil {
return err
}
serverConfig, err := newAPIServerConfig(cli.Config)
if err != nil {
return err
}
if opts.Validate {
fmt.Fprintln(os.Stderr, "configuration OK")
return nil
}
configureProxyEnv(cli.Config)
configureDaemonLogs(cli.Config)
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 privileges. To run dockerd in rootless mode as an unprivileged user, see https://docs.docker.com/go/rootless/")
}
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")
}
}
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()
stopc := make(chan bool)
defer close(stopc)
trap.Trap(func() {
cli.stop()
<-stopc
}, logrus.StandardLogger())
preNotifyReady()
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)
notifyReady()
errAPI := <-serveAPIWait
c.Cleanup()
notifyStopping()
shutdownDaemon(d)
cancel()
if errAPI != nil {
return errors.Wrap(errAPI, "shutting down due to ServeAPI error")
}
logrus.Info("Daemon shutdown complete")
return nil
}