github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/daemon/daemon.go (about) 1 // Package daemon exposes the functions that occur on the host server 2 // that the Docker daemon is running. 3 // 4 // In implementing the various functions of the daemon, there is often 5 // a method-specific struct for configuring the runtime behavior. 6 package daemon 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "net" 14 "os" 15 "path" 16 "path/filepath" 17 "runtime" 18 "strings" 19 "sync" 20 "syscall" 21 "time" 22 23 "github.com/Sirupsen/logrus" 24 containerd "github.com/docker/containerd/api/grpc/types" 25 "github.com/docker/docker/api" 26 "github.com/docker/docker/api/types" 27 containertypes "github.com/docker/docker/api/types/container" 28 "github.com/docker/docker/container" 29 "github.com/docker/docker/daemon/events" 30 "github.com/docker/docker/daemon/exec" 31 "github.com/docker/docker/dockerversion" 32 "github.com/docker/libnetwork/cluster" 33 // register graph drivers 34 _ "github.com/docker/docker/daemon/graphdriver/register" 35 dmetadata "github.com/docker/docker/distribution/metadata" 36 "github.com/docker/docker/distribution/xfer" 37 "github.com/docker/docker/image" 38 "github.com/docker/docker/layer" 39 "github.com/docker/docker/libcontainerd" 40 "github.com/docker/docker/migrate/v1" 41 "github.com/docker/docker/pkg/fileutils" 42 "github.com/docker/docker/pkg/graphdb" 43 "github.com/docker/docker/pkg/idtools" 44 "github.com/docker/docker/pkg/plugingetter" 45 "github.com/docker/docker/pkg/progress" 46 "github.com/docker/docker/pkg/registrar" 47 "github.com/docker/docker/pkg/signal" 48 "github.com/docker/docker/pkg/streamformatter" 49 "github.com/docker/docker/pkg/sysinfo" 50 "github.com/docker/docker/pkg/system" 51 "github.com/docker/docker/pkg/truncindex" 52 pluginstore "github.com/docker/docker/plugin/store" 53 "github.com/docker/docker/reference" 54 "github.com/docker/docker/registry" 55 "github.com/docker/docker/runconfig" 56 volumedrivers "github.com/docker/docker/volume/drivers" 57 "github.com/docker/docker/volume/local" 58 "github.com/docker/docker/volume/store" 59 "github.com/docker/libnetwork" 60 nwconfig "github.com/docker/libnetwork/config" 61 "github.com/docker/libtrust" 62 ) 63 64 var ( 65 // DefaultRuntimeBinary is the default runtime to be used by 66 // containerd if none is specified 67 DefaultRuntimeBinary = "docker-runc" 68 69 errSystemNotSupported = fmt.Errorf("The Docker daemon is not supported on this platform.") 70 ) 71 72 // Daemon holds information about the Docker daemon. 73 type Daemon struct { 74 ID string 75 repository string 76 containers container.Store 77 execCommands *exec.Store 78 referenceStore reference.Store 79 downloadManager *xfer.LayerDownloadManager 80 uploadManager *xfer.LayerUploadManager 81 distributionMetadataStore dmetadata.Store 82 trustKey libtrust.PrivateKey 83 idIndex *truncindex.TruncIndex 84 configStore *Config 85 statsCollector *statsCollector 86 defaultLogConfig containertypes.LogConfig 87 RegistryService registry.Service 88 EventsService *events.Events 89 netController libnetwork.NetworkController 90 volumes *store.VolumeStore 91 discoveryWatcher discoveryReloader 92 root string 93 seccompEnabled bool 94 shutdown bool 95 uidMaps []idtools.IDMap 96 gidMaps []idtools.IDMap 97 layerStore layer.Store 98 imageStore image.Store 99 PluginStore *pluginstore.Store 100 nameIndex *registrar.Registrar 101 linkIndex *linkIndex 102 containerd libcontainerd.Client 103 containerdRemote libcontainerd.Remote 104 defaultIsolation containertypes.Isolation // Default isolation mode on Windows 105 clusterProvider cluster.Provider 106 cluster Cluster 107 } 108 109 // HasExperimental returns whether the experimental features of the daemon are enabled or not 110 func (daemon *Daemon) HasExperimental() bool { 111 if daemon.configStore != nil && daemon.configStore.Experimental { 112 return true 113 } 114 return false 115 } 116 117 func (daemon *Daemon) restore() error { 118 var ( 119 currentDriver = daemon.GraphDriverName() 120 containers = make(map[string]*container.Container) 121 ) 122 123 logrus.Info("Loading containers: start.") 124 125 dir, err := ioutil.ReadDir(daemon.repository) 126 if err != nil { 127 return err 128 } 129 130 for _, v := range dir { 131 id := v.Name() 132 container, err := daemon.load(id) 133 if err != nil { 134 logrus.Errorf("Failed to load container %v: %v", id, err) 135 continue 136 } 137 138 // Ignore the container if it does not support the current driver being used by the graph 139 if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { 140 rwlayer, err := daemon.layerStore.GetRWLayer(container.ID) 141 if err != nil { 142 logrus.Errorf("Failed to load container mount %v: %v", id, err) 143 continue 144 } 145 container.RWLayer = rwlayer 146 logrus.Debugf("Loaded container %v", container.ID) 147 148 containers[container.ID] = container 149 } else { 150 logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) 151 } 152 } 153 154 var migrateLegacyLinks bool 155 removeContainers := make(map[string]*container.Container) 156 restartContainers := make(map[*container.Container]chan struct{}) 157 activeSandboxes := make(map[string]interface{}) 158 for id, c := range containers { 159 if err := daemon.registerName(c); err != nil { 160 logrus.Errorf("Failed to register container %s: %s", c.ID, err) 161 delete(containers, id) 162 continue 163 } 164 if err := daemon.Register(c); err != nil { 165 logrus.Errorf("Failed to register container %s: %s", c.ID, err) 166 delete(containers, id) 167 continue 168 } 169 170 // verify that all volumes valid and have been migrated from the pre-1.7 layout 171 if err := daemon.verifyVolumesInfo(c); err != nil { 172 // don't skip the container due to error 173 logrus.Errorf("Failed to verify volumes for container '%s': %v", c.ID, err) 174 } 175 176 // The LogConfig.Type is empty if the container was created before docker 1.12 with default log driver. 177 // We should rewrite it to use the daemon defaults. 178 // Fixes https://github.com/docker/docker/issues/22536 179 if c.HostConfig.LogConfig.Type == "" { 180 if err := daemon.mergeAndVerifyLogConfig(&c.HostConfig.LogConfig); err != nil { 181 logrus.Errorf("Failed to verify log config for container %s: %q", c.ID, err) 182 continue 183 } 184 } 185 } 186 var wg sync.WaitGroup 187 var mapLock sync.Mutex 188 for _, c := range containers { 189 wg.Add(1) 190 go func(c *container.Container) { 191 defer wg.Done() 192 if err := backportMountSpec(c); err != nil { 193 logrus.Errorf("Failed to migrate old mounts to use new spec format") 194 } 195 196 if c.IsRunning() || c.IsPaused() { 197 c.RestartManager().Cancel() // manually start containers because some need to wait for swarm networking 198 if err := daemon.containerd.Restore(c.ID, c.InitializeStdio); err != nil { 199 logrus.Errorf("Failed to restore %s with containerd: %s", c.ID, err) 200 return 201 } 202 c.ResetRestartManager(false) 203 if !c.HostConfig.NetworkMode.IsContainer() && c.IsRunning() { 204 options, err := daemon.buildSandboxOptions(c) 205 if err != nil { 206 logrus.Warnf("Failed build sandbox option to restore container %s: %v", c.ID, err) 207 } 208 mapLock.Lock() 209 activeSandboxes[c.NetworkSettings.SandboxID] = options 210 mapLock.Unlock() 211 } 212 213 } 214 // fixme: only if not running 215 // get list of containers we need to restart 216 if !c.IsRunning() && !c.IsPaused() { 217 // Do not autostart containers which 218 // has endpoints in a swarm scope 219 // network yet since the cluster is 220 // not initialized yet. We will start 221 // it after the cluster is 222 // initialized. 223 if daemon.configStore.AutoRestart && c.ShouldRestart() && !c.NetworkSettings.HasSwarmEndpoint { 224 mapLock.Lock() 225 restartContainers[c] = make(chan struct{}) 226 mapLock.Unlock() 227 } else if c.HostConfig != nil && c.HostConfig.AutoRemove { 228 mapLock.Lock() 229 removeContainers[c.ID] = c 230 mapLock.Unlock() 231 } 232 } 233 234 if c.RemovalInProgress { 235 // We probably crashed in the middle of a removal, reset 236 // the flag. 237 // 238 // We DO NOT remove the container here as we do not 239 // know if the user had requested for either the 240 // associated volumes, network links or both to also 241 // be removed. So we put the container in the "dead" 242 // state and leave further processing up to them. 243 logrus.Debugf("Resetting RemovalInProgress flag from %v", c.ID) 244 c.ResetRemovalInProgress() 245 c.SetDead() 246 c.ToDisk() 247 } 248 249 // if c.hostConfig.Links is nil (not just empty), then it is using the old sqlite links and needs to be migrated 250 if c.HostConfig != nil && c.HostConfig.Links == nil { 251 migrateLegacyLinks = true 252 } 253 }(c) 254 } 255 wg.Wait() 256 daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes) 257 if err != nil { 258 return fmt.Errorf("Error initializing network controller: %v", err) 259 } 260 261 // migrate any legacy links from sqlite 262 linkdbFile := filepath.Join(daemon.root, "linkgraph.db") 263 var legacyLinkDB *graphdb.Database 264 if migrateLegacyLinks { 265 legacyLinkDB, err = graphdb.NewSqliteConn(linkdbFile) 266 if err != nil { 267 return fmt.Errorf("error connecting to legacy link graph DB %s, container links may be lost: %v", linkdbFile, err) 268 } 269 defer legacyLinkDB.Close() 270 } 271 272 // Now that all the containers are registered, register the links 273 for _, c := range containers { 274 if migrateLegacyLinks { 275 if err := daemon.migrateLegacySqliteLinks(legacyLinkDB, c); err != nil { 276 return err 277 } 278 } 279 if err := daemon.registerLinks(c, c.HostConfig); err != nil { 280 logrus.Errorf("failed to register link for container %s: %v", c.ID, err) 281 } 282 } 283 284 group := sync.WaitGroup{} 285 for c, notifier := range restartContainers { 286 group.Add(1) 287 288 go func(c *container.Container, chNotify chan struct{}) { 289 defer group.Done() 290 291 logrus.Debugf("Starting container %s", c.ID) 292 293 // ignore errors here as this is a best effort to wait for children to be 294 // running before we try to start the container 295 children := daemon.children(c) 296 timeout := time.After(5 * time.Second) 297 for _, child := range children { 298 if notifier, exists := restartContainers[child]; exists { 299 select { 300 case <-notifier: 301 case <-timeout: 302 } 303 } 304 } 305 306 // Make sure networks are available before starting 307 daemon.waitForNetworks(c) 308 if err := daemon.containerStart(c, "", "", true); err != nil { 309 logrus.Errorf("Failed to start container %s: %s", c.ID, err) 310 } 311 close(chNotify) 312 }(c, notifier) 313 314 } 315 group.Wait() 316 317 removeGroup := sync.WaitGroup{} 318 for id := range removeContainers { 319 removeGroup.Add(1) 320 go func(cid string) { 321 if err := daemon.ContainerRm(cid, &types.ContainerRmConfig{ForceRemove: true, RemoveVolume: true}); err != nil { 322 logrus.Errorf("Failed to remove container %s: %s", cid, err) 323 } 324 removeGroup.Done() 325 }(id) 326 } 327 removeGroup.Wait() 328 329 // any containers that were started above would already have had this done, 330 // however we need to now prepare the mountpoints for the rest of the containers as well. 331 // This shouldn't cause any issue running on the containers that already had this run. 332 // This must be run after any containers with a restart policy so that containerized plugins 333 // can have a chance to be running before we try to initialize them. 334 for _, c := range containers { 335 // if the container has restart policy, do not 336 // prepare the mountpoints since it has been done on restarting. 337 // This is to speed up the daemon start when a restart container 338 // has a volume and the volume dirver is not available. 339 if _, ok := restartContainers[c]; ok { 340 continue 341 } else if _, ok := removeContainers[c.ID]; ok { 342 // container is automatically removed, skip it. 343 continue 344 } 345 346 group.Add(1) 347 go func(c *container.Container) { 348 defer group.Done() 349 if err := daemon.prepareMountPoints(c); err != nil { 350 logrus.Error(err) 351 } 352 }(c) 353 } 354 355 group.Wait() 356 357 logrus.Info("Loading containers: done.") 358 359 return nil 360 } 361 362 // RestartSwarmContainers restarts any autostart container which has a 363 // swarm endpoint. 364 func (daemon *Daemon) RestartSwarmContainers() { 365 group := sync.WaitGroup{} 366 for _, c := range daemon.List() { 367 if !c.IsRunning() && !c.IsPaused() { 368 // Autostart all the containers which has a 369 // swarm endpoint now that the cluster is 370 // initialized. 371 if daemon.configStore.AutoRestart && c.ShouldRestart() && c.NetworkSettings.HasSwarmEndpoint { 372 group.Add(1) 373 go func(c *container.Container) { 374 defer group.Done() 375 if err := daemon.containerStart(c, "", "", true); err != nil { 376 logrus.Error(err) 377 } 378 }(c) 379 } 380 } 381 382 } 383 group.Wait() 384 } 385 386 // waitForNetworks is used during daemon initialization when starting up containers 387 // It ensures that all of a container's networks are available before the daemon tries to start the container. 388 // In practice it just makes sure the discovery service is available for containers which use a network that require discovery. 389 func (daemon *Daemon) waitForNetworks(c *container.Container) { 390 if daemon.discoveryWatcher == nil { 391 return 392 } 393 // Make sure if the container has a network that requires discovery that the discovery service is available before starting 394 for netName := range c.NetworkSettings.Networks { 395 // If we get `ErrNoSuchNetwork` here, we can assume that it is due to discovery not being ready 396 // Most likely this is because the K/V store used for discovery is in a container and needs to be started 397 if _, err := daemon.netController.NetworkByName(netName); err != nil { 398 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 399 continue 400 } 401 // use a longish timeout here due to some slowdowns in libnetwork if the k/v store is on anything other than --net=host 402 // FIXME: why is this slow??? 403 logrus.Debugf("Container %s waiting for network to be ready", c.Name) 404 select { 405 case <-daemon.discoveryWatcher.ReadyCh(): 406 case <-time.After(60 * time.Second): 407 } 408 return 409 } 410 } 411 } 412 413 func (daemon *Daemon) children(c *container.Container) map[string]*container.Container { 414 return daemon.linkIndex.children(c) 415 } 416 417 // parents returns the names of the parent containers of the container 418 // with the given name. 419 func (daemon *Daemon) parents(c *container.Container) map[string]*container.Container { 420 return daemon.linkIndex.parents(c) 421 } 422 423 func (daemon *Daemon) registerLink(parent, child *container.Container, alias string) error { 424 fullName := path.Join(parent.Name, alias) 425 if err := daemon.nameIndex.Reserve(fullName, child.ID); err != nil { 426 if err == registrar.ErrNameReserved { 427 logrus.Warnf("error registering link for %s, to %s, as alias %s, ignoring: %v", parent.ID, child.ID, alias, err) 428 return nil 429 } 430 return err 431 } 432 daemon.linkIndex.link(parent, child, fullName) 433 return nil 434 } 435 436 // SetClusterProvider sets a component for querying the current cluster state. 437 func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) { 438 daemon.clusterProvider = clusterProvider 439 daemon.netController.SetClusterProvider(clusterProvider) 440 } 441 442 // IsSwarmCompatible verifies if the current daemon 443 // configuration is compatible with the swarm mode 444 func (daemon *Daemon) IsSwarmCompatible() error { 445 if daemon.configStore == nil { 446 return nil 447 } 448 return daemon.configStore.isSwarmCompatible() 449 } 450 451 // NewDaemon sets up everything for the daemon to be able to service 452 // requests from the webserver. 453 func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) { 454 setDefaultMtu(config) 455 456 // Ensure that we have a correct root key limit for launching containers. 457 if err := ModifyRootKeyLimit(); err != nil { 458 logrus.Warnf("unable to modify root key limit, number of containers could be limitied by this quota: %v", err) 459 } 460 461 // Ensure we have compatible and valid configuration options 462 if err := verifyDaemonSettings(config); err != nil { 463 return nil, err 464 } 465 466 // Do we have a disabled network? 467 config.DisableBridge = isBridgeNetworkDisabled(config) 468 469 // Verify the platform is supported as a daemon 470 if !platformSupported { 471 return nil, errSystemNotSupported 472 } 473 474 // Validate platform-specific requirements 475 if err := checkSystem(); err != nil { 476 return nil, err 477 } 478 479 // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event 480 // on Windows to dump Go routine stacks 481 setupDumpStackTrap(config.Root) 482 483 uidMaps, gidMaps, err := setupRemappedRoot(config) 484 if err != nil { 485 return nil, err 486 } 487 rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) 488 if err != nil { 489 return nil, err 490 } 491 492 // get the canonical path to the Docker root directory 493 var realRoot string 494 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 495 realRoot = config.Root 496 } else { 497 realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) 498 if err != nil { 499 return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 500 } 501 } 502 503 if err := setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { 504 return nil, err 505 } 506 507 if err := setupDaemonProcess(config); err != nil { 508 return nil, err 509 } 510 511 // set up the tmpDir to use a canonical path 512 tmp, err := tempDir(config.Root, rootUID, rootGID) 513 if err != nil { 514 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 515 } 516 realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) 517 if err != nil { 518 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 519 } 520 os.Setenv("TMPDIR", realTmp) 521 522 d := &Daemon{configStore: config} 523 // Ensure the daemon is properly shutdown if there is a failure during 524 // initialization 525 defer func() { 526 if err != nil { 527 if err := d.Shutdown(); err != nil { 528 logrus.Error(err) 529 } 530 } 531 }() 532 533 // Set the default isolation mode (only applicable on Windows) 534 if err := d.setDefaultIsolation(); err != nil { 535 return nil, fmt.Errorf("error setting default isolation mode: %v", err) 536 } 537 538 logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) 539 540 if err := configureMaxThreads(config); err != nil { 541 logrus.Warnf("Failed to configure golang's threads limit: %v", err) 542 } 543 544 installDefaultAppArmorProfile() 545 daemonRepo := filepath.Join(config.Root, "containers") 546 if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { 547 return nil, err 548 } 549 550 if runtime.GOOS == "windows" { 551 if err := idtools.MkdirAllAs(filepath.Join(config.Root, "credentialspecs"), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { 552 return nil, err 553 } 554 } 555 556 driverName := os.Getenv("DOCKER_DRIVER") 557 if driverName == "" { 558 driverName = config.GraphDriver 559 } 560 561 d.PluginStore = pluginstore.NewStore(config.Root) 562 563 d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{ 564 StorePath: config.Root, 565 MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), 566 GraphDriver: driverName, 567 GraphDriverOptions: config.GraphOptions, 568 UIDMaps: uidMaps, 569 GIDMaps: gidMaps, 570 PluginGetter: d.PluginStore, 571 }) 572 if err != nil { 573 return nil, err 574 } 575 576 graphDriver := d.layerStore.DriverName() 577 imageRoot := filepath.Join(config.Root, "image", graphDriver) 578 579 // Configure and validate the kernels security support 580 if err := configureKernelSecuritySupport(config, graphDriver); err != nil { 581 return nil, err 582 } 583 584 logrus.Debugf("Max Concurrent Downloads: %d", *config.MaxConcurrentDownloads) 585 d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, *config.MaxConcurrentDownloads) 586 logrus.Debugf("Max Concurrent Uploads: %d", *config.MaxConcurrentUploads) 587 d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads) 588 589 ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) 590 if err != nil { 591 return nil, err 592 } 593 594 d.imageStore, err = image.NewImageStore(ifs, d.layerStore) 595 if err != nil { 596 return nil, err 597 } 598 599 // Configure the volumes driver 600 volStore, err := d.configureVolumes(rootUID, rootGID) 601 if err != nil { 602 return nil, err 603 } 604 605 trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) 606 if err != nil { 607 return nil, err 608 } 609 610 trustDir := filepath.Join(config.Root, "trust") 611 612 if err := system.MkdirAll(trustDir, 0700); err != nil { 613 return nil, err 614 } 615 616 distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) 617 if err != nil { 618 return nil, err 619 } 620 621 eventsService := events.New() 622 623 referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json")) 624 if err != nil { 625 return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err) 626 } 627 628 migrationStart := time.Now() 629 if err := v1.Migrate(config.Root, graphDriver, d.layerStore, d.imageStore, referenceStore, distributionMetadataStore); err != nil { 630 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) 631 } 632 logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) 633 634 // Discovery is only enabled when the daemon is launched with an address to advertise. When 635 // initialized, the daemon is registered and we can store the discovery backend as its read-only 636 if err := d.initDiscovery(config); err != nil { 637 return nil, err 638 } 639 640 sysInfo := sysinfo.New(false) 641 // Check if Devices cgroup is mounted, it is hard requirement for container security, 642 // on Linux. 643 if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled { 644 return nil, fmt.Errorf("Devices cgroup isn't mounted") 645 } 646 647 d.ID = trustKey.PublicKey().KeyID() 648 d.repository = daemonRepo 649 d.containers = container.NewMemoryStore() 650 d.execCommands = exec.NewStore() 651 d.referenceStore = referenceStore 652 d.distributionMetadataStore = distributionMetadataStore 653 d.trustKey = trustKey 654 d.idIndex = truncindex.NewTruncIndex([]string{}) 655 d.statsCollector = d.newStatsCollector(1 * time.Second) 656 d.defaultLogConfig = containertypes.LogConfig{ 657 Type: config.LogConfig.Type, 658 Config: config.LogConfig.Config, 659 } 660 d.RegistryService = registryService 661 d.EventsService = eventsService 662 d.volumes = volStore 663 d.root = config.Root 664 d.uidMaps = uidMaps 665 d.gidMaps = gidMaps 666 d.seccompEnabled = sysInfo.Seccomp 667 668 d.nameIndex = registrar.NewRegistrar() 669 d.linkIndex = newLinkIndex() 670 d.containerdRemote = containerdRemote 671 672 go d.execCommandGC() 673 674 d.containerd, err = containerdRemote.Client(d) 675 if err != nil { 676 return nil, err 677 } 678 679 // Plugin system initialization should happen before restore. Do not change order. 680 if err := d.pluginInit(config, containerdRemote); err != nil { 681 return nil, err 682 } 683 684 if err := d.restore(); err != nil { 685 return nil, err 686 } 687 688 // FIXME: this method never returns an error 689 info, _ := d.SystemInfo() 690 691 engineVersion.WithValues( 692 dockerversion.Version, 693 dockerversion.GitCommit, 694 info.Architecture, 695 info.Driver, 696 info.KernelVersion, 697 info.OperatingSystem, 698 ).Set(1) 699 engineCpus.Set(float64(info.NCPU)) 700 engineMemory.Set(float64(info.MemTotal)) 701 702 return d, nil 703 } 704 705 func (daemon *Daemon) shutdownContainer(c *container.Container) error { 706 stopTimeout := c.StopTimeout() 707 // TODO(windows): Handle docker restart with paused containers 708 if c.IsPaused() { 709 // To terminate a process in freezer cgroup, we should send 710 // SIGTERM to this process then unfreeze it, and the process will 711 // force to terminate immediately. 712 logrus.Debugf("Found container %s is paused, sending SIGTERM before unpausing it", c.ID) 713 sig, ok := signal.SignalMap["TERM"] 714 if !ok { 715 return fmt.Errorf("System does not support SIGTERM") 716 } 717 if err := daemon.kill(c, int(sig)); err != nil { 718 return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err) 719 } 720 if err := daemon.containerUnpause(c); err != nil { 721 return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err) 722 } 723 if _, err := c.WaitStop(time.Duration(stopTimeout) * time.Second); err != nil { 724 logrus.Debugf("container %s failed to exit in %d second of SIGTERM, sending SIGKILL to force", c.ID, stopTimeout) 725 sig, ok := signal.SignalMap["KILL"] 726 if !ok { 727 return fmt.Errorf("System does not support SIGKILL") 728 } 729 if err := daemon.kill(c, int(sig)); err != nil { 730 logrus.Errorf("Failed to SIGKILL container %s", c.ID) 731 } 732 c.WaitStop(-1 * time.Second) 733 return err 734 } 735 } 736 // If container failed to exit in stopTimeout seconds of SIGTERM, then using the force 737 if err := daemon.containerStop(c, stopTimeout); err != nil { 738 return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err) 739 } 740 741 c.WaitStop(-1 * time.Second) 742 return nil 743 } 744 745 // ShutdownTimeout returns the shutdown timeout based on the max stopTimeout of the containers, 746 // and is limited by daemon's ShutdownTimeout. 747 func (daemon *Daemon) ShutdownTimeout() int { 748 // By default we use daemon's ShutdownTimeout. 749 shutdownTimeout := daemon.configStore.ShutdownTimeout 750 751 graceTimeout := 5 752 if daemon.containers != nil { 753 for _, c := range daemon.containers.List() { 754 if shutdownTimeout >= 0 { 755 stopTimeout := c.StopTimeout() 756 if stopTimeout < 0 { 757 shutdownTimeout = -1 758 } else { 759 if stopTimeout+graceTimeout > shutdownTimeout { 760 shutdownTimeout = stopTimeout + graceTimeout 761 } 762 } 763 } 764 } 765 } 766 return shutdownTimeout 767 } 768 769 // Shutdown stops the daemon. 770 func (daemon *Daemon) Shutdown() error { 771 daemon.shutdown = true 772 // Keep mounts and networking running on daemon shutdown if 773 // we are to keep containers running and restore them. 774 775 if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil { 776 // check if there are any running containers, if none we should do some cleanup 777 if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil { 778 return nil 779 } 780 } 781 782 if daemon.containers != nil { 783 logrus.Debugf("start clean shutdown of all containers with a %d seconds timeout...", daemon.configStore.ShutdownTimeout) 784 daemon.containers.ApplyAll(func(c *container.Container) { 785 if !c.IsRunning() { 786 return 787 } 788 logrus.Debugf("stopping %s", c.ID) 789 if err := daemon.shutdownContainer(c); err != nil { 790 logrus.Errorf("Stop container error: %v", err) 791 return 792 } 793 if mountid, err := daemon.layerStore.GetMountID(c.ID); err == nil { 794 daemon.cleanupMountsByID(mountid) 795 } 796 logrus.Debugf("container stopped %s", c.ID) 797 }) 798 } 799 800 // Shutdown plugins after containers. Dont change the order. 801 daemon.pluginShutdown() 802 803 // trigger libnetwork Stop only if it's initialized 804 if daemon.netController != nil { 805 daemon.netController.Stop() 806 } 807 808 if daemon.layerStore != nil { 809 if err := daemon.layerStore.Cleanup(); err != nil { 810 logrus.Errorf("Error during layer Store.Cleanup(): %v", err) 811 } 812 } 813 814 if err := daemon.cleanupMounts(); err != nil { 815 return err 816 } 817 818 return nil 819 } 820 821 // Mount sets container.BaseFS 822 // (is it not set coming in? why is it unset?) 823 func (daemon *Daemon) Mount(container *container.Container) error { 824 dir, err := container.RWLayer.Mount(container.GetMountLabel()) 825 if err != nil { 826 return err 827 } 828 logrus.Debugf("container mounted via layerStore: %v", dir) 829 830 if container.BaseFS != dir { 831 // The mount path reported by the graph driver should always be trusted on Windows, since the 832 // volume path for a given mounted layer may change over time. This should only be an error 833 // on non-Windows operating systems. 834 if container.BaseFS != "" && runtime.GOOS != "windows" { 835 daemon.Unmount(container) 836 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 837 daemon.GraphDriverName(), container.ID, container.BaseFS, dir) 838 } 839 } 840 container.BaseFS = dir // TODO: combine these fields 841 return nil 842 } 843 844 // Unmount unsets the container base filesystem 845 func (daemon *Daemon) Unmount(container *container.Container) error { 846 if err := container.RWLayer.Unmount(); err != nil { 847 logrus.Errorf("Error unmounting container %s: %s", container.ID, err) 848 return err 849 } 850 return nil 851 } 852 853 // V4Subnets returns the IPv4 subnets of networks that are managed by Docker. 854 func (daemon *Daemon) V4Subnets() []net.IPNet { 855 var subnets []net.IPNet 856 857 managedNetworks := daemon.netController.Networks() 858 859 for _, managedNetwork := range managedNetworks { 860 v4Infos, _ := managedNetwork.Info().IpamInfo() 861 for _, v4Info := range v4Infos { 862 if v4Info.IPAMData.Pool != nil { 863 subnets = append(subnets, *v4Info.IPAMData.Pool) 864 } 865 } 866 } 867 868 return subnets 869 } 870 871 // V6Subnets returns the IPv6 subnets of networks that are managed by Docker. 872 func (daemon *Daemon) V6Subnets() []net.IPNet { 873 var subnets []net.IPNet 874 875 managedNetworks := daemon.netController.Networks() 876 877 for _, managedNetwork := range managedNetworks { 878 _, v6Infos := managedNetwork.Info().IpamInfo() 879 for _, v6Info := range v6Infos { 880 if v6Info.IPAMData.Pool != nil { 881 subnets = append(subnets, *v6Info.IPAMData.Pool) 882 } 883 } 884 } 885 886 return subnets 887 } 888 889 func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) { 890 progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false) 891 operationCancelled := false 892 893 for prog := range progressChan { 894 if err := progressOutput.WriteProgress(prog); err != nil && !operationCancelled { 895 // don't log broken pipe errors as this is the normal case when a client aborts 896 if isBrokenPipe(err) { 897 logrus.Info("Pull session cancelled") 898 } else { 899 logrus.Errorf("error writing progress to client: %v", err) 900 } 901 cancelFunc() 902 operationCancelled = true 903 // Don't return, because we need to continue draining 904 // progressChan until it's closed to avoid a deadlock. 905 } 906 } 907 } 908 909 func isBrokenPipe(e error) bool { 910 if netErr, ok := e.(*net.OpError); ok { 911 e = netErr.Err 912 if sysErr, ok := netErr.Err.(*os.SyscallError); ok { 913 e = sysErr.Err 914 } 915 } 916 return e == syscall.EPIPE 917 } 918 919 // GraphDriverName returns the name of the graph driver used by the layer.Store 920 func (daemon *Daemon) GraphDriverName() string { 921 return daemon.layerStore.DriverName() 922 } 923 924 // GetUIDGIDMaps returns the current daemon's user namespace settings 925 // for the full uid and gid maps which will be applied to containers 926 // started in this instance. 927 func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) { 928 return daemon.uidMaps, daemon.gidMaps 929 } 930 931 // GetRemappedUIDGID returns the current daemon's uid and gid values 932 // if user namespaces are in use for this daemon instance. If not 933 // this function will return "real" root values of 0, 0. 934 func (daemon *Daemon) GetRemappedUIDGID() (int, int) { 935 uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) 936 return uid, gid 937 } 938 939 // tempDir returns the default directory to use for temporary files. 940 func tempDir(rootDir string, rootUID, rootGID int) (string, error) { 941 var tmpDir string 942 if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 943 tmpDir = filepath.Join(rootDir, "tmp") 944 } 945 return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) 946 } 947 948 func (daemon *Daemon) setupInitLayer(initPath string) error { 949 rootUID, rootGID := daemon.GetRemappedUIDGID() 950 return setupInitLayer(initPath, rootUID, rootGID) 951 } 952 953 func setDefaultMtu(config *Config) { 954 // do nothing if the config does not have the default 0 value. 955 if config.Mtu != 0 { 956 return 957 } 958 config.Mtu = defaultNetworkMtu 959 } 960 961 func (daemon *Daemon) configureVolumes(rootUID, rootGID int) (*store.VolumeStore, error) { 962 volumesDriver, err := local.New(daemon.configStore.Root, rootUID, rootGID) 963 if err != nil { 964 return nil, err 965 } 966 967 volumedrivers.RegisterPluginGetter(daemon.PluginStore) 968 969 if !volumedrivers.Register(volumesDriver, volumesDriver.Name()) { 970 return nil, fmt.Errorf("local volume driver could not be registered") 971 } 972 return store.New(daemon.configStore.Root) 973 } 974 975 // IsShuttingDown tells whether the daemon is shutting down or not 976 func (daemon *Daemon) IsShuttingDown() bool { 977 return daemon.shutdown 978 } 979 980 // initDiscovery initializes the discovery watcher for this daemon. 981 func (daemon *Daemon) initDiscovery(config *Config) error { 982 advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise) 983 if err != nil { 984 if err == errDiscoveryDisabled { 985 return nil 986 } 987 return err 988 } 989 990 config.ClusterAdvertise = advertise 991 discoveryWatcher, err := initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts) 992 if err != nil { 993 return fmt.Errorf("discovery initialization failed (%v)", err) 994 } 995 996 daemon.discoveryWatcher = discoveryWatcher 997 return nil 998 } 999 1000 // Reload reads configuration changes and modifies the 1001 // daemon according to those changes. 1002 // These are the settings that Reload changes: 1003 // - Daemon labels. 1004 // - Daemon debug log level. 1005 // - Daemon insecure registries. 1006 // - Daemon max concurrent downloads 1007 // - Daemon max concurrent uploads 1008 // - Cluster discovery (reconfigure and restart). 1009 // - Daemon live restore 1010 // - Daemon shutdown timeout (in seconds). 1011 func (daemon *Daemon) Reload(config *Config) (err error) { 1012 1013 daemon.configStore.reloadLock.Lock() 1014 1015 attributes := daemon.platformReload(config) 1016 1017 defer func() { 1018 // we're unlocking here, because 1019 // LogDaemonEventWithAttributes() -> SystemInfo() -> GetAllRuntimes() 1020 // holds that lock too. 1021 daemon.configStore.reloadLock.Unlock() 1022 if err == nil { 1023 daemon.LogDaemonEventWithAttributes("reload", attributes) 1024 } 1025 }() 1026 1027 if err := daemon.reloadClusterDiscovery(config); err != nil { 1028 return err 1029 } 1030 1031 if config.IsValueSet("labels") { 1032 daemon.configStore.Labels = config.Labels 1033 } 1034 if config.IsValueSet("debug") { 1035 daemon.configStore.Debug = config.Debug 1036 } 1037 if config.IsValueSet("insecure-registries") { 1038 daemon.configStore.InsecureRegistries = config.InsecureRegistries 1039 if err := daemon.RegistryService.LoadInsecureRegistries(config.InsecureRegistries); err != nil { 1040 return err 1041 } 1042 } 1043 if config.IsValueSet("live-restore") { 1044 daemon.configStore.LiveRestoreEnabled = config.LiveRestoreEnabled 1045 if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil { 1046 return err 1047 } 1048 } 1049 1050 // If no value is set for max-concurrent-downloads we assume it is the default value 1051 // We always "reset" as the cost is lightweight and easy to maintain. 1052 if config.IsValueSet("max-concurrent-downloads") && config.MaxConcurrentDownloads != nil { 1053 *daemon.configStore.MaxConcurrentDownloads = *config.MaxConcurrentDownloads 1054 } else { 1055 maxConcurrentDownloads := defaultMaxConcurrentDownloads 1056 daemon.configStore.MaxConcurrentDownloads = &maxConcurrentDownloads 1057 } 1058 logrus.Debugf("Reset Max Concurrent Downloads: %d", *daemon.configStore.MaxConcurrentDownloads) 1059 if daemon.downloadManager != nil { 1060 daemon.downloadManager.SetConcurrency(*daemon.configStore.MaxConcurrentDownloads) 1061 } 1062 1063 // If no value is set for max-concurrent-upload we assume it is the default value 1064 // We always "reset" as the cost is lightweight and easy to maintain. 1065 if config.IsValueSet("max-concurrent-uploads") && config.MaxConcurrentUploads != nil { 1066 *daemon.configStore.MaxConcurrentUploads = *config.MaxConcurrentUploads 1067 } else { 1068 maxConcurrentUploads := defaultMaxConcurrentUploads 1069 daemon.configStore.MaxConcurrentUploads = &maxConcurrentUploads 1070 } 1071 logrus.Debugf("Reset Max Concurrent Uploads: %d", *daemon.configStore.MaxConcurrentUploads) 1072 if daemon.uploadManager != nil { 1073 daemon.uploadManager.SetConcurrency(*daemon.configStore.MaxConcurrentUploads) 1074 } 1075 1076 if config.IsValueSet("shutdown-timeout") { 1077 daemon.configStore.ShutdownTimeout = config.ShutdownTimeout 1078 logrus.Debugf("Reset Shutdown Timeout: %d", daemon.configStore.ShutdownTimeout) 1079 } 1080 1081 // We emit daemon reload event here with updatable configurations 1082 attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug) 1083 attributes["live-restore"] = fmt.Sprintf("%t", daemon.configStore.LiveRestoreEnabled) 1084 1085 if daemon.configStore.InsecureRegistries != nil { 1086 insecureRegistries, err := json.Marshal(daemon.configStore.InsecureRegistries) 1087 if err != nil { 1088 return err 1089 } 1090 attributes["insecure-registries"] = string(insecureRegistries) 1091 } else { 1092 attributes["insecure-registries"] = "[]" 1093 } 1094 1095 attributes["cluster-store"] = daemon.configStore.ClusterStore 1096 if daemon.configStore.ClusterOpts != nil { 1097 opts, err := json.Marshal(daemon.configStore.ClusterOpts) 1098 if err != nil { 1099 return err 1100 } 1101 attributes["cluster-store-opts"] = string(opts) 1102 } else { 1103 attributes["cluster-store-opts"] = "{}" 1104 } 1105 attributes["cluster-advertise"] = daemon.configStore.ClusterAdvertise 1106 1107 if daemon.configStore.Labels != nil { 1108 labels, err := json.Marshal(daemon.configStore.Labels) 1109 if err != nil { 1110 return err 1111 } 1112 attributes["labels"] = string(labels) 1113 } else { 1114 attributes["labels"] = "[]" 1115 } 1116 1117 attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads) 1118 attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads) 1119 attributes["shutdown-timeout"] = fmt.Sprintf("%d", daemon.configStore.ShutdownTimeout) 1120 1121 return nil 1122 } 1123 1124 func (daemon *Daemon) reloadClusterDiscovery(config *Config) error { 1125 var err error 1126 newAdvertise := daemon.configStore.ClusterAdvertise 1127 newClusterStore := daemon.configStore.ClusterStore 1128 if config.IsValueSet("cluster-advertise") { 1129 if config.IsValueSet("cluster-store") { 1130 newClusterStore = config.ClusterStore 1131 } 1132 newAdvertise, err = parseClusterAdvertiseSettings(newClusterStore, config.ClusterAdvertise) 1133 if err != nil && err != errDiscoveryDisabled { 1134 return err 1135 } 1136 } 1137 1138 if daemon.clusterProvider != nil { 1139 if err := config.isSwarmCompatible(); err != nil { 1140 return err 1141 } 1142 } 1143 1144 // check discovery modifications 1145 if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) { 1146 return nil 1147 } 1148 1149 // enable discovery for the first time if it was not previously enabled 1150 if daemon.discoveryWatcher == nil { 1151 discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts) 1152 if err != nil { 1153 return fmt.Errorf("discovery initialization failed (%v)", err) 1154 } 1155 daemon.discoveryWatcher = discoveryWatcher 1156 } else { 1157 if err == errDiscoveryDisabled { 1158 // disable discovery if it was previously enabled and it's disabled now 1159 daemon.discoveryWatcher.Stop() 1160 } else { 1161 // reload discovery 1162 if err = daemon.discoveryWatcher.Reload(config.ClusterStore, newAdvertise, config.ClusterOpts); err != nil { 1163 return err 1164 } 1165 } 1166 } 1167 1168 daemon.configStore.ClusterStore = newClusterStore 1169 daemon.configStore.ClusterOpts = config.ClusterOpts 1170 daemon.configStore.ClusterAdvertise = newAdvertise 1171 1172 if daemon.netController == nil { 1173 return nil 1174 } 1175 netOptions, err := daemon.networkOptions(daemon.configStore, daemon.PluginStore, nil) 1176 if err != nil { 1177 logrus.WithError(err).Warnf("failed to get options with network controller") 1178 return nil 1179 } 1180 err = daemon.netController.ReloadConfiguration(netOptions...) 1181 if err != nil { 1182 logrus.Warnf("Failed to reload configuration with network controller: %v", err) 1183 } 1184 1185 return nil 1186 } 1187 1188 func isBridgeNetworkDisabled(config *Config) bool { 1189 return config.bridgeConfig.Iface == disableNetworkBridge 1190 } 1191 1192 func (daemon *Daemon) networkOptions(dconfig *Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) { 1193 options := []nwconfig.Option{} 1194 if dconfig == nil { 1195 return options, nil 1196 } 1197 1198 options = append(options, nwconfig.OptionDataDir(dconfig.Root)) 1199 options = append(options, nwconfig.OptionExecRoot(dconfig.GetExecRoot())) 1200 1201 dd := runconfig.DefaultDaemonNetworkMode() 1202 dn := runconfig.DefaultDaemonNetworkMode().NetworkName() 1203 options = append(options, nwconfig.OptionDefaultDriver(string(dd))) 1204 options = append(options, nwconfig.OptionDefaultNetwork(dn)) 1205 1206 if strings.TrimSpace(dconfig.ClusterStore) != "" { 1207 kv := strings.Split(dconfig.ClusterStore, "://") 1208 if len(kv) != 2 { 1209 return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL") 1210 } 1211 options = append(options, nwconfig.OptionKVProvider(kv[0])) 1212 options = append(options, nwconfig.OptionKVProviderURL(kv[1])) 1213 } 1214 if len(dconfig.ClusterOpts) > 0 { 1215 options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts)) 1216 } 1217 1218 if daemon.discoveryWatcher != nil { 1219 options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher)) 1220 } 1221 1222 if dconfig.ClusterAdvertise != "" { 1223 options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise)) 1224 } 1225 1226 options = append(options, nwconfig.OptionLabels(dconfig.Labels)) 1227 options = append(options, driverOptions(dconfig)...) 1228 1229 if daemon.configStore != nil && daemon.configStore.LiveRestoreEnabled && len(activeSandboxes) != 0 { 1230 options = append(options, nwconfig.OptionActiveSandboxes(activeSandboxes)) 1231 } 1232 1233 if pg != nil { 1234 options = append(options, nwconfig.OptionPluginGetter(pg)) 1235 } 1236 1237 return options, nil 1238 } 1239 1240 func copyBlkioEntry(entries []*containerd.BlkioStatsEntry) []types.BlkioStatEntry { 1241 out := make([]types.BlkioStatEntry, len(entries)) 1242 for i, re := range entries { 1243 out[i] = types.BlkioStatEntry{ 1244 Major: re.Major, 1245 Minor: re.Minor, 1246 Op: re.Op, 1247 Value: re.Value, 1248 } 1249 } 1250 return out 1251 } 1252 1253 // GetCluster returns the cluster 1254 func (daemon *Daemon) GetCluster() Cluster { 1255 return daemon.cluster 1256 } 1257 1258 // SetCluster sets the cluster 1259 func (daemon *Daemon) SetCluster(cluster Cluster) { 1260 daemon.cluster = cluster 1261 }