func setupTcpHttp(addr string, job *engine.Job) (*HttpServer, error) { r, err := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version")) if err != nil { return nil, err } l, err := newListener("tcp", addr, job.GetenvBool("BufferRequests")) if err != nil { return nil, err } var tlsConfig *tls.Config switch job.Getenv("Auth") { case "identity": trustKey, err := api.LoadOrCreateTrustKey(job.Getenv("TrustKey")) if err != nil { return nil, err } manager, err := NewClientKeyManager(trustKey, job.Getenv("TrustClients"), job.Getenv("TrustDir")) if err != nil { return nil, err } if tlsConfig, err = NewIdentityAuthTLSConfig(trustKey, manager, addr); err != nil { return nil, fmt.Errorf("Error creating TLS config: %s", err) } case "cert": if tlsConfig, err = NewCertAuthTLSConfig(job.Getenv("AuthCa"), job.Getenv("AuthCert"), job.Getenv("AuthKey")); err != nil { return nil, fmt.Errorf("Error creating TLS config: %s", err) } case "none": tlsConfig = nil default: return nil, fmt.Errorf("Unknown auth method: %s", job.Getenv("Auth")) } if tlsConfig == nil { log.Infof("/!\\ DON'T BIND INSECURELY ON A TCP ADDRESS IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\") } else { l = tls.NewListener(l, tlsConfig) } return &HttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil }
func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { setDefaultMtu(config) // Ensure we have compatible configuration options if err := checkConfigOptions(config); err != nil { return nil, err } // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) // Verify the platform is supported as a daemon if runtime.GOOS != "linux" && runtime.GOOS != "windows" { return nil, ErrSystemNotSupported } // Validate platform-specific requirements if err := checkSystem(); err != nil { return nil, err } // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event // on Windows to dump Go routine stacks setupDumpStackTrap() // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } config.Root = realRoot // Create the root directory if it doesn't exists if err := system.MkdirAll(config.Root, 0700); err != nil { return nil, err } // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) // Set the default driver graphdriver.DefaultDriver = config.GraphDriver // Load storage driver driver, err := graphdriver.New(config.Root, config.GraphOptions) if err != nil { return nil, fmt.Errorf("error initializing graphdriver: %v", err) } logrus.Debugf("Using graph driver %s", driver) d := &Daemon{} d.driver = driver // Ensure the graph driver is shutdown at a later point defer func() { if err != nil { if err := d.Shutdown(); err != nil { logrus.Error(err) } } }() // Verify logging driver type if config.LogConfig.Type != "none" { if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { return nil, fmt.Errorf("error finding the logging driver: %v", err) } } logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) // Configure and validate the kernels security support if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil { return nil, err } daemonRepo := filepath.Join(config.Root, "containers") if err := system.MkdirAll(daemonRepo, 0700); err != nil { return nil, err } // Migrate the container if it is aufs and aufs is enabled if err := migrateIfDownlevel(d.driver, config.Root); err != nil { return nil, err } logrus.Debug("Creating images graph") g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver) if err != nil { return nil, err } // Configure the volumes driver if err := configureVolumes(config); err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } trustDir := filepath.Join(config.Root, "trust") if err := system.MkdirAll(trustDir, 0700); err != nil { return nil, err } trustService, err := trust.NewTrustStore(trustDir) if err != nil { return nil, fmt.Errorf("could not create trust store: %s", err) } eventsService := events.New() logrus.Debug("Creating repository list") tagCfg := &graph.TagStoreConfig{ Graph: g, Key: trustKey, Registry: registryService, Events: eventsService, Trust: trustService, } repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err) } d.netController, err = initNetworkController(config) if err != nil { return nil, fmt.Errorf("Error initializing network controller: %v", err) } graphdbPath := filepath.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil { return nil, err } d.containerGraph = graph var sysInitPath string if config.ExecDriver == "lxc" { initPath, err := configureSysInit(config) if err != nil { return nil, err } sysInitPath = initPath } sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux/FreeBSD. if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { return nil, fmt.Errorf("Devices cgroup isn't mounted") } ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo) if err != nil { return nil, err } d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = &contStore{s: make(map[string]*Container)} d.execCommands = newExecStore() d.graph = g d.repositories = repositories d.idIndex = truncindex.NewTruncIndex([]string{}) d.sysInfo = sysInfo d.config = config d.sysInitPath = sysInitPath d.execDriver = ed d.statsCollector = newStatsCollector(1 * time.Second) d.defaultLogConfig = config.LogConfig d.RegistryService = registryService d.EventsService = eventsService d.root = config.Root go d.execCommandGC() if err := d.restore(); err != nil { return nil, err } return d, nil }
// NewDaemon sets up everything for the daemon to be able to service // requests from the webserver. func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { setDefaultMtu(config) // Ensure we have compatible configuration options if err := checkConfigOptions(config); err != nil { return nil, err } // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) // Verify the platform is supported as a daemon if !platformSupported { return nil, errSystemNotSupported } // Validate platform-specific requirements if err := checkSystem(); err != nil { return nil, err } // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event // on Windows to dump Go routine stacks setupDumpStackTrap() uidMaps, gidMaps, err := setupRemappedRoot(config) if err != nil { return nil, err } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { return nil, err } // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root, rootUID, rootGID) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) // Set the default driver graphdriver.DefaultDriver = config.GraphDriver // Load storage driver driver, err := graphdriver.New(config.Root, config.GraphOptions, uidMaps, gidMaps) if err != nil { return nil, fmt.Errorf("error initializing graphdriver: %v", err) } logrus.Debugf("Using graph driver %s", driver) d := &Daemon{} d.driver = driver // Ensure the graph driver is shutdown at a later point defer func() { if err != nil { if err := d.Shutdown(); err != nil { logrus.Error(err) } } }() // Verify logging driver type if config.LogConfig.Type != "none" { if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { return nil, fmt.Errorf("error finding the logging driver: %v", err) } } logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) // Configure and validate the kernels security support if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil { return nil, err } daemonRepo := filepath.Join(config.Root, "containers") if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { return nil, err } // Migrate the container if it is aufs and aufs is enabled if err := migrateIfDownlevel(d.driver, config.Root); err != nil { return nil, err } imageRoot := filepath.Join(config.Root, "image", d.driver.String()) fms, err := layer.NewFSMetadataStore(filepath.Join(imageRoot, "layerdb")) if err != nil { return nil, err } d.layerStore, err = layer.NewStore(fms, d.driver) if err != nil { return nil, err } d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, maxDownloadConcurrency) d.uploadManager = xfer.NewLayerUploadManager(maxUploadConcurrency) ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) if err != nil { return nil, err } d.imageStore, err = image.NewImageStore(ifs, d.layerStore) if err != nil { return nil, err } // Configure the volumes driver volStore, err := configureVolumes(config, rootUID, rootGID) if err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } trustDir := filepath.Join(config.Root, "trust") if err := system.MkdirAll(trustDir, 0700); err != nil { return nil, err } distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) if err != nil { return nil, err } eventsService := events.New() tagStore, err := tag.NewTagStore(filepath.Join(imageRoot, "repositories.json")) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err) } if err := restoreCustomImage(d.driver, d.imageStore, d.layerStore, tagStore); err != nil { return nil, fmt.Errorf("Couldn't restore custom images: %s", err) } if err := v1.Migrate(config.Root, d.driver.String(), d.layerStore, d.imageStore, tagStore, distributionMetadataStore); err != nil { return nil, err } // Discovery is only enabled when the daemon is launched with an address to advertise. When // initialized, the daemon is registered and we can store the discovery backend as its read-only // DiscoveryWatcher version. if config.ClusterStore != "" && config.ClusterAdvertise != "" { advertise, err := discovery.ParseAdvertise(config.ClusterStore, config.ClusterAdvertise) if err != nil { return nil, fmt.Errorf("discovery advertise parsing failed (%v)", err) } config.ClusterAdvertise = advertise d.discoveryWatcher, err = initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts) if err != nil { return nil, fmt.Errorf("discovery initialization failed (%v)", err) } } else if config.ClusterAdvertise != "" { return nil, fmt.Errorf("invalid cluster configuration. --cluster-advertise must be accompanied by --cluster-store configuration") } d.netController, err = d.initNetworkController(config) if err != nil { return nil, fmt.Errorf("Error initializing network controller: %v", err) } graphdbPath := filepath.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil { return nil, err } d.containerGraphDB = graph sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux/FreeBSD. if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { return nil, fmt.Errorf("Devices cgroup isn't mounted") } ed, err := execdrivers.NewDriver(config.ExecOptions, config.ExecRoot, config.Root, sysInfo) if err != nil { return nil, err } d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = &contStore{s: make(map[string]*container.Container)} d.execCommands = exec.NewStore() d.tagStore = tagStore d.distributionMetadataStore = distributionMetadataStore d.trustKey = trustKey d.idIndex = truncindex.NewTruncIndex([]string{}) d.configStore = config d.execDriver = ed d.statsCollector = d.newStatsCollector(1 * time.Second) d.defaultLogConfig = config.LogConfig d.RegistryService = registryService d.EventsService = eventsService d.volumes = volStore d.root = config.Root d.uidMaps = uidMaps d.gidMaps = gidMaps if err := d.cleanupMounts(); err != nil { return nil, err } go d.execCommandGC() if err := d.restore(); err != nil { return nil, err } return d, nil }
// NewDaemon sets up everything for the daemon to be able to service // requests from the webserver. func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) { setDefaultMtu(config) // Ensure that we have a correct root key limit for launching containers. if err := ModifyRootKeyLimit(); err != nil { logrus.Warnf("unable to modify root key limit, number of containers could be limitied by this quota: %v", err) } // Ensure we have compatible and valid configuration options if err := verifyDaemonSettings(config); err != nil { return nil, err } // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) // Verify the platform is supported as a daemon if !platformSupported { return nil, errSystemNotSupported } // Validate platform-specific requirements if err := checkSystem(); err != nil { return nil, err } // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event // on Windows to dump Go routine stacks setupDumpStackTrap() uidMaps, gidMaps, err := setupRemappedRoot(config) if err != nil { return nil, err } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } if err := setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { return nil, err } if err := setupDaemonProcess(config); err != nil { return nil, err } // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root, rootUID, rootGID) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) d := &Daemon{configStore: config} // Ensure the daemon is properly shutdown if there is a failure during // initialization defer func() { if err != nil { if err := d.Shutdown(); err != nil { logrus.Error(err) } } }() // Set the default isolation mode (only applicable on Windows) if err := d.setDefaultIsolation(); err != nil { return nil, fmt.Errorf("error setting default isolation mode: %v", err) } logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) if err := configureMaxThreads(config); err != nil { logrus.Warnf("Failed to configure golang's threads limit: %v", err) } installDefaultAppArmorProfile() daemonRepo := filepath.Join(config.Root, "containers") if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { return nil, err } driverName := os.Getenv("DOCKER_DRIVER") if driverName == "" { driverName = config.GraphDriver } d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{ StorePath: config.Root, MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), GraphDriver: driverName, GraphDriverOptions: config.GraphOptions, UIDMaps: uidMaps, GIDMaps: gidMaps, }) if err != nil { return nil, err } graphDriver := d.layerStore.DriverName() imageRoot := filepath.Join(config.Root, "image", graphDriver) // Configure and validate the kernels security support if err := configureKernelSecuritySupport(config, graphDriver); err != nil { return nil, err } logrus.Debugf("Max Concurrent Downloads: %d", *config.MaxConcurrentDownloads) d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, *config.MaxConcurrentDownloads) logrus.Debugf("Max Concurrent Uploads: %d", *config.MaxConcurrentUploads) d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads) ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) if err != nil { return nil, err } d.imageStore, err = image.NewImageStore(ifs, d.layerStore) if err != nil { return nil, err } // Configure the volumes driver volStore, err := d.configureVolumes(rootUID, rootGID) if err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } trustDir := filepath.Join(config.Root, "trust") if err := system.MkdirAll(trustDir, 0700); err != nil { return nil, err } distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) if err != nil { return nil, err } eventsService := events.New() referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json")) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err) } migrationStart := time.Now() if err := v1.Migrate(config.Root, graphDriver, d.layerStore, d.imageStore, referenceStore, distributionMetadataStore); err != nil { logrus.Errorf("Graph migration failed: %q. Your old graph data was found to be too inconsistent for upgrading to content-addressable storage. Some of the old data was probably not upgraded. We recommend starting over with a clean storage directory if possible.", err) } logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) // Discovery is only enabled when the daemon is launched with an address to advertise. When // initialized, the daemon is registered and we can store the discovery backend as its read-only if err := d.initDiscovery(config); err != nil { return nil, err } sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux. if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled { return nil, fmt.Errorf("Devices cgroup isn't mounted") } d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = container.NewMemoryStore() d.execCommands = exec.NewStore() d.referenceStore = referenceStore d.distributionMetadataStore = distributionMetadataStore d.trustKey = trustKey d.idIndex = truncindex.NewTruncIndex([]string{}) d.statsCollector = d.newStatsCollector(1 * time.Second) d.defaultLogConfig = containertypes.LogConfig{ Type: config.LogConfig.Type, Config: config.LogConfig.Config, } d.RegistryService = registryService d.EventsService = eventsService d.volumes = volStore d.root = config.Root d.uidMaps = uidMaps d.gidMaps = gidMaps d.seccompEnabled = sysInfo.Seccomp d.nameIndex = registrar.NewRegistrar() d.linkIndex = newLinkIndex() d.containerdRemote = containerdRemote go d.execCommandGC() d.containerd, err = containerdRemote.Client(d) if err != nil { return nil, err } if err := d.restore(); err != nil { return nil, err } if err := pluginInit(d, config, containerdRemote); err != nil { return nil, err } return d, nil }
func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) { if config.Mtu == 0 { config.Mtu = getDefaultNetworkMtu() } // Check for mutually incompatible config options if config.BridgeIface != "" && config.BridgeIP != "" { return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") } if !config.EnableIptables && !config.InterContainerCommunication { return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") } if !config.EnableIptables && config.EnableIpMasq { config.EnableIpMasq = false } config.DisableNetwork = config.BridgeIface == disableNetworkBridge // Claim the pidfile first, to avoid any and all unexpected race conditions. // Some of the init doesn't need a pidfile lock - but let's not try to be smart. if config.Pidfile != "" { if err := utils.CreatePidFile(config.Pidfile); err != nil { return nil, err } eng.OnShutdown(func() { // Always release the pidfile last, just in case utils.RemovePidFile(config.Pidfile) }) } // Check that the system is supported and we have sufficient privileges if runtime.GOOS != "linux" { return nil, fmt.Errorf("The Docker daemon is only supported on linux") } if os.Geteuid() != 0 { return nil, fmt.Errorf("The Docker daemon needs to be run as root") } if err := checkKernelAndArch(); err != nil { return nil, err } // set up the TempDir to use a canonical path tmp, err := utils.TempDir(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := utils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) if !config.EnableSelinuxSupport { selinuxSetDisabled() } // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = utils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } config.Root = realRoot // Create the root directory if it doesn't exists if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { return nil, err } // Set the default driver graphdriver.DefaultDriver = config.GraphDriver // Load storage driver driver, err := graphdriver.New(config.Root, config.GraphOptions) if err != nil { return nil, err } log.Debugf("Using graph driver %s", driver) // As Docker on btrfs and SELinux are incompatible at present, error on both being enabled if selinuxEnabled() && config.EnableSelinuxSupport && driver.String() == "btrfs" { return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver!") } daemonRepo := path.Join(config.Root, "containers") if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) { return nil, err } // Migrate the container if it is aufs and aufs is enabled if err = migrateIfAufs(driver, config.Root); err != nil { return nil, err } log.Debugf("Creating images graph") g, err := graph.NewGraph(path.Join(config.Root, "graph"), driver) if err != nil { return nil, err } volumesDriver, err := graphdriver.GetDriver("vfs", config.Root, config.GraphOptions) if err != nil { return nil, err } volumes, err := volumes.NewRepository(path.Join(config.Root, "volumes"), volumesDriver) if err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } log.Debugf("Creating repository list") repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, trustKey) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store: %s", err) } trustDir := path.Join(config.Root, "trust") if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { return nil, err } t, err := trust.NewTrustStore(trustDir) if err != nil { return nil, fmt.Errorf("could not create trust store: %s", err) } if !config.DisableNetwork { job := eng.Job("init_networkdriver") job.SetenvBool("EnableIptables", config.EnableIptables) job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication) job.SetenvBool("EnableIpForward", config.EnableIpForward) job.SetenvBool("EnableIpMasq", config.EnableIpMasq) job.SetenvBool("EnableIPv6", config.EnableIPv6) job.Setenv("BridgeIface", config.BridgeIface) job.Setenv("BridgeIP", config.BridgeIP) job.Setenv("FixedCIDR", config.FixedCIDR) job.Setenv("FixedCIDRv6", config.FixedCIDRv6) job.Setenv("DefaultBindingIP", config.DefaultIp.String()) if err := job.Run(); err != nil { return nil, err } } graphdbPath := path.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil { return nil, err } localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) sysInitPath := utils.DockerInitPath(localCopy) if sysInitPath == "" { return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See http://docs.docker.com/contributing/devenvironment for official build instructions.") } if sysInitPath != localCopy { // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { return nil, err } if _, err := utils.CopyFile(sysInitPath, localCopy); err != nil { return nil, err } if err := os.Chmod(localCopy, 0700); err != nil { return nil, err } sysInitPath = localCopy } sysInfo := sysinfo.New(false) ed, err := execdrivers.NewDriver(config.ExecDriver, config.Root, sysInitPath, sysInfo) if err != nil { return nil, err } daemon := &Daemon{ ID: trustKey.PublicKey().KeyID(), repository: daemonRepo, containers: &contStore{s: make(map[string]*Container)}, execCommands: newExecStore(), graph: g, repositories: repositories, idIndex: truncindex.NewTruncIndex([]string{}), sysInfo: sysInfo, volumes: volumes, config: config, containerGraph: graph, driver: driver, sysInitPath: sysInitPath, execDriver: ed, eng: eng, trustStore: t, } if err := daemon.restore(); err != nil { return nil, err } // set up filesystem watch on resolv.conf for network changes if err := daemon.setupResolvconfWatcher(); err != nil { return nil, err } // Setup shutdown handlers // FIXME: can these shutdown handlers be registered closer to their source? eng.OnShutdown(func() { // FIXME: if these cleanup steps can be called concurrently, register // them as separate handlers to speed up total shutdown time if err := daemon.shutdown(); err != nil { log.Errorf("daemon.shutdown(): %s", err) } if err := portallocator.ReleaseAll(); err != nil { log.Errorf("portallocator.ReleaseAll(): %s", err) } if err := daemon.driver.Cleanup(); err != nil { log.Errorf("daemon.driver.Cleanup(): %s", err.Error()) } if err := daemon.containerGraph.Close(); err != nil { log.Errorf("daemon.containerGraph.Close(): %s", err.Error()) } }) return daemon, nil }
// NewDaemon sets up everything for the daemon to be able to service // requests from the webserver. func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { setDefaultMtu(config) // Ensure we have compatible configuration options if err := checkConfigOptions(config); err != nil { return nil, err } // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) // Verify the platform is supported as a daemon if !platformSupported { return nil, errSystemNotSupported } // Validate platform-specific requirements if err := checkSystem(); err != nil { return nil, err } // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event // on Windows to dump Go routine stacks setupDumpStackTrap() uidMaps, gidMaps, err := setupRemappedRoot(config) if err != nil { return nil, err } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { return nil, err } // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root, rootUID, rootGID) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) d := &Daemon{} // Ensure the daemon is properly shutdown if there is a failure during // initialization defer func() { if err != nil { if err := d.Shutdown(); err != nil { logrus.Error(err) } } }() // Verify logging driver type if config.LogConfig.Type != "none" { if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { return nil, fmt.Errorf("error finding the logging driver: %v", err) } } logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) daemonRepo := filepath.Join(config.Root, "containers") if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { return nil, err } driverName := os.Getenv("DOCKER_DRIVER") if driverName == "" { driverName = config.GraphDriver } d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{ StorePath: config.Root, MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), GraphDriver: driverName, GraphDriverOptions: config.GraphOptions, UIDMaps: uidMaps, GIDMaps: gidMaps, }) if err != nil { return nil, err } graphDriver := d.layerStore.DriverName() imageRoot := filepath.Join(config.Root, "image", graphDriver) // Configure and validate the kernels security support if err := configureKernelSecuritySupport(config, graphDriver); err != nil { return nil, err } d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, maxDownloadConcurrency) d.uploadManager = xfer.NewLayerUploadManager(maxUploadConcurrency) ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) if err != nil { return nil, err } d.imageStore, err = image.NewImageStore(ifs, d.layerStore) if err != nil { return nil, err } // Configure the volumes driver volStore, err := configureVolumes(config, rootUID, rootGID) if err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } trustDir := filepath.Join(config.Root, "trust") if err := system.MkdirAll(trustDir, 0700); err != nil { return nil, err } distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) if err != nil { return nil, err } eventsService := events.New() referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json")) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err) } if err := restoreCustomImage(d.imageStore, d.layerStore, referenceStore); err != nil { return nil, fmt.Errorf("Couldn't restore custom images: %s", err) } migrationStart := time.Now() if err := v1.Migrate(config.Root, graphDriver, d.layerStore, d.imageStore, referenceStore, distributionMetadataStore); err != nil { return nil, err } logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) // Discovery is only enabled when the daemon is launched with an address to advertise. When // initialized, the daemon is registered and we can store the discovery backend as its read-only if err := d.initDiscovery(config); err != nil { return nil, err } d.netController, err = d.initNetworkController(config) if err != nil { return nil, fmt.Errorf("Error initializing network controller: %v", err) } sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux/FreeBSD. if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { return nil, fmt.Errorf("Devices cgroup isn't mounted") } ed, err := execdrivers.NewDriver(config.ExecOptions, config.ExecRoot, config.Root, sysInfo) if err != nil { return nil, err } d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = container.NewMemoryStore() d.execCommands = exec.NewStore() d.referenceStore = referenceStore d.distributionMetadataStore = distributionMetadataStore d.trustKey = trustKey d.idIndex = truncindex.NewTruncIndex([]string{}) d.configStore = config d.execDriver = ed d.statsCollector = d.newStatsCollector(1 * time.Second) d.defaultLogConfig = containertypes.LogConfig{ Type: config.LogConfig.Type, Config: config.LogConfig.Config, } d.RegistryService = registryService d.EventsService = eventsService d.volumes = volStore d.root = config.Root d.uidMaps = uidMaps d.gidMaps = gidMaps d.seccompEnabled = sysInfo.Seccomp d.nameIndex = registrar.NewRegistrar() d.linkIndex = newLinkIndex() if err := d.cleanupMounts(); err != nil { return nil, err } go d.execCommandGC() if err := d.restore(); err != nil { return nil, err } return d, nil }
func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { // Check for mutually incompatible config options if config.Bridge.Iface != "" && config.Bridge.IP != "" { return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") } setDefaultMtu(config) if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication { return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") } if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq { config.Bridge.EnableIPMasq = false } config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge // Check that the system is supported and we have sufficient privileges if runtime.GOOS != "linux" { return nil, fmt.Errorf("The Docker daemon is only supported on linux") } if os.Geteuid() != 0 { return nil, fmt.Errorf("The Docker daemon needs to be run as root") } if err := checkKernel(); err != nil { return nil, err } // set up SIGUSR1 handler to dump Go routine stacks setupSigusr1Trap() // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } config.Root = realRoot // Create the root directory if it doesn't exists if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { return nil, err } // Set the default driver graphdriver.DefaultDriver = config.GraphDriver // Load storage driver driver, err := graphdriver.New(config.Root, config.GraphOptions) if err != nil { return nil, fmt.Errorf("error initializing graphdriver: %v", err) } logrus.Debugf("Using graph driver %s", driver) d := &Daemon{} d.driver = driver defer func() { if err != nil { if err := d.Shutdown(); err != nil { logrus.Error(err) } } }() // Verify logging driver type if config.LogConfig.Type != "none" { if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { return nil, fmt.Errorf("error finding the logging driver: %v", err) } } logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) if config.EnableSelinuxSupport { if selinuxEnabled() { // As Docker on btrfs and SELinux are incompatible at present, error on both being enabled if d.driver.String() == "btrfs" { return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver") } logrus.Debug("SELinux enabled successfully") } else { logrus.Warn("Docker could not enable SELinux on the host system") } } else { selinuxSetDisabled() } daemonRepo := path.Join(config.Root, "containers") if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) { return nil, err } // Migrate the container if it is aufs and aufs is enabled if err := migrateIfAufs(d.driver, config.Root); err != nil { return nil, err } logrus.Debug("Creating images graph") g, err := graph.NewGraph(path.Join(config.Root, "graph"), d.driver) if err != nil { return nil, err } volumesDriver, err := local.New(config.Root) if err != nil { return nil, err } volumedrivers.Register(volumesDriver, volumesDriver.Name()) trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { return nil, err } trustDir := path.Join(config.Root, "trust") if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { return nil, err } trustService, err := trust.NewTrustStore(trustDir) if err != nil { return nil, fmt.Errorf("could not create trust store: %s", err) } eventsService := events.New() logrus.Debug("Creating repository list") tagCfg := &graph.TagStoreConfig{ Graph: g, Key: trustKey, Registry: registryService, Events: eventsService, Trust: trustService, } repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store: %s", err) } if !config.DisableNetwork { d.netController, err = initNetworkController(config) if err != nil { return nil, fmt.Errorf("Error initializing network controller: %v", err) } } graphdbPath := path.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil { return nil, err } d.containerGraph = graph localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) sysInitPath := utils.DockerInitPath(localCopy) if sysInitPath == "" { return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/contributing/devenvironment for official build instructions.") } if sysInitPath != localCopy { // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { return nil, err } if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil { return nil, err } if err := os.Chmod(localCopy, 0700); err != nil { return nil, err } sysInitPath = localCopy } sysInfo := sysinfo.New(false) ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo) if err != nil { return nil, err } d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = &contStore{s: make(map[string]*Container)} d.execCommands = newExecStore() d.graph = g d.repositories = repositories d.idIndex = truncindex.NewTruncIndex([]string{}) d.sysInfo = sysInfo d.config = config d.sysInitPath = sysInitPath d.execDriver = ed d.statsCollector = newStatsCollector(1 * time.Second) d.defaultLogConfig = config.LogConfig d.RegistryService = registryService d.EventsService = eventsService d.root = config.Root if err := d.restore(); err != nil { return nil, err } return d, nil }
func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { uidMaps, gidMaps, err := setupRemappedRoot(config) if err != nil { return nil, err } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // get the canonical path to the Docker root directory var realRoot string if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { realRoot = config.Root } else { realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) if err != nil { return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) } } if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { return nil, err } // set up the tmpDir to use a canonical path tmp, err := tempDir(config.Root, rootUID, rootGID) if err != nil { return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) if err != nil { return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) } os.Setenv("TMPDIR", realTmp) // Load storage driver driver, err := graphdriver.New(config.Root, config.GraphOptions, uidMaps, gidMaps) if err != nil { return nil, fmt.Errorf("error initializing graphdriver: %v", err) } glog.V(1).Infof("Using graph driver %s", driver) d := &Daemon{} d.driver = driver defer func() { if err != nil { if err := d.Shutdown(); err != nil { glog.Error(err) } } }() daemonRepo := path.Join(config.Root, "containers") if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) { glog.Error(err.Error()) return nil, err } glog.Info("Creating images graph") g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver, uidMaps, gidMaps) if err != nil { glog.Error(err.Error()) return nil, err } // Configure the volumes driver volStore, err := configureVolumes(config, rootUID, rootGID) if err != nil { return nil, err } trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) if err != nil { glog.Error(err.Error()) return nil, err } trustDir := path.Join(config.Root, "trust") if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { glog.Error(err.Error()) return nil, err } eventsService := events.New() glog.Info("Creating repository list") tagCfg := &graph.TagStoreConfig{ Graph: g, Key: trustKey, Registry: registryService, Events: eventsService, } repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) if err != nil { glog.Error(err.Error()) return nil, fmt.Errorf("Couldn't create Tag store: %s", err) } graphdbPath := path.Join(config.Root, "linkgraph.db") graph, err := graphdb.NewSqliteConn(graphdbPath) if err != nil { glog.Error(err.Error()) return nil, err } d.containerGraphDB = graph sysInfo := sysinfo.New(false) d.ID = trustKey.PublicKey().KeyID() d.repository = daemonRepo d.containers = &contStore{s: make(map[string]*Container)} d.graph = g d.repositories = repositories d.idIndex = truncindex.NewTruncIndex([]string{}) d.sysInfo = sysInfo d.configStore = config d.sysInitPath = "" d.defaultLogConfig = config.LogConfig d.RegistryService = registryService d.EventsService = eventsService d.root = config.Root d.volumes = volStore if err := d.restore(); err != nil { return nil, err } return d, nil }
func main() { if reexec.Init() { return } flag.Parse() // FIXME: validate daemon flags here if *flVersion { showVersion() return } if *flLogLevel != "" { lvl, err := log.ParseLevel(*flLogLevel) if err != nil { log.Fatalf("Unable to parse logging level: %s", *flLogLevel) } initLogging(lvl) } else { initLogging(log.InfoLevel) } // -D, --debug, -l/--log-level=debug processing // When/if -D is removed this block can be deleted if *flDebug { os.Setenv("DEBUG", "1") initLogging(log.DebugLevel) } if len(flHosts) == 0 { defaultHost := os.Getenv("DOCKER_HOST") if defaultHost == "" || *flDaemon { // If we do not have a host, default to unix socket defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET) } defaultHost, err := api.ValidateHost(defaultHost) if err != nil { log.Fatal(err) } flHosts = append(flHosts, defaultHost) } if *flDaemon { mainDaemon() return } if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) trustKey, err := api.LoadOrCreateTrustKey(*flTrustKey) if err != nil { log.Fatal(err) } var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true // Regardless of whether the user sets it to true or false, if they // specify --tlsverify at all then we need to turn on tls if flag.IsSet("-tlsverify") { *flTls = true } // If we should verify the server, we need to load a trusted ca if *flTlsVerify { certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } // If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } // Avoid fallback to SSL protocols < TLS1.0 tlsConfig.MinVersion = tls.VersionTLS10 } if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], nil) } if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } }