func BuildContext(driver, root string) (*Context, error) { d, err := graphdriver.GetDriver(driver, root, nil, nil, nil) if err != nil { return nil, err } g, err := graph.NewGraph(filepath.Join(root, "graph"), d, nil, nil) if err != nil { return nil, err } config := &graph.TagStoreConfig{ Graph: g, Events: events.New(), Registry: registry.NewService(®istry.Options{ Mirrors: opts.NewListOpts(nil), InsecureRegistries: *opts.NewListOptsRef(&internalDockerEndpoints, nil), }), } store, err := graph.NewTagStore(filepath.Join(root, "repositories-"+d.String()), config) if err != nil { return nil, err } return NewContext(store, g, d), nil }
func Register(eng *engine.Engine) error { if err := daemon(eng); err != nil { return err } if err := remote(eng); err != nil { return err } if err := eng.Register("version", dockerVersion); err != nil { return err } return registry.NewService().Install(eng) }
func Init(portLayerAddr, product string, config *config.VirtualContainerHostConfigSpec, insecureRegs []url.URL) error { _, _, err := net.SplitHostPort(portLayerAddr) if err != nil { return err } vchConfig = config productName = product if config != nil { if config.Version != nil { productVersion = config.Version.ShortVersion() } if productVersion == "" { portLayerName = product + " Backend Engine" } else { portLayerName = product + " " + productVersion + " Backend Engine" } } else { portLayerName = product + " Backend Engine" } t := httptransport.New(portLayerAddr, "/", []string{"http"}) portLayerClient = client.New(t, nil) portLayerServerAddr = portLayerAddr // block indefinitely while waiting on the portlayer to respond to pings // the vic-machine installer timeout will intervene if this blocks for too long pingPortLayer() if err := hydrateCaches(); err != nil { return err } log.Info("Creating image store") if err := createImageStore(); err != nil { log.Errorf("Failed to create image store") return err } serviceOptions := registry.ServiceOptions{} for _, r := range insecureRegs { insecureRegistries = append(insecureRegistries, r.Path) } if len(insecureRegistries) > 0 { serviceOptions.InsecureRegistries = insecureRegistries } log.Debugf("New registry service with options %#v", serviceOptions) RegistryService = registry.NewService(serviceOptions) return nil }
func NewDocker() (*Docker, error) { registryService := registry.NewService(registryCfg) daemonCfg.TrustKeyPath = getDaemonConfDir() + "/" + defaultTrustKeyFile daemonCfg.Root = utils.HYPER_ROOT d, err := daemon.NewDaemon(daemonCfg, registryService) if err != nil { glog.Errorf("Error starting daemon: %v", err) return nil, err } glog.Info("Daemon has completed initialization") return &Docker{ daemon: d, }, nil }
func InitDockerCfg(mirrors []string, insecureRegistries []string, graphdriver, root string) { if dockerCfg.LogConfig.Config == nil { dockerCfg.LogConfig.Config = make(map[string]string) } dockerCfg.LogConfig.Config = make(map[string]string) var errhandler flag.ErrorHandling = flag.ContinueOnError flags := flag.NewFlagSet("", errhandler) dockerCfg.InstallFlags(flags, presentInHelp) dockerCfg.GraphDriver = graphdriver dockerCfg.Root = root dockerCfg.TrustKeyPath = path.Join(root, "keys") // disable docker network flags.Set("-bridge", "none") flags.Set("-iptables", "false") flags.Set("-ipmasq", "false") // disable log driver dockerCfg.LogConfig.Type = "none" // debug mode if glog.V(3) { dockerutils.EnableDebug() } registryOpts := ®istry.Options{ Mirrors: opts.NewListOpts(nil), InsecureRegistries: opts.NewListOpts(nil), } registryOpts.InstallFlags(flags, absentFromHelp) for _, m := range mirrors { registryOpts.Mirrors.Set(m) } for _, ir := range insecureRegistries { registryOpts.InsecureRegistries.Set(ir) } registryCfg = registry.NewService(registryOpts) }
func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine { if root == "" { if dir, err := newTestDirectory(unitTestStoreBase); err != nil { t.Fatal(err) } else { root = dir } } os.MkdirAll(root, 0700) eng := engine.New() eng.Logging = false // Load default plugins if err := builtins.Register(eng); err != nil { t.Fatal(err) } // load registry service if err := registry.NewService(nil).Install(eng); err != nil { t.Fatal(err) } // (This is manually copied and modified from main() until we have a more generic plugin system) cfg := &daemon.Config{ Root: root, AutoRestart: autorestart, ExecDriver: "native", // Either InterContainerCommunication or EnableIptables must be set, // otherwise NewDaemon will fail because of conflicting settings. InterContainerCommunication: true, TrustKeyPath: filepath.Join(root, "key.json"), LogConfig: runconfig.LogConfig{Type: "json-file"}, } d, err := daemon.NewDaemon(cfg, eng) if err != nil { t.Fatal(err) } if err := d.Install(eng); err != nil { t.Fatal(err) } return eng }
func TestDaemonReloadInsecureRegistries(t *testing.T) { daemon := &Daemon{} // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000" daemon.RegistryService = registry.NewService(registry.ServiceOptions{ InsecureRegistries: []string{ "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000", // this will be removed when reloading "docker1.com", "docker2.com", // this will be removed when reloading }, }) daemon.configStore = &Config{} insecureRegistries := []string{ "127.0.0.0/8", // this will be kept "10.10.1.11:5000", // this will be kept "10.10.1.33:5000", // this will be newly added "docker1.com", // this will be kept "docker3.com", // this will be newly added } valuesSets := make(map[string]interface{}) valuesSets["insecure-registries"] = insecureRegistries newConfig := &Config{ CommonConfig: CommonConfig{ ServiceOptions: registry.ServiceOptions{ InsecureRegistries: insecureRegistries, }, valuesSet: valuesSets, }, } if err := daemon.Reload(newConfig); err != nil { t.Fatal(err) } // After Reload, daemon.RegistryService will be changed which is useful // for registry communication in daemon. registries := daemon.RegistryService.ServiceConfig() // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon. // Then collect registries.InsecureRegistryCIDRs in dataMap. // When collecting, we need to convert CIDRS into string as a key, // while the times of key appears as value. dataMap := map[string]int{} for _, value := range registries.InsecureRegistryCIDRs { if _, ok := dataMap[value.String()]; !ok { dataMap[value.String()] = 1 } else { dataMap[value.String()]++ } } for _, value := range registries.IndexConfigs { if _, ok := dataMap[value.Name]; !ok { dataMap[value.Name] = 1 } else { dataMap[value.Name]++ } } // Finally compare dataMap with the original insecureRegistries. // Each value in insecureRegistries should appear in daemon's insecure registries, // and each can only appear exactly ONCE. for _, r := range insecureRegistries { if value, ok := dataMap[r]; !ok { t.Fatalf("Expected daemon insecure registry %s, got none", r) } else if value != 1 { t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value) } } // assert if "10.10.1.22:5000" is removed when reloading if value, ok := dataMap["10.10.1.22:5000"]; ok { t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value) } // assert if "docker2.com" is removed when reloading if value, ok := dataMap["docker2.com"]; ok { t.Fatalf("Expected no insecure registry of docker2.com, got %d", value) } }
func getData(c *cli.Context, ref reference.Named) (*imageInspect, error) { repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return nil, err } authConfig, err := getAuthConfig(c, repoInfo.Index) if err != nil { return nil, err } if err := validateRepoName(repoInfo.Name()); err != nil { return nil, err } //options := ®istry.Options{} //options.Mirrors = opts.NewListOpts(nil) //options.InsecureRegistries = opts.NewListOpts(nil) //options.InsecureRegistries.Set("0.0.0.0/0") //registryService := registry.NewService(options) registryService := registry.NewService(nil) //// TODO(runcom): hacky, provide a way of passing tls cert (flag?) to be used to lookup //for _, ic := range registryService.Config.IndexConfigs { //ic.Secure = false //} endpoints, err := registryService.LookupPullEndpoints(repoInfo) if err != nil { return nil, err } var ( ctx = context.Background() lastErr error discardNoSupportErrors bool imgInspect *imageInspect confirmedV2 bool ) for _, endpoint := range endpoints { // make sure I can reach the registry, same as docker pull does v1endpoint, err := endpoint.ToV1Endpoint(nil) if err != nil { return nil, err } if _, err := v1endpoint.Ping(); err != nil { if strings.Contains(err.Error(), "timeout") { return nil, err } continue } if confirmedV2 && endpoint.Version == registry.APIVersion1 { logrus.Debugf("Skipping v1 endpoint %s because v2 registry was detected", endpoint.URL) continue } logrus.Debugf("Trying to fetch image manifest of %s repository from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version) //fetcher, err := newManifestFetcher(endpoint, repoInfo, config) fetcher, err := newManifestFetcher(endpoint, repoInfo, authConfig, registryService) if err != nil { lastErr = err continue } if imgInspect, err = fetcher.Fetch(ctx, ref); err != nil { // Was this fetch cancelled? If so, don't try to fall back. fallback := false select { case <-ctx.Done(): default: if fallbackErr, ok := err.(fallbackError); ok { fallback = true confirmedV2 = confirmedV2 || fallbackErr.confirmedV2 err = fallbackErr.err } } if fallback { if _, ok := err.(registry.ErrNoSupport); !ok { // Because we found an error that's not ErrNoSupport, discard all subsequent ErrNoSupport errors. discardNoSupportErrors = true // save the current error lastErr = err } else if !discardNoSupportErrors { // Save the ErrNoSupport error, because it's either the first error or all encountered errors // were also ErrNoSupport errors. lastErr = err } continue } logrus.Debugf("Not continuing with error: %v", err) return nil, err } return imgInspect, nil } if lastErr == nil { lastErr = fmt.Errorf("no endpoints found for %s", ref.String()) } return nil, lastErr }
func mainDaemon() { if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } if flag.NArg() != 0 { flag.Usage() return } logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: timeutils.RFC3339NanoFixed}) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } var pfile *pidfile.PidFile if daemonCfg.Pidfile != "" { pf, err := pidfile.New(daemonCfg.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } serverConfig := &apiserver.ServerConfig{ Logging: true, EnableCors: daemonCfg.EnableCors, CorsHeaders: daemonCfg.CorsHeaders, Version: dockerversion.VERSION, } serverConfig = setPlatformServerConfig(serverConfig, daemonCfg) if *flTls { if *flTlsVerify { tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(tlsOptions) if err != nil { logrus.Fatal(err) } serverConfig.TLSConfig = tlsConfig } api := apiserver.New(serverConfig) // 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 func() { if err := api.ServeApi(flHosts); err != nil { logrus.Errorf("ServeAPI error: %v", err) serveAPIWait <- err return } serveAPIWait <- nil }() if err := migrateKey(); err != nil { logrus.Fatal(err) } daemonCfg.TrustKeyPath = *flTrustKey registryService := registry.NewService(registryCfg) d, err := daemon.NewDaemon(daemonCfg, registryService) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.VERSION, "commit": dockerversion.GITCOMMIT, "execdriver": d.ExecutionDriver().Name(), "graphdriver": d.GraphDriver().String(), }).Info("Docker daemon") signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can tell the api to start // accepting connections with specified daemon api.AcceptConnections(d) // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait shutdownDaemon(d, 15) if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } }
func (cli *DaemonCli) start(opts daemonOptions) (err error) { stopc := make(chan bool) defer close(stopc) // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf opts.common.SetDefaultOptions(opts.flags) if opts.common.TrustKey == "" { opts.common.TrustKey = filepath.Join( getDaemonConfDir(), cliflags.DefaultTrustKeyFile) } if cli.Config, err = loadDaemonCliConfig(opts); err != nil { return err } cli.configFile = &opts.configFile cli.flags = opts.flags if cli.Config.Debug { utils.EnableDebug() } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{ TimestampFormat: jsonlog.RFC3339NanoFixed, DisableColors: cli.Config.RawLogs, }) if err := setDefaultUmask(); err != nil { return fmt.Errorf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { return fmt.Errorf("Failed to set log opts: %v", err) } } if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { return fmt.Errorf("Error starting daemon: %v", err) } defer func() { if err := pf.Remove(); err != nil { logrus.Error(err) } }() } serverConfig := &apiserver.Config{ Logging: true, SocketGroup: cli.Config.SocketGroup, Version: dockerversion.Version, EnableCors: cli.Config.EnableCors, 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, } if cli.Config.TLSVerify { // server requires and verifies client's certificate tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(tlsOptions) if err != nil { return err } serverConfig.TLSConfig = tlsConfig } if len(cli.Config.Hosts) == 0 { cli.Config.Hosts = make([]string, 1) } api := apiserver.New(serverConfig) cli.api = api for i := 0; i < len(cli.Config.Hosts); i++ { var err error if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil { return fmt.Errorf("error parsing -H %s : %v", cli.Config.Hosts[i], err) } protoAddr := cli.Config.Hosts[i] protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { return fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr) } proto := protoAddrParts[0] addr := protoAddrParts[1] // It's a bad idea to bind to TCP without tlsverify. 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 err } ls = wrapListeners(proto, ls) // If we're binding to a TCP port, make sure that a container doesn't try to use it. if proto == "tcp" { if err := allocateDaemonPort(addr); err != nil { return err } } logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr) api.Accept(addr, ls...) } if err := migrateKey(); err != nil { return err } // FIXME: why is this down here instead of with the other TrustKey logic above? cli.TrustKeyPath = opts.common.TrustKey registryService := registry.NewService(cli.Config.ServiceOptions) containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...) if err != nil { return err } signal.Trap(func() { cli.stop() <-stopc // wait for daemonCli.start() to return }) d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote) if err != nil { return fmt.Errorf("Error starting daemon: %v", err) } name, _ := os.Hostname() c, err := cluster.New(cluster.Config{ Root: cli.Config.Root, Name: name, Backend: d, NetworkSubnetsProvider: d, DefaultAdvertiseAddr: cli.Config.SwarmDefaultAdvertiseAddr, RuntimeRoot: cli.getSwarmRunRoot(), }) if err != nil { logrus.Fatalf("Error creating cluster component: %v", 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() logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.Version, "commit": dockerversion.GitCommit, "graphdriver": d.GraphDriverName(), }).Info("Docker daemon") cli.d = d // initMiddlewares needs cli.d to be populated. Dont change this init order. cli.initMiddlewares(api, serverConfig) initRouter(api, d, c) 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) // after the daemon is done setting up we can notify systemd api notifySystem() // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait c.Cleanup() shutdownDaemon(d) containerdRemote.Cleanup() if errAPI != nil { return fmt.Errorf("Shutting down due to ServeAPI error: %v", errAPI) } return nil }
// CmdDaemon is the daemon command, called the raw arguments after `docker daemon`. func (cli *DaemonCli) CmdDaemon(args ...string) error { // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() { // deny `docker -D daemon` illegalFlag := getGlobalFlag() fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0]) os.Exit(1) } else { // allow new form `docker daemon -D` flag.Merge(cli.flags, commonFlags.FlagSet) } configFile := cli.flags.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file") cli.flags.ParseFlags(args, true) commonFlags.PostParse() if commonFlags.TrustKey == "" { commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), defaultTrustKeyFile) } cliConfig, err := loadDaemonCliConfig(cli.Config, cli.flags, commonFlags, *configFile) if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } cli.Config = cliConfig if cli.Config.Debug { utils.EnableDebug() } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{ TimestampFormat: jsonlog.RFC3339NanoFixed, DisableColors: cli.Config.RawLogs, }) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { logrus.Fatalf("Failed to set log opts: %v", err) } } var pfile *pidfile.PIDFile if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } serverConfig := &apiserver.Config{ AuthorizationPluginNames: cli.Config.AuthorizationPlugins, Logging: true, SocketGroup: cli.Config.SocketGroup, Version: dockerversion.Version, } serverConfig = setPlatformServerConfig(serverConfig, cli.Config) if cli.Config.TLS { tlsOptions := tlsconfig.Options{ CAFile: cli.Config.CommonTLSOptions.CAFile, CertFile: cli.Config.CommonTLSOptions.CertFile, KeyFile: cli.Config.CommonTLSOptions.KeyFile, } if cli.Config.TLSVerify { // server requires and verifies client's certificate tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(tlsOptions) if err != nil { logrus.Fatal(err) } serverConfig.TLSConfig = tlsConfig } if len(cli.Config.Hosts) == 0 { cli.Config.Hosts = make([]string, 1) } api := apiserver.New(serverConfig) for i := 0; i < len(cli.Config.Hosts); i++ { var err error if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil { logrus.Fatalf("error parsing -H %s : %v", cli.Config.Hosts[i], err) } protoAddr := cli.Config.Hosts[i] protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr) } l, err := listeners.Init(protoAddrParts[0], protoAddrParts[1], serverConfig.SocketGroup, serverConfig.TLSConfig) if err != nil { logrus.Fatal(err) } logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1]) api.Accept(protoAddrParts[1], l...) } if err := migrateKey(); err != nil { logrus.Fatal(err) } cli.TrustKeyPath = commonFlags.TrustKey registryService := registry.NewService(cli.Config.ServiceOptions) d, err := daemon.NewDaemon(cli.Config, registryService) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.Version, "commit": dockerversion.GitCommit, "execdriver": d.ExecutionDriver().Name(), "graphdriver": d.GraphDriverName(), }).Info("Docker daemon") initRouter(api, d) reload := func(config *daemon.Config) { if err := d.Reload(config); err != nil { logrus.Errorf("Error reconfiguring the daemon: %v", err) return } if config.IsValueSet("debug") { debugEnabled := utils.IsDebugEnabled() switch { case debugEnabled && !config.Debug: // disable debug utils.DisableDebug() api.DisableProfiler() case config.Debug && !debugEnabled: // enable debug utils.EnableDebug() api.EnableProfiler() } } } setupConfigReloadTrap(*configFile, cli.flags, reload) // 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) signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can notify systemd api notifySystem() // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait shutdownDaemon(d, 15) if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } return nil }
// CmdDaemon is the daemon command, called the raw arguments after `docker daemon`. func (cli *DaemonCli) CmdDaemon(args ...string) error { // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf //调整一下daemon的启动方式 if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() { // deny `docker -D daemon` illegalFlag := getGlobalFlag() fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0]) os.Exit(1) } else { // allow new form `docker daemon -D` flag.Merge(cli.flags, commonFlags.FlagSet) } configFile := cli.flags.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file") //匹配配置参数 cli.flags.ParseFlags(args, true) //配置参数生效 commonFlags.PostParse() if commonFlags.TrustKey == "" { commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), defaultTrustKeyFile) } cliConfig, err := loadDaemonCliConfig(cli.Config, cli.flags, commonFlags, *configFile) if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } cli.Config = cliConfig if cli.Config.Debug { utils.EnableDebug() } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{ TimestampFormat: jsonlog.RFC3339NanoFixed, DisableColors: cli.Config.RawLogs, }) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { logrus.Fatalf("Failed to set log opts: %v", err) } } var pfile *pidfile.PIDFile if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } //定义apiserver的配置,包括认证、日志输出、版本等。 serverConfig := &apiserver.Config{ AuthorizationPluginNames: cli.Config.AuthorizationPlugins, Logging: true, SocketGroup: cli.Config.SocketGroup, Version: dockerversion.Version, } serverConfig = setPlatformServerConfig(serverConfig, cli.Config) if cli.Config.TLS { tlsOptions := tlsconfig.Options{ CAFile: cli.Config.CommonTLSOptions.CAFile, CertFile: cli.Config.CommonTLSOptions.CertFile, KeyFile: cli.Config.CommonTLSOptions.KeyFile, } if cli.Config.TLSVerify { // server requires and verifies client's certificate tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(tlsOptions) if err != nil { logrus.Fatal(err) } serverConfig.TLSConfig = tlsConfig } if len(cli.Config.Hosts) == 0 { cli.Config.Hosts = make([]string, 1) } //定义一个新的apiserver。 //apiServer是一个这样的结构(api/server/server.go): /* type Server struct { cfg *Config servers []*HTTPServer routers []router.Router authZPlugins []authorization.Plugin routerSwapper *routerSwapper } */ api := apiserver.New(serverConfig) for i := 0; i < len(cli.Config.Hosts); i++ { var err error if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil { logrus.Fatalf("error parsin g -H %s : %v", cli.Config.Hosts[i], err) } protoAddr := cli.Config.Hosts[i] protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr) } l, err := listeners.Init(protoAddrParts[0], protoAddrParts[1], serverConfig.SocketGroup, serverConfig.TLSConfig) if err != nil { logrus.Fatal(err) } logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1]) //初始化api的servers数组,里面放着的都是httpserver类型。此时也没有具体的运行什么 api.Accept(protoAddrParts[1], l...) } if err := migrateKey(); err != nil { logrus.Fatal(err) } cli.TrustKeyPath = commonFlags.TrustKey //创建镜像仓库服务 registryService := registry.NewService(cli.Config.ServiceOptions) //初始化libcontainer。比如在linux中,就会调用libcontainerd/remote_linux.go中的New方法。 containerdRemote, err := libcontainerd.New(filepath.Join(cli.Config.ExecRoot, "libcontainerd"), cli.getPlatformRemoteOptions()...) if err != nil { logrus.Fatal(err) } //初始化守护进程使得能够服务。需要输入仓库服务和libcontainerd服务的参数。 //返回的d是Daemon类型: /* type Daemon struct { ID string repository string containers container.Store execCommands *exec.Store referenceStore reference.Store downloadManager *xfer.LayerDownloadManager uploadManager *xfer.LayerUploadManager distributionMetadataStore dmetadata.Store trustKey libtrust.PrivateKey idIndex *truncindex.TruncIndex configStore *Config statsCollector *statsCollector defaultLogConfig containertypes.LogConfig RegistryService *registry.Service EventsService *events.Events netController libnetwork.NetworkController volumes *store.VolumeStore discoveryWatcher discoveryReloader root string seccompEnabled bool shutdown bool uidMaps []idtools.IDMap gidMaps []idtools.IDMap layerStore layer.Store imageStore image.Store nameIndex *registrar.Registrar linkIndex *linkIndex containerd libcontainerd.Client defaultIsolation containertypes.Isolation // Default isolation mode on Windows } */ d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.Version, "commit": dockerversion.GitCommit, "graphdriver": d.GraphDriverName(), }).Info("Docker daemon") //初始化http的路由,这个路由设计的非常易懂,所有的路由及处理函数的映射关系 //请见api/server/router/文件夹中的内容。有类似这样的内容: //router.NewPostRoute("/containers/create", r.postContainersCreate), //其中,对应的处理函数postContainersCreate在api/server/router/container/container_routes.go //但是,实际上这个函数也不做具体的事情,他交给backend去做,就是daemon去做 /* ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{ Name: name, Config: config, HostConfig: hostConfig, NetworkingConfig: networkingConfig, AdjustCPUShares: adjustCPUShares, }) */ //其中的ContainerCreate在 initRouter(api, d) reload := func(config *daemon.Config) { if err := d.Reload(config); err != nil { logrus.Errorf("Error reconfiguring the daemon: %v", err) return } if config.IsValueSet("debug") { debugEnabled := utils.IsDebugEnabled() switch { case debugEnabled && !config.Debug: // disable debug utils.DisableDebug() api.DisableProfiler() case config.Debug && !debugEnabled: // enable debug utils.EnableDebug() api.EnableProfiler() } } } setupConfigReloadTrap(*configFile, cli.flags, reload) // 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 //设置一个传输apiServer状态的通道 serveAPIWait := make(chan error) //重新开启一个goroutine作为httpServer。 //具体的请查看api/server/server.go中的方法func (s *Server) serveAPI() error go api.Wait(serveAPIWait) signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can notify systemd api notifySystem() // Daemon is fully initialized and handling API traffic // Wait for serve API to complete //<-表示接受通道值,只有当通道中有值的时候,才会返回。 //也就是说主线程一直在等待api.wait的goroutine启动apiServer之后的返回才会进行。 errAPI := <-serveAPIWait //当接收到返回(返回就是错误了),开始清理进程。 shutdownDaemon(d, 15) containerdRemote.Cleanup() if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } return nil }
// CmdDaemon is the daemon command, called the raw arguments after `docker daemon`. func (cli *DaemonCli) CmdDaemon(args ...string) error { // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() { // deny `docker -D daemon` illegalFlag := getGlobalFlag() fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0]) os.Exit(1) } else { // allow new form `docker daemon -D` flag.Merge(daemonFlags, commonFlags.FlagSet) } daemonFlags.ParseFlags(args, true) commonFlags.PostParse() if commonFlags.TrustKey == "" { commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), defaultTrustKeyFile) } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: jsonlog.RFC3339NanoFixed}) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { logrus.Fatalf("Failed to set log opts: %v", err) } } var pfile *pidfile.PIDFile if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } serverConfig := &apiserver.Config{ AuthZPluginNames: cli.Config.AuthZPlugins, Logging: true, Version: dockerversion.Version, } serverConfig = setPlatformServerConfig(serverConfig, cli.Config) defaultHost := opts.DefaultHost if commonFlags.TLSOptions != nil { if !commonFlags.TLSOptions.InsecureSkipVerify { // server requires and verifies client's certificate commonFlags.TLSOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(*commonFlags.TLSOptions) if err != nil { logrus.Fatal(err) } serverConfig.TLSConfig = tlsConfig defaultHost = opts.DefaultTLSHost } if len(commonFlags.Hosts) == 0 { commonFlags.Hosts = make([]string, 1) } for i := 0; i < len(commonFlags.Hosts); i++ { var err error if commonFlags.Hosts[i], err = opts.ParseHost(defaultHost, commonFlags.Hosts[i]); err != nil { logrus.Fatalf("error parsing -H %s : %v", commonFlags.Hosts[i], err) } } for _, protoAddr := range commonFlags.Hosts { protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr) } serverConfig.Addrs = append(serverConfig.Addrs, apiserver.Addr{Proto: protoAddrParts[0], Addr: protoAddrParts[1]}) } api, err := apiserver.New(serverConfig) if err != nil { logrus.Fatal(err) } if err := migrateKey(); err != nil { logrus.Fatal(err) } cli.TrustKeyPath = commonFlags.TrustKey registryService := registry.NewService(cli.registryOptions) d, err := daemon.NewDaemon(cli.Config, registryService) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.Version, "commit": dockerversion.GitCommit, "execdriver": d.ExecutionDriver().Name(), "graphdriver": d.GraphDriverName(), }).Info("Docker daemon") api.InitRouters(d) // 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 func() { if err := api.ServeAPI(); err != nil { logrus.Errorf("ServeAPI error: %v", err) serveAPIWait <- err return } serveAPIWait <- nil }() signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can notify systemd api notifySystem() // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait shutdownDaemon(d, 15) if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } return nil }
// CmdDaemon is the daemon command, called the raw arguments after `docker daemon`. func (cli *DaemonCli) CmdDaemon(args ...string) error { if *flDaemon { // allow legacy forms `docker -D -d` and `docker -d -D` logrus.Warn("please use 'docker daemon' instead.") } else if !commonFlags.FlagSet.IsEmpty() || !clientFlags.FlagSet.IsEmpty() { // deny `docker -D daemon` illegalFlag := getGlobalFlag() fmt.Fprintf(os.Stderr, "invalid flag '-%s'.\nSee 'docker daemon --help'.\n", illegalFlag.Names[0]) os.Exit(1) } else { // allow new form `docker daemon -D` flag.Merge(daemonFlags, commonFlags.FlagSet) } daemonFlags.ParseFlags(args, true) commonFlags.PostParse() if len(commonFlags.Hosts) == 0 { commonFlags.Hosts = []string{opts.DefaultHost} } if commonFlags.TrustKey == "" { commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), defaultTrustKeyFile) } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: timeutils.RFC3339NanoFixed}) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { logrus.Fatalf("Failed to set log opts: %v", err) } } var pfile *pidfile.PIDFile if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } if cli.LogConfig.Config == nil { cli.LogConfig.Config = make(map[string]string) } serverConfig := &apiserver.ServerConfig{ Logging: true, EnableCors: cli.EnableCors, CorsHeaders: cli.CorsHeaders, Version: dockerversion.VERSION, } serverConfig = setPlatformServerConfig(serverConfig, cli.Config) if commonFlags.TLSOptions != nil { if !commonFlags.TLSOptions.InsecureSkipVerify { // server requires and verifies client's certificate commonFlags.TLSOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(*commonFlags.TLSOptions) if err != nil { logrus.Fatalf("foobar: %v", err) } serverConfig.TLSConfig = tlsConfig } api := apiserver.New(serverConfig) // 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 func() { if err := api.ServeApi(commonFlags.Hosts); err != nil { logrus.Errorf("ServeAPI error: %v", err) serveAPIWait <- err return } serveAPIWait <- nil }() if err := migrateKey(); err != nil { logrus.Fatal(err) } cli.TrustKeyPath = commonFlags.TrustKey registryService := registry.NewService(cli.registryOptions) d, err := daemon.NewDaemon(cli.Config, registryService) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.VERSION, "commit": dockerversion.GITCOMMIT, "execdriver": d.ExecutionDriver().Name(), "graphdriver": d.GraphDriver().String(), }).Info("Docker daemon") signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can tell the api to start // accepting connections with specified daemon api.AcceptConnections(d) // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait shutdownDaemon(d, 15) if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } return nil }
func mainDaemon() { if flag.NArg() != 0 { flag.Usage() return } eng := engine.New() signal.Trap(eng.Shutdown) if err := migrateKey(); err != nil { logrus.Fatal(err) } daemonCfg.TrustKeyPath = *flTrustKey // Load builtins if err := builtins.Register(eng); err != nil { logrus.Fatal(err) } // load registry service if err := registry.NewService(registryCfg).Install(eng); err != nil { logrus.Fatal(err) } // load the daemon in the background so we can immediately start // the http api so that connections don't fail while the daemon // is booting daemonInitWait := make(chan error) go func() { d, err := daemon.NewDaemon(daemonCfg, eng) if err != nil { daemonInitWait <- err return } logrus.Infof("docker daemon: %s %s; execdriver: %s; graphdriver: %s", dockerversion.VERSION, dockerversion.GITCOMMIT, d.ExecutionDriver().Name(), d.GraphDriver().String(), ) if err := d.Install(eng); err != nil { daemonInitWait <- err return } b := &builder.BuilderJob{eng, d} b.Install() // after the daemon is done setting up we can tell the api to start // accepting connections if err := eng.Job("acceptconnections").Run(); err != nil { daemonInitWait <- err return } daemonInitWait <- nil }() // Serve api job := eng.Job("serveapi", flHosts...) job.SetenvBool("Logging", true) job.SetenvBool("EnableCors", daemonCfg.EnableCors) job.Setenv("CorsHeaders", daemonCfg.CorsHeaders) job.Setenv("Version", dockerversion.VERSION) job.Setenv("SocketGroup", daemonCfg.SocketGroup) job.SetenvBool("Tls", *flTls) job.SetenvBool("TlsVerify", *flTlsVerify) job.Setenv("TlsCa", *flCa) job.Setenv("TlsCert", *flCert) job.Setenv("TlsKey", *flKey) job.SetenvBool("BufferRequests", true) // The serve API job 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 func() { if err := job.Run(); err != nil { logrus.Errorf("ServeAPI error: %v", err) serveAPIWait <- err return } serveAPIWait <- nil }() // Wait for the daemon startup goroutine to finish // This makes sure we can actually cleanly shutdown the daemon logrus.Debug("waiting for daemon to initialize") errDaemon := <-daemonInitWait if errDaemon != nil { eng.Shutdown() outStr := fmt.Sprintf("Shutting down daemon due to errors: %v", errDaemon) if strings.Contains(errDaemon.Error(), "engine is shutdown") { // if the error is "engine is shutdown", we've already reported (or // will report below in API server errors) the error outStr = "Shutting down daemon due to reported errors" } // we must "fatal" exit here as the API server may be happy to // continue listening forever if the error had no impact to API logrus.Fatal(outStr) } else { logrus.Info("Daemon has completed initialization") } // Daemon is fully initialized and handling API traffic // Wait for serve API job to complete errAPI := <-serveAPIWait // If we have an error here it is unique to API (as daemonErr would have // exited the daemon process above) eng.Shutdown() if errAPI != nil { logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } }
func (cli *DaemonCli) start() { // warn from uuid package when running the daemon uuid.Loggerf = logrus.Warnf flags := flag.CommandLine cli.commonFlags.PostParse() if cli.commonFlags.TrustKey == "" { cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile) } cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile) if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } cli.Config = cliConfig if cli.Config.Debug { utils.EnableDebug() } if utils.ExperimentalBuild() { logrus.Warn("Running experimental build") } logrus.SetFormatter(&logrus.TextFormatter{ TimestampFormat: jsonlog.RFC3339NanoFixed, DisableColors: cli.Config.RawLogs, }) if err := setDefaultUmask(); err != nil { logrus.Fatalf("Failed to set umask: %v", err) } if len(cli.LogConfig.Config) > 0 { if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil { logrus.Fatalf("Failed to set log opts: %v", err) } } var pfile *pidfile.PIDFile if cli.Pidfile != "" { pf, err := pidfile.New(cli.Pidfile) if err != nil { logrus.Fatalf("Error starting daemon: %v", err) } pfile = pf defer func() { if err := pfile.Remove(); err != nil { logrus.Error(err) } }() } serverConfig := &apiserver.Config{ Logging: true, SocketGroup: cli.Config.SocketGroup, Version: dockerversion.Version, } serverConfig = setPlatformServerConfig(serverConfig, cli.Config) if cli.Config.TLS { tlsOptions := tlsconfig.Options{ CAFile: cli.Config.CommonTLSOptions.CAFile, CertFile: cli.Config.CommonTLSOptions.CertFile, KeyFile: cli.Config.CommonTLSOptions.KeyFile, } if cli.Config.TLSVerify { // server requires and verifies client's certificate tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert } tlsConfig, err := tlsconfig.Server(tlsOptions) if err != nil { logrus.Fatal(err) } serverConfig.TLSConfig = tlsConfig } if len(cli.Config.Hosts) == 0 { cli.Config.Hosts = make([]string, 1) } api := apiserver.New(serverConfig) for i := 0; i < len(cli.Config.Hosts); i++ { var err error if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil { logrus.Fatalf("error parsing -H %s : %v", cli.Config.Hosts[i], err) } protoAddr := cli.Config.Hosts[i] protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr) } proto := protoAddrParts[0] addr := protoAddrParts[1] // It's a bad idea to bind to TCP without tlsverify. 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 [!]") } l, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig) if err != nil { logrus.Fatal(err) } // If we're binding to a TCP port, make sure that a container doesn't try to use it. if proto == "tcp" { if err := allocateDaemonPort(addr); err != nil { logrus.Fatal(err) } } logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1]) api.Accept(protoAddrParts[1], l...) } if err := migrateKey(); err != nil { logrus.Fatal(err) } cli.TrustKeyPath = cli.commonFlags.TrustKey registryService := registry.NewService(cli.Config.ServiceOptions) containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...) if err != nil { logrus.Fatal(err) } d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote) if err != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Error starting daemon: %v", err) } logrus.Info("Daemon has completed initialization") logrus.WithFields(logrus.Fields{ "version": dockerversion.Version, "commit": dockerversion.GitCommit, "graphdriver": d.GraphDriverName(), }).Info("Docker daemon") cli.initMiddlewares(api, serverConfig) initRouter(api, d) reload := func(config *daemon.Config) { if err := d.Reload(config); err != nil { logrus.Errorf("Error reconfiguring the daemon: %v", err) return } if config.IsValueSet("debug") { debugEnabled := utils.IsDebugEnabled() switch { case debugEnabled && !config.Debug: // disable debug utils.DisableDebug() api.DisableProfiler() case config.Debug && !debugEnabled: // enable debug utils.EnableDebug() api.EnableProfiler() } } } setupConfigReloadTrap(*cli.configFile, flags, reload) // 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) signal.Trap(func() { api.Close() <-serveAPIWait shutdownDaemon(d, 15) if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } }) // after the daemon is done setting up we can notify systemd api notifySystem() // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait shutdownDaemon(d, 15) containerdRemote.Cleanup() if errAPI != nil { if pfile != nil { if err := pfile.Remove(); err != nil { logrus.Error(err) } } logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI) } }
func TestDaemonReloadMirrors(t *testing.T) { daemon := &Daemon{} daemon.RegistryService = registry.NewService(registry.ServiceOptions{ InsecureRegistries: []string{}, Mirrors: []string{ "https://mirror.test1.com", "https://mirror.test2.com", // this will be removed when reloading "https://mirror.test3.com", // this will be removed when reloading }, }) daemon.configStore = &Config{} type pair struct { valid bool mirrors []string after []string } loadMirrors := []pair{ { valid: false, mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid after: []string{}, }, { valid: false, mirrors: []string{"mirror.test1.com"}, // this mirror is invalid after: []string{}, }, { valid: false, mirrors: []string{"10.10.1.11:5000", "mirror.test1.com"}, // mirrors are invalid after: []string{}, }, { valid: true, mirrors: []string{"https://mirror.test1.com", "https://mirror.test4.com"}, after: []string{"https://mirror.test1.com/", "https://mirror.test4.com/"}, }, } for _, value := range loadMirrors { valuesSets := make(map[string]interface{}) valuesSets["registry-mirrors"] = value.mirrors newConfig := &Config{ CommonConfig: CommonConfig{ ServiceOptions: registry.ServiceOptions{ Mirrors: value.mirrors, }, valuesSet: valuesSets, }, } err := daemon.Reload(newConfig) if !value.valid && err == nil { // mirrors should be invalid, should be a non-nil error t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors) } if value.valid { if err != nil { // mirrors should be valid, should be no error t.Fatal(err) } registryService := daemon.RegistryService.ServiceConfig() if len(registryService.Mirrors) != len(value.after) { t.Fatalf("Expected %d daemon mirrors %s while get %d with %s", len(value.after), value.after, len(registryService.Mirrors), registryService.Mirrors) } dataMap := map[string]struct{}{} for _, mirror := range registryService.Mirrors { if _, exist := dataMap[mirror]; !exist { dataMap[mirror] = struct{}{} } } for _, address := range value.after { if _, exist := dataMap[address]; !exist { t.Fatalf("Expected %s in daemon mirrors, while get none", address) } } } } }
func newRegistryService() registry.Service { return pluginRegistryService{ Service: registry.NewService(registry.ServiceOptions{V2Only: true}), } }
func mainDaemon() { if flag.NArg() != 0 { flag.Usage() return } eng := engine.New() signal.Trap(eng.Shutdown) daemonCfg.TrustKeyPath = *flTrustKey // Load builtins if err := builtins.Register(eng); err != nil { log.Fatal(err) } // load registry service if err := registry.NewService(registryCfg).Install(eng); err != nil { log.Fatal(err) } // load the daemon in the background so we can immediately start // the http api so that connections don't fail while the daemon // is booting go func() { d, err := daemon.NewDaemon(daemonCfg, eng) if err != nil { log.Fatal(err) } log.Infof("docker daemon: %s %s; execdriver: %s; graphdriver: %s", dockerversion.VERSION, dockerversion.GITCOMMIT, d.ExecutionDriver().Name(), d.GraphDriver().String(), ) if err := d.Install(eng); err != nil { log.Fatal(err) } b := &builder.BuilderJob{eng, d} b.Install() // after the daemon is done setting up we can tell the api to start // accepting connections if err := eng.Job("acceptconnections").Run(); err != nil { log.Fatal(err) } }() // Serve api job := eng.Job("serveapi", flHosts...) job.SetenvBool("Logging", true) job.SetenvBool("EnableCors", *flEnableCors) job.Setenv("Version", dockerversion.VERSION) job.Setenv("SocketGroup", *flSocketGroup) job.SetenvBool("Tls", *flTls) job.SetenvBool("TlsVerify", *flTlsVerify) job.Setenv("TlsCa", *flCa) job.Setenv("TlsCert", *flCert) job.Setenv("TlsKey", *flKey) job.SetenvBool("BufferRequests", true) if err := job.Run(); err != nil { log.Fatal(err) } }
func initRegistry() *registry.Service { return registry.NewService(nil) }