func newExecDriver() (execdriver.Driver, error) { sysInitPath := path.Join(dockerRoot, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) //sysInfo := sysinfo.New(false) // only native driver //ed, err := execdrivers.NewDriver(c.ExecDriver, dockerRoot, sysInitPath, sysInfo) ed, err := execdrivers.NewDriver("native", dockerRoot, sysInitPath, execdriver.NativeExternal, nil) if err != nil { return nil, err } return ed, 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 }
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 NewDaemonFromDirectory(config *daemonconfig.Config, eng *engine.Engine) (*Daemon, error) { if runtime.GOOS != "linux" { log.Fatalf("The Docker daemon is only supported on linux") } if os.Geteuid() != 0 { log.Fatalf("The Docker daemon needs to be run as root") } if err := checkKernelAndArch(); err != nil { log.Fatal(err) } // set up the TempDir to use a canonical path tmp, err := utils.TempDir(config.Root) if err != nil { log.Fatalf("Unable to get the TempDir under %s: %s", config.Root, err) } realTmp, err := utils.ReadSymlinkedDirectory(tmp) if err != nil { log.Fatalf("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 { log.Fatalf("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 } utils.Debugf("Using graph driver %s", driver) // As Docker on btrfs and SELinux are incompatible at present, error on both being enabled if 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 } utils.Debugf("Creating images graph") g, err := graph.NewGraph(path.Join(config.Root, "graph"), driver) if err != nil { return nil, err } // We don't want to use a complex driver like aufs or devmapper // for volumes, just a plain filesystem volumesDriver, err := graphdriver.GetDriver("vfs", config.Root, config.GraphOptions) if err != nil { return nil, err } utils.Debugf("Creating volumes graph") volumes, err := graph.NewGraph(path.Join(config.Root, "volumes"), volumesDriver) if err != nil { return nil, err } utils.Debugf("Creating repository list") repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g) if err != nil { return nil, fmt.Errorf("Couldn't create Tag 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.Setenv("BridgeIface", config.BridgeIface) job.Setenv("BridgeIP", config.BridgeIP) 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{ repository: daemonRepo, containers: &contStore{s: make(map[string]*Container)}, graph: g, repositories: repositories, idIndex: truncindex.NewTruncIndex([]string{}), sysInfo: sysInfo, volumes: volumes, config: config, containerGraph: graph, driver: driver, sysInitPath: sysInitPath, execDriver: ed, eng: eng, Sockets: config.Sockets, } if err := daemon.checkLocaldns(); err != nil { return nil, err } if err := daemon.restore(); err != nil { return nil, err } return daemon, 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 }