github.com/afbjorklund/moby@v20.10.5+incompatible/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 // import "github.com/docker/docker/daemon" 7 8 import ( 9 "context" 10 "fmt" 11 "io/ioutil" 12 "net" 13 "net/url" 14 "os" 15 "path" 16 "path/filepath" 17 "runtime" 18 "strings" 19 "sync" 20 "time" 21 22 "github.com/docker/docker/pkg/fileutils" 23 "go.etcd.io/bbolt" 24 "google.golang.org/grpc" 25 "google.golang.org/grpc/backoff" 26 27 "github.com/containerd/containerd" 28 "github.com/containerd/containerd/defaults" 29 "github.com/containerd/containerd/pkg/dialer" 30 "github.com/containerd/containerd/remotes/docker" 31 "github.com/containerd/containerd/sys" 32 "github.com/docker/docker/api/types" 33 containertypes "github.com/docker/docker/api/types/container" 34 "github.com/docker/docker/api/types/swarm" 35 "github.com/docker/docker/builder" 36 "github.com/docker/docker/container" 37 "github.com/docker/docker/daemon/config" 38 "github.com/docker/docker/daemon/discovery" 39 "github.com/docker/docker/daemon/events" 40 "github.com/docker/docker/daemon/exec" 41 "github.com/docker/docker/daemon/images" 42 "github.com/docker/docker/daemon/logger" 43 "github.com/docker/docker/daemon/network" 44 "github.com/docker/docker/errdefs" 45 bkconfig "github.com/moby/buildkit/cmd/buildkitd/config" 46 "github.com/moby/buildkit/util/resolver" 47 "github.com/sirupsen/logrus" 48 49 // register graph drivers 50 _ "github.com/docker/docker/daemon/graphdriver/register" 51 "github.com/docker/docker/daemon/stats" 52 dmetadata "github.com/docker/docker/distribution/metadata" 53 "github.com/docker/docker/dockerversion" 54 "github.com/docker/docker/image" 55 "github.com/docker/docker/layer" 56 "github.com/docker/docker/libcontainerd" 57 libcontainerdtypes "github.com/docker/docker/libcontainerd/types" 58 "github.com/docker/docker/pkg/idtools" 59 "github.com/docker/docker/pkg/plugingetter" 60 "github.com/docker/docker/pkg/system" 61 "github.com/docker/docker/pkg/truncindex" 62 "github.com/docker/docker/plugin" 63 pluginexec "github.com/docker/docker/plugin/executor/containerd" 64 refstore "github.com/docker/docker/reference" 65 "github.com/docker/docker/registry" 66 "github.com/docker/docker/runconfig" 67 volumesservice "github.com/docker/docker/volume/service" 68 "github.com/docker/libnetwork" 69 "github.com/docker/libnetwork/cluster" 70 nwconfig "github.com/docker/libnetwork/config" 71 "github.com/moby/locker" 72 "github.com/pkg/errors" 73 "golang.org/x/sync/semaphore" 74 ) 75 76 // ContainersNamespace is the name of the namespace used for users containers 77 const ( 78 ContainersNamespace = "moby" 79 ) 80 81 var ( 82 errSystemNotSupported = errors.New("the Docker daemon is not supported on this platform") 83 ) 84 85 // Daemon holds information about the Docker daemon. 86 type Daemon struct { 87 ID string 88 repository string 89 containers container.Store 90 containersReplica container.ViewDB 91 execCommands *exec.Store 92 imageService *images.ImageService 93 idIndex *truncindex.TruncIndex 94 configStore *config.Config 95 statsCollector *stats.Collector 96 defaultLogConfig containertypes.LogConfig 97 RegistryService registry.Service 98 EventsService *events.Events 99 netController libnetwork.NetworkController 100 volumes *volumesservice.VolumesService 101 discoveryWatcher discovery.Reloader 102 root string 103 seccompEnabled bool 104 apparmorEnabled bool 105 shutdown bool 106 idMapping *idtools.IdentityMapping 107 // TODO: move graphDrivers field to an InfoService 108 graphDrivers map[string]string // By operating system 109 110 PluginStore *plugin.Store // todo: remove 111 pluginManager *plugin.Manager 112 linkIndex *linkIndex 113 containerdCli *containerd.Client 114 containerd libcontainerdtypes.Client 115 defaultIsolation containertypes.Isolation // Default isolation mode on Windows 116 clusterProvider cluster.Provider 117 cluster Cluster 118 genericResources []swarm.GenericResource 119 metricsPluginListener net.Listener 120 121 machineMemory uint64 122 123 seccompProfile []byte 124 seccompProfilePath string 125 126 diskUsageRunning int32 127 pruneRunning int32 128 hosts map[string]bool // hosts stores the addresses the daemon is listening on 129 startupDone chan struct{} 130 131 attachmentStore network.AttachmentStore 132 attachableNetworkLock *locker.Locker 133 134 // This is used for Windows which doesn't currently support running on containerd 135 // It stores metadata for the content store (used for manifest caching) 136 // This needs to be closed on daemon exit 137 mdDB *bbolt.DB 138 } 139 140 // StoreHosts stores the addresses the daemon is listening on 141 func (daemon *Daemon) StoreHosts(hosts []string) { 142 if daemon.hosts == nil { 143 daemon.hosts = make(map[string]bool) 144 } 145 for _, h := range hosts { 146 daemon.hosts[h] = true 147 } 148 } 149 150 // HasExperimental returns whether the experimental features of the daemon are enabled or not 151 func (daemon *Daemon) HasExperimental() bool { 152 return daemon.configStore != nil && daemon.configStore.Experimental 153 } 154 155 // Features returns the features map from configStore 156 func (daemon *Daemon) Features() *map[string]bool { 157 return &daemon.configStore.Features 158 } 159 160 // RegistryHosts returns registry configuration in containerd resolvers format 161 func (daemon *Daemon) RegistryHosts() docker.RegistryHosts { 162 var ( 163 registryKey = "docker.io" 164 mirrors = make([]string, len(daemon.configStore.Mirrors)) 165 m = map[string]bkconfig.RegistryConfig{} 166 ) 167 // must trim "https://" or "http://" prefix 168 for i, v := range daemon.configStore.Mirrors { 169 if uri, err := url.Parse(v); err == nil { 170 v = uri.Host 171 } 172 mirrors[i] = v 173 } 174 // set mirrors for default registry 175 m[registryKey] = bkconfig.RegistryConfig{Mirrors: mirrors} 176 177 for _, v := range daemon.configStore.InsecureRegistries { 178 u, err := url.Parse(v) 179 c := bkconfig.RegistryConfig{} 180 if err == nil { 181 v = u.Host 182 t := true 183 if u.Scheme == "http" { 184 c.PlainHTTP = &t 185 } else { 186 c.Insecure = &t 187 } 188 } 189 m[v] = c 190 } 191 192 for k, v := range m { 193 if d, err := registry.HostCertsDir(k); err == nil { 194 v.TLSConfigDir = []string{d} 195 m[k] = v 196 } 197 } 198 199 certsDir := registry.CertsDir() 200 if fis, err := ioutil.ReadDir(certsDir); err == nil { 201 for _, fi := range fis { 202 if _, ok := m[fi.Name()]; !ok { 203 m[fi.Name()] = bkconfig.RegistryConfig{ 204 TLSConfigDir: []string{filepath.Join(certsDir, fi.Name())}, 205 } 206 } 207 } 208 } 209 210 return resolver.NewRegistryConfig(m) 211 } 212 213 func (daemon *Daemon) restore() error { 214 var mapLock sync.Mutex 215 containers := make(map[string]*container.Container) 216 217 logrus.Info("Loading containers: start.") 218 219 dir, err := ioutil.ReadDir(daemon.repository) 220 if err != nil { 221 return err 222 } 223 224 // parallelLimit is the maximum number of parallel startup jobs that we 225 // allow (this is the limited used for all startup semaphores). The multipler 226 // (128) was chosen after some fairly significant benchmarking -- don't change 227 // it unless you've tested it significantly (this value is adjusted if 228 // RLIMIT_NOFILE is small to avoid EMFILE). 229 parallelLimit := adjustParallelLimit(len(dir), 128*runtime.NumCPU()) 230 231 // Re-used for all parallel startup jobs. 232 var group sync.WaitGroup 233 sem := semaphore.NewWeighted(int64(parallelLimit)) 234 235 for _, v := range dir { 236 group.Add(1) 237 go func(id string) { 238 defer group.Done() 239 _ = sem.Acquire(context.Background(), 1) 240 defer sem.Release(1) 241 242 log := logrus.WithField("container", id) 243 244 c, err := daemon.load(id) 245 if err != nil { 246 log.WithError(err).Error("failed to load container") 247 return 248 } 249 if !system.IsOSSupported(c.OS) { 250 log.Errorf("failed to load container: %s (%q)", system.ErrNotSupportedOperatingSystem, c.OS) 251 return 252 } 253 // Ignore the container if it does not support the current driver being used by the graph 254 currentDriverForContainerOS := daemon.graphDrivers[c.OS] 255 if (c.Driver == "" && currentDriverForContainerOS == "aufs") || c.Driver == currentDriverForContainerOS { 256 rwlayer, err := daemon.imageService.GetLayerByID(c.ID, c.OS) 257 if err != nil { 258 log.WithError(err).Error("failed to load container mount") 259 return 260 } 261 c.RWLayer = rwlayer 262 log.WithFields(logrus.Fields{ 263 "running": c.IsRunning(), 264 "paused": c.IsPaused(), 265 }).Debug("loaded container") 266 267 mapLock.Lock() 268 containers[c.ID] = c 269 mapLock.Unlock() 270 } else { 271 log.Debugf("cannot load container because it was created with another storage driver") 272 } 273 }(v.Name()) 274 } 275 group.Wait() 276 277 removeContainers := make(map[string]*container.Container) 278 restartContainers := make(map[*container.Container]chan struct{}) 279 activeSandboxes := make(map[string]interface{}) 280 281 for _, c := range containers { 282 group.Add(1) 283 go func(c *container.Container) { 284 defer group.Done() 285 _ = sem.Acquire(context.Background(), 1) 286 defer sem.Release(1) 287 288 log := logrus.WithField("container", c.ID) 289 290 if err := daemon.registerName(c); err != nil { 291 log.WithError(err).Errorf("failed to register container name: %s", c.Name) 292 mapLock.Lock() 293 delete(containers, c.ID) 294 mapLock.Unlock() 295 return 296 } 297 if err := daemon.Register(c); err != nil { 298 log.WithError(err).Error("failed to register container") 299 mapLock.Lock() 300 delete(containers, c.ID) 301 mapLock.Unlock() 302 return 303 } 304 305 // The LogConfig.Type is empty if the container was created before docker 1.12 with default log driver. 306 // We should rewrite it to use the daemon defaults. 307 // Fixes https://github.com/docker/docker/issues/22536 308 if c.HostConfig.LogConfig.Type == "" { 309 if err := daemon.mergeAndVerifyLogConfig(&c.HostConfig.LogConfig); err != nil { 310 log.WithError(err).Error("failed to verify log config for container") 311 } 312 } 313 }(c) 314 } 315 group.Wait() 316 317 for _, c := range containers { 318 group.Add(1) 319 go func(c *container.Container) { 320 defer group.Done() 321 _ = sem.Acquire(context.Background(), 1) 322 defer sem.Release(1) 323 324 log := logrus.WithField("container", c.ID) 325 326 daemon.backportMountSpec(c) 327 if err := daemon.checkpointAndSave(c); err != nil { 328 log.WithError(err).Error("error saving backported mountspec to disk") 329 } 330 331 daemon.setStateCounter(c) 332 333 logger := func(c *container.Container) *logrus.Entry { 334 return log.WithFields(logrus.Fields{ 335 "running": c.IsRunning(), 336 "paused": c.IsPaused(), 337 "restarting": c.IsRestarting(), 338 }) 339 } 340 341 logger(c).Debug("restoring container") 342 343 var ( 344 err error 345 alive bool 346 ec uint32 347 exitedAt time.Time 348 process libcontainerdtypes.Process 349 ) 350 351 alive, _, process, err = daemon.containerd.Restore(context.Background(), c.ID, c.InitializeStdio) 352 if err != nil && !errdefs.IsNotFound(err) { 353 logger(c).WithError(err).Error("failed to restore container with containerd") 354 return 355 } 356 logger(c).Debugf("alive: %v", alive) 357 if !alive { 358 // If process is not nil, cleanup dead container from containerd. 359 // If process is nil then the above `containerd.Restore` returned an errdefs.NotFoundError, 360 // and docker's view of the container state will be updated accorrdingly via SetStopped further down. 361 if process != nil { 362 logger(c).Debug("cleaning up dead container process") 363 ec, exitedAt, err = process.Delete(context.Background()) 364 if err != nil && !errdefs.IsNotFound(err) { 365 logger(c).WithError(err).Error("failed to delete container from containerd") 366 return 367 } 368 } 369 } else if !daemon.configStore.LiveRestoreEnabled { 370 logger(c).Debug("shutting down container considered alive by containerd") 371 if err := daemon.shutdownContainer(c); err != nil && !errdefs.IsNotFound(err) { 372 log.WithError(err).Error("error shutting down container") 373 return 374 } 375 c.ResetRestartManager(false) 376 } 377 378 if c.IsRunning() || c.IsPaused() { 379 logger(c).Debug("syncing container on disk state with real state") 380 381 c.RestartManager().Cancel() // manually start containers because some need to wait for swarm networking 382 383 if c.IsPaused() && alive { 384 s, err := daemon.containerd.Status(context.Background(), c.ID) 385 if err != nil { 386 logger(c).WithError(err).Error("failed to get container status") 387 } else { 388 logger(c).WithField("state", s).Info("restored container paused") 389 switch s { 390 case containerd.Paused, containerd.Pausing: 391 // nothing to do 392 case containerd.Stopped: 393 alive = false 394 case containerd.Unknown: 395 log.Error("unknown status for paused container during restore") 396 default: 397 // running 398 c.Lock() 399 c.Paused = false 400 daemon.setStateCounter(c) 401 if err := c.CheckpointTo(daemon.containersReplica); err != nil { 402 log.WithError(err).Error("failed to update paused container state") 403 } 404 c.Unlock() 405 } 406 } 407 } 408 409 if !alive { 410 logger(c).Debug("setting stopped state") 411 c.Lock() 412 c.SetStopped(&container.ExitStatus{ExitCode: int(ec), ExitedAt: exitedAt}) 413 daemon.Cleanup(c) 414 if err := c.CheckpointTo(daemon.containersReplica); err != nil { 415 log.WithError(err).Error("failed to update stopped container state") 416 } 417 c.Unlock() 418 logger(c).Debug("set stopped state") 419 } 420 421 // we call Mount and then Unmount to get BaseFs of the container 422 if err := daemon.Mount(c); err != nil { 423 // The mount is unlikely to fail. However, in case mount fails 424 // the container should be allowed to restore here. Some functionalities 425 // (like docker exec -u user) might be missing but container is able to be 426 // stopped/restarted/removed. 427 // See #29365 for related information. 428 // The error is only logged here. 429 logger(c).WithError(err).Warn("failed to mount container to get BaseFs path") 430 } else { 431 if err := daemon.Unmount(c); err != nil { 432 logger(c).WithError(err).Warn("failed to umount container to get BaseFs path") 433 } 434 } 435 436 c.ResetRestartManager(false) 437 if !c.HostConfig.NetworkMode.IsContainer() && c.IsRunning() { 438 options, err := daemon.buildSandboxOptions(c) 439 if err != nil { 440 logger(c).WithError(err).Warn("failed to build sandbox option to restore container") 441 } 442 mapLock.Lock() 443 activeSandboxes[c.NetworkSettings.SandboxID] = options 444 mapLock.Unlock() 445 } 446 } 447 448 // get list of containers we need to restart 449 450 // Do not autostart containers which 451 // has endpoints in a swarm scope 452 // network yet since the cluster is 453 // not initialized yet. We will start 454 // it after the cluster is 455 // initialized. 456 if daemon.configStore.AutoRestart && c.ShouldRestart() && !c.NetworkSettings.HasSwarmEndpoint && c.HasBeenStartedBefore { 457 mapLock.Lock() 458 restartContainers[c] = make(chan struct{}) 459 mapLock.Unlock() 460 } else if c.HostConfig != nil && c.HostConfig.AutoRemove { 461 mapLock.Lock() 462 removeContainers[c.ID] = c 463 mapLock.Unlock() 464 } 465 466 c.Lock() 467 if c.RemovalInProgress { 468 // We probably crashed in the middle of a removal, reset 469 // the flag. 470 // 471 // We DO NOT remove the container here as we do not 472 // know if the user had requested for either the 473 // associated volumes, network links or both to also 474 // be removed. So we put the container in the "dead" 475 // state and leave further processing up to them. 476 c.RemovalInProgress = false 477 c.Dead = true 478 if err := c.CheckpointTo(daemon.containersReplica); err != nil { 479 log.WithError(err).Error("failed to update RemovalInProgress container state") 480 } else { 481 log.Debugf("reset RemovalInProgress state for container") 482 } 483 } 484 c.Unlock() 485 logger(c).Debug("done restoring container") 486 }(c) 487 } 488 group.Wait() 489 490 daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes) 491 if err != nil { 492 return fmt.Errorf("Error initializing network controller: %v", err) 493 } 494 495 // Now that all the containers are registered, register the links 496 for _, c := range containers { 497 group.Add(1) 498 go func(c *container.Container) { 499 _ = sem.Acquire(context.Background(), 1) 500 501 if err := daemon.registerLinks(c, c.HostConfig); err != nil { 502 logrus.WithField("container", c.ID).WithError(err).Error("failed to register link for container") 503 } 504 505 sem.Release(1) 506 group.Done() 507 }(c) 508 } 509 group.Wait() 510 511 for c, notifier := range restartContainers { 512 group.Add(1) 513 go func(c *container.Container, chNotify chan struct{}) { 514 _ = sem.Acquire(context.Background(), 1) 515 516 log := logrus.WithField("container", c.ID) 517 518 log.Debug("starting container") 519 520 // ignore errors here as this is a best effort to wait for children to be 521 // running before we try to start the container 522 children := daemon.children(c) 523 timeout := time.NewTimer(5 * time.Second) 524 defer timeout.Stop() 525 526 for _, child := range children { 527 if notifier, exists := restartContainers[child]; exists { 528 select { 529 case <-notifier: 530 case <-timeout.C: 531 } 532 } 533 } 534 535 // Make sure networks are available before starting 536 daemon.waitForNetworks(c) 537 if err := daemon.containerStart(c, "", "", true); err != nil { 538 log.WithError(err).Error("failed to start container") 539 } 540 close(chNotify) 541 542 sem.Release(1) 543 group.Done() 544 }(c, notifier) 545 } 546 group.Wait() 547 548 for id := range removeContainers { 549 group.Add(1) 550 go func(cid string) { 551 _ = sem.Acquire(context.Background(), 1) 552 553 if err := daemon.ContainerRm(cid, &types.ContainerRmConfig{ForceRemove: true, RemoveVolume: true}); err != nil { 554 logrus.WithField("container", cid).WithError(err).Error("failed to remove container") 555 } 556 557 sem.Release(1) 558 group.Done() 559 }(id) 560 } 561 group.Wait() 562 563 // any containers that were started above would already have had this done, 564 // however we need to now prepare the mountpoints for the rest of the containers as well. 565 // This shouldn't cause any issue running on the containers that already had this run. 566 // This must be run after any containers with a restart policy so that containerized plugins 567 // can have a chance to be running before we try to initialize them. 568 for _, c := range containers { 569 // if the container has restart policy, do not 570 // prepare the mountpoints since it has been done on restarting. 571 // This is to speed up the daemon start when a restart container 572 // has a volume and the volume driver is not available. 573 if _, ok := restartContainers[c]; ok { 574 continue 575 } else if _, ok := removeContainers[c.ID]; ok { 576 // container is automatically removed, skip it. 577 continue 578 } 579 580 group.Add(1) 581 go func(c *container.Container) { 582 _ = sem.Acquire(context.Background(), 1) 583 584 if err := daemon.prepareMountPoints(c); err != nil { 585 logrus.WithField("container", c.ID).WithError(err).Error("failed to prepare mountpoints for container") 586 } 587 588 sem.Release(1) 589 group.Done() 590 }(c) 591 } 592 group.Wait() 593 594 logrus.Info("Loading containers: done.") 595 596 return nil 597 } 598 599 // RestartSwarmContainers restarts any autostart container which has a 600 // swarm endpoint. 601 func (daemon *Daemon) RestartSwarmContainers() { 602 ctx := context.Background() 603 604 // parallelLimit is the maximum number of parallel startup jobs that we 605 // allow (this is the limited used for all startup semaphores). The multipler 606 // (128) was chosen after some fairly significant benchmarking -- don't change 607 // it unless you've tested it significantly (this value is adjusted if 608 // RLIMIT_NOFILE is small to avoid EMFILE). 609 parallelLimit := adjustParallelLimit(len(daemon.List()), 128*runtime.NumCPU()) 610 611 var group sync.WaitGroup 612 sem := semaphore.NewWeighted(int64(parallelLimit)) 613 614 for _, c := range daemon.List() { 615 if !c.IsRunning() && !c.IsPaused() { 616 // Autostart all the containers which has a 617 // swarm endpoint now that the cluster is 618 // initialized. 619 if daemon.configStore.AutoRestart && c.ShouldRestart() && c.NetworkSettings.HasSwarmEndpoint && c.HasBeenStartedBefore { 620 group.Add(1) 621 go func(c *container.Container) { 622 if err := sem.Acquire(ctx, 1); err != nil { 623 // ctx is done. 624 group.Done() 625 return 626 } 627 628 if err := daemon.containerStart(c, "", "", true); err != nil { 629 logrus.WithField("container", c.ID).WithError(err).Error("failed to start swarm container") 630 } 631 632 sem.Release(1) 633 group.Done() 634 }(c) 635 } 636 } 637 } 638 group.Wait() 639 } 640 641 // waitForNetworks is used during daemon initialization when starting up containers 642 // It ensures that all of a container's networks are available before the daemon tries to start the container. 643 // In practice it just makes sure the discovery service is available for containers which use a network that require discovery. 644 func (daemon *Daemon) waitForNetworks(c *container.Container) { 645 if daemon.discoveryWatcher == nil { 646 return 647 } 648 649 // Make sure if the container has a network that requires discovery that the discovery service is available before starting 650 for netName := range c.NetworkSettings.Networks { 651 // If we get `ErrNoSuchNetwork` here, we can assume that it is due to discovery not being ready 652 // Most likely this is because the K/V store used for discovery is in a container and needs to be started 653 if _, err := daemon.netController.NetworkByName(netName); err != nil { 654 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 655 continue 656 } 657 658 // use a longish timeout here due to some slowdowns in libnetwork if the k/v store is on anything other than --net=host 659 // FIXME: why is this slow??? 660 dur := 60 * time.Second 661 timer := time.NewTimer(dur) 662 663 logrus.WithField("container", c.ID).Debugf("Container %s waiting for network to be ready", c.Name) 664 select { 665 case <-daemon.discoveryWatcher.ReadyCh(): 666 case <-timer.C: 667 } 668 timer.Stop() 669 670 return 671 } 672 } 673 } 674 675 func (daemon *Daemon) children(c *container.Container) map[string]*container.Container { 676 return daemon.linkIndex.children(c) 677 } 678 679 // parents returns the names of the parent containers of the container 680 // with the given name. 681 func (daemon *Daemon) parents(c *container.Container) map[string]*container.Container { 682 return daemon.linkIndex.parents(c) 683 } 684 685 func (daemon *Daemon) registerLink(parent, child *container.Container, alias string) error { 686 fullName := path.Join(parent.Name, alias) 687 if err := daemon.containersReplica.ReserveName(fullName, child.ID); err != nil { 688 if err == container.ErrNameReserved { 689 logrus.Warnf("error registering link for %s, to %s, as alias %s, ignoring: %v", parent.ID, child.ID, alias, err) 690 return nil 691 } 692 return err 693 } 694 daemon.linkIndex.link(parent, child, fullName) 695 return nil 696 } 697 698 // DaemonJoinsCluster informs the daemon has joined the cluster and provides 699 // the handler to query the cluster component 700 func (daemon *Daemon) DaemonJoinsCluster(clusterProvider cluster.Provider) { 701 daemon.setClusterProvider(clusterProvider) 702 } 703 704 // DaemonLeavesCluster informs the daemon has left the cluster 705 func (daemon *Daemon) DaemonLeavesCluster() { 706 // Daemon is in charge of removing the attachable networks with 707 // connected containers when the node leaves the swarm 708 daemon.clearAttachableNetworks() 709 // We no longer need the cluster provider, stop it now so that 710 // the network agent will stop listening to cluster events. 711 daemon.setClusterProvider(nil) 712 // Wait for the networking cluster agent to stop 713 daemon.netController.AgentStopWait() 714 // Daemon is in charge of removing the ingress network when the 715 // node leaves the swarm. Wait for job to be done or timeout. 716 // This is called also on graceful daemon shutdown. We need to 717 // wait, because the ingress release has to happen before the 718 // network controller is stopped. 719 720 if done, err := daemon.ReleaseIngress(); err == nil { 721 timeout := time.NewTimer(5 * time.Second) 722 defer timeout.Stop() 723 724 select { 725 case <-done: 726 case <-timeout.C: 727 logrus.Warn("timeout while waiting for ingress network removal") 728 } 729 } else { 730 logrus.Warnf("failed to initiate ingress network removal: %v", err) 731 } 732 733 daemon.attachmentStore.ClearAttachments() 734 } 735 736 // setClusterProvider sets a component for querying the current cluster state. 737 func (daemon *Daemon) setClusterProvider(clusterProvider cluster.Provider) { 738 daemon.clusterProvider = clusterProvider 739 daemon.netController.SetClusterProvider(clusterProvider) 740 daemon.attachableNetworkLock = locker.New() 741 } 742 743 // IsSwarmCompatible verifies if the current daemon 744 // configuration is compatible with the swarm mode 745 func (daemon *Daemon) IsSwarmCompatible() error { 746 if daemon.configStore == nil { 747 return nil 748 } 749 return daemon.configStore.IsSwarmCompatible() 750 } 751 752 // NewDaemon sets up everything for the daemon to be able to service 753 // requests from the webserver. 754 func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.Store) (daemon *Daemon, err error) { 755 setDefaultMtu(config) 756 757 registryService, err := registry.NewService(config.ServiceOptions) 758 if err != nil { 759 return nil, err 760 } 761 762 // Ensure that we have a correct root key limit for launching containers. 763 if err := ModifyRootKeyLimit(); err != nil { 764 logrus.Warnf("unable to modify root key limit, number of containers could be limited by this quota: %v", err) 765 } 766 767 // Ensure we have compatible and valid configuration options 768 if err := verifyDaemonSettings(config); err != nil { 769 return nil, err 770 } 771 772 // Do we have a disabled network? 773 config.DisableBridge = isBridgeNetworkDisabled(config) 774 775 // Setup the resolv.conf 776 setupResolvConf(config) 777 778 // Verify the platform is supported as a daemon 779 if !platformSupported { 780 return nil, errSystemNotSupported 781 } 782 783 // Validate platform-specific requirements 784 if err := checkSystem(); err != nil { 785 return nil, err 786 } 787 788 idMapping, err := setupRemappedRoot(config) 789 if err != nil { 790 return nil, err 791 } 792 rootIDs := idMapping.RootPair() 793 if err := setupDaemonProcess(config); err != nil { 794 return nil, err 795 } 796 797 // set up the tmpDir to use a canonical path 798 tmp, err := prepareTempDir(config.Root) 799 if err != nil { 800 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 801 } 802 realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) 803 if err != nil { 804 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 805 } 806 if isWindows { 807 if _, err := os.Stat(realTmp); err != nil && os.IsNotExist(err) { 808 if err := system.MkdirAll(realTmp, 0700); err != nil { 809 return nil, fmt.Errorf("Unable to create the TempDir (%s): %s", realTmp, err) 810 } 811 } 812 os.Setenv("TEMP", realTmp) 813 os.Setenv("TMP", realTmp) 814 } else { 815 os.Setenv("TMPDIR", realTmp) 816 } 817 818 d := &Daemon{ 819 configStore: config, 820 PluginStore: pluginStore, 821 startupDone: make(chan struct{}), 822 } 823 824 // Ensure the daemon is properly shutdown if there is a failure during 825 // initialization 826 defer func() { 827 if err != nil { 828 if err := d.Shutdown(); err != nil { 829 logrus.Error(err) 830 } 831 } 832 }() 833 834 if err := d.setGenericResources(config); err != nil { 835 return nil, err 836 } 837 // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event 838 // on Windows to dump Go routine stacks 839 stackDumpDir := config.Root 840 if execRoot := config.GetExecRoot(); execRoot != "" { 841 stackDumpDir = execRoot 842 } 843 d.setupDumpStackTrap(stackDumpDir) 844 845 if err := d.setupSeccompProfile(); err != nil { 846 return nil, err 847 } 848 849 // Set the default isolation mode (only applicable on Windows) 850 if err := d.setDefaultIsolation(); err != nil { 851 return nil, fmt.Errorf("error setting default isolation mode: %v", err) 852 } 853 854 if err := configureMaxThreads(config); err != nil { 855 logrus.Warnf("Failed to configure golang's threads limit: %v", err) 856 } 857 858 // ensureDefaultAppArmorProfile does nothing if apparmor is disabled 859 if err := ensureDefaultAppArmorProfile(); err != nil { 860 logrus.Errorf(err.Error()) 861 } 862 863 daemonRepo := filepath.Join(config.Root, "containers") 864 if err := idtools.MkdirAllAndChown(daemonRepo, 0701, idtools.CurrentIdentity()); err != nil { 865 return nil, err 866 } 867 868 // Create the directory where we'll store the runtime scripts (i.e. in 869 // order to support runtimeArgs) 870 daemonRuntimes := filepath.Join(config.Root, "runtimes") 871 if err := system.MkdirAll(daemonRuntimes, 0700); err != nil { 872 return nil, err 873 } 874 if err := d.loadRuntimes(); err != nil { 875 return nil, err 876 } 877 878 if isWindows { 879 if err := system.MkdirAll(filepath.Join(config.Root, "credentialspecs"), 0); err != nil { 880 return nil, err 881 } 882 } 883 884 // On Windows we don't support the environment variable, or a user supplied graphdriver 885 // as Windows has no choice in terms of which graphdrivers to use. It's a case of 886 // running Windows containers on Windows - windowsfilter, running Linux containers on Windows, 887 // lcow. Unix platforms however run a single graphdriver for all containers, and it can 888 // be set through an environment variable, a daemon start parameter, or chosen through 889 // initialization of the layerstore through driver priority order for example. 890 d.graphDrivers = make(map[string]string) 891 layerStores := make(map[string]layer.Store) 892 if isWindows { 893 d.graphDrivers[runtime.GOOS] = "windowsfilter" 894 if system.LCOWSupported() { 895 d.graphDrivers["linux"] = "lcow" 896 } 897 } else { 898 driverName := os.Getenv("DOCKER_DRIVER") 899 if driverName == "" { 900 driverName = config.GraphDriver 901 } else { 902 logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", driverName) 903 } 904 d.graphDrivers[runtime.GOOS] = driverName // May still be empty. Layerstore init determines instead. 905 } 906 907 d.RegistryService = registryService 908 logger.RegisterPluginGetter(d.PluginStore) 909 910 metricsSockPath, err := d.listenMetricsSock() 911 if err != nil { 912 return nil, err 913 } 914 registerMetricsPluginCallback(d.PluginStore, metricsSockPath) 915 916 backoffConfig := backoff.DefaultConfig 917 backoffConfig.MaxDelay = 3 * time.Second 918 connParams := grpc.ConnectParams{ 919 Backoff: backoffConfig, 920 } 921 gopts := []grpc.DialOption{ 922 // WithBlock makes sure that the following containerd request 923 // is reliable. 924 // 925 // NOTE: In one edge case with high load pressure, kernel kills 926 // dockerd, containerd and containerd-shims caused by OOM. 927 // When both dockerd and containerd restart, but containerd 928 // will take time to recover all the existing containers. Before 929 // containerd serving, dockerd will failed with gRPC error. 930 // That bad thing is that restore action will still ignore the 931 // any non-NotFound errors and returns running state for 932 // already stopped container. It is unexpected behavior. And 933 // we need to restart dockerd to make sure that anything is OK. 934 // 935 // It is painful. Add WithBlock can prevent the edge case. And 936 // n common case, the containerd will be serving in shortly. 937 // It is not harm to add WithBlock for containerd connection. 938 grpc.WithBlock(), 939 940 grpc.WithInsecure(), 941 grpc.WithConnectParams(connParams), 942 grpc.WithContextDialer(dialer.ContextDialer), 943 944 // TODO(stevvooe): We may need to allow configuration of this on the client. 945 grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)), 946 grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)), 947 } 948 if config.ContainerdAddr != "" { 949 d.containerdCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) 950 if err != nil { 951 return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) 952 } 953 } 954 955 createPluginExec := func(m *plugin.Manager) (plugin.Executor, error) { 956 var pluginCli *containerd.Client 957 958 // Windows is not currently using containerd, keep the 959 // client as nil 960 if config.ContainerdAddr != "" { 961 pluginCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdPluginNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) 962 if err != nil { 963 return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) 964 } 965 } 966 967 var rt types.Runtime 968 if runtime.GOOS != "windows" { 969 rtPtr, err := d.getRuntime(config.GetDefaultRuntimeName()) 970 if err != nil { 971 return nil, err 972 } 973 rt = *rtPtr 974 } 975 return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m, rt) 976 } 977 978 // Plugin system initialization should happen before restore. Do not change order. 979 d.pluginManager, err = plugin.NewManager(plugin.ManagerConfig{ 980 Root: filepath.Join(config.Root, "plugins"), 981 ExecRoot: getPluginExecRoot(config.Root), 982 Store: d.PluginStore, 983 CreateExecutor: createPluginExec, 984 RegistryService: registryService, 985 LiveRestoreEnabled: config.LiveRestoreEnabled, 986 LogPluginEvent: d.LogPluginEvent, // todo: make private 987 AuthzMiddleware: config.AuthzMiddleware, 988 }) 989 if err != nil { 990 return nil, errors.Wrap(err, "couldn't create plugin manager") 991 } 992 993 if err := d.setupDefaultLogConfig(); err != nil { 994 return nil, err 995 } 996 997 for operatingSystem, gd := range d.graphDrivers { 998 layerStores[operatingSystem], err = layer.NewStoreFromOptions(layer.StoreOptions{ 999 Root: config.Root, 1000 MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), 1001 GraphDriver: gd, 1002 GraphDriverOptions: config.GraphOptions, 1003 IDMapping: idMapping, 1004 PluginGetter: d.PluginStore, 1005 ExperimentalEnabled: config.Experimental, 1006 OS: operatingSystem, 1007 }) 1008 if err != nil { 1009 return nil, err 1010 } 1011 1012 // As layerstore initialization may set the driver 1013 d.graphDrivers[operatingSystem] = layerStores[operatingSystem].DriverName() 1014 } 1015 1016 // Configure and validate the kernels security support. Note this is a Linux/FreeBSD 1017 // operation only, so it is safe to pass *just* the runtime OS graphdriver. 1018 if err := configureKernelSecuritySupport(config, d.graphDrivers[runtime.GOOS]); err != nil { 1019 return nil, err 1020 } 1021 1022 imageRoot := filepath.Join(config.Root, "image", d.graphDrivers[runtime.GOOS]) 1023 ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) 1024 if err != nil { 1025 return nil, err 1026 } 1027 1028 lgrMap := make(map[string]image.LayerGetReleaser) 1029 for los, ls := range layerStores { 1030 lgrMap[los] = ls 1031 } 1032 imageStore, err := image.NewImageStore(ifs, lgrMap) 1033 if err != nil { 1034 return nil, err 1035 } 1036 1037 d.volumes, err = volumesservice.NewVolumeService(config.Root, d.PluginStore, rootIDs, d) 1038 if err != nil { 1039 return nil, err 1040 } 1041 1042 trustKey, err := loadOrCreateTrustKey(config.TrustKeyPath) 1043 if err != nil { 1044 return nil, err 1045 } 1046 1047 trustDir := filepath.Join(config.Root, "trust") 1048 1049 if err := system.MkdirAll(trustDir, 0700); err != nil { 1050 return nil, err 1051 } 1052 1053 // We have a single tag/reference store for the daemon globally. However, it's 1054 // stored under the graphdriver. On host platforms which only support a single 1055 // container OS, but multiple selectable graphdrivers, this means depending on which 1056 // graphdriver is chosen, the global reference store is under there. For 1057 // platforms which support multiple container operating systems, this is slightly 1058 // more problematic as where does the global ref store get located? Fortunately, 1059 // for Windows, which is currently the only daemon supporting multiple container 1060 // operating systems, the list of graphdrivers available isn't user configurable. 1061 // For backwards compatibility, we just put it under the windowsfilter 1062 // directory regardless. 1063 refStoreLocation := filepath.Join(imageRoot, `repositories.json`) 1064 rs, err := refstore.NewReferenceStore(refStoreLocation) 1065 if err != nil { 1066 return nil, fmt.Errorf("Couldn't create reference store repository: %s", err) 1067 } 1068 1069 distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) 1070 if err != nil { 1071 return nil, err 1072 } 1073 1074 // Discovery is only enabled when the daemon is launched with an address to advertise. When 1075 // initialized, the daemon is registered and we can store the discovery backend as it's read-only 1076 if err := d.initDiscovery(config); err != nil { 1077 return nil, err 1078 } 1079 1080 sysInfo := d.RawSysInfo(false) 1081 // Check if Devices cgroup is mounted, it is hard requirement for container security, 1082 // on Linux. 1083 if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled && !sys.RunningInUserNS() { 1084 return nil, errors.New("Devices cgroup isn't mounted") 1085 } 1086 1087 d.ID = trustKey.PublicKey().KeyID() 1088 d.repository = daemonRepo 1089 d.containers = container.NewMemoryStore() 1090 if d.containersReplica, err = container.NewViewDB(); err != nil { 1091 return nil, err 1092 } 1093 d.execCommands = exec.NewStore() 1094 d.idIndex = truncindex.NewTruncIndex([]string{}) 1095 d.statsCollector = d.newStatsCollector(1 * time.Second) 1096 1097 d.EventsService = events.New() 1098 d.root = config.Root 1099 d.idMapping = idMapping 1100 d.seccompEnabled = sysInfo.Seccomp 1101 d.apparmorEnabled = sysInfo.AppArmor 1102 1103 d.linkIndex = newLinkIndex() 1104 1105 imgSvcConfig := images.ImageServiceConfig{ 1106 ContainerStore: d.containers, 1107 DistributionMetadataStore: distributionMetadataStore, 1108 EventsService: d.EventsService, 1109 ImageStore: imageStore, 1110 LayerStores: layerStores, 1111 MaxConcurrentDownloads: *config.MaxConcurrentDownloads, 1112 MaxConcurrentUploads: *config.MaxConcurrentUploads, 1113 MaxDownloadAttempts: *config.MaxDownloadAttempts, 1114 ReferenceStore: rs, 1115 RegistryService: registryService, 1116 TrustKey: trustKey, 1117 ContentNamespace: config.ContainerdNamespace, 1118 } 1119 1120 // containerd is not currently supported with Windows. 1121 // So sometimes d.containerdCli will be nil 1122 // In that case we'll create a local content store... but otherwise we'll use containerd 1123 if d.containerdCli != nil { 1124 imgSvcConfig.Leases = d.containerdCli.LeasesService() 1125 imgSvcConfig.ContentStore = d.containerdCli.ContentStore() 1126 } else { 1127 cs, lm, err := d.configureLocalContentStore() 1128 if err != nil { 1129 return nil, err 1130 } 1131 imgSvcConfig.ContentStore = cs 1132 imgSvcConfig.Leases = lm 1133 } 1134 1135 // TODO: imageStore, distributionMetadataStore, and ReferenceStore are only 1136 // used above to run migration. They could be initialized in ImageService 1137 // if migration is called from daemon/images. layerStore might move as well. 1138 d.imageService = images.NewImageService(imgSvcConfig) 1139 1140 go d.execCommandGC() 1141 1142 d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d) 1143 if err != nil { 1144 return nil, err 1145 } 1146 1147 if err := d.restore(); err != nil { 1148 return nil, err 1149 } 1150 close(d.startupDone) 1151 1152 info := d.SystemInfo() 1153 1154 engineInfo.WithValues( 1155 dockerversion.Version, 1156 dockerversion.GitCommit, 1157 info.Architecture, 1158 info.Driver, 1159 info.KernelVersion, 1160 info.OperatingSystem, 1161 info.OSType, 1162 info.OSVersion, 1163 info.ID, 1164 ).Set(1) 1165 engineCpus.Set(float64(info.NCPU)) 1166 engineMemory.Set(float64(info.MemTotal)) 1167 1168 gd := "" 1169 for os, driver := range d.graphDrivers { 1170 if len(gd) > 0 { 1171 gd += ", " 1172 } 1173 gd += driver 1174 if len(d.graphDrivers) > 1 { 1175 gd = fmt.Sprintf("%s (%s)", gd, os) 1176 } 1177 } 1178 logrus.WithFields(logrus.Fields{ 1179 "version": dockerversion.Version, 1180 "commit": dockerversion.GitCommit, 1181 "graphdriver(s)": gd, 1182 }).Info("Docker daemon") 1183 1184 return d, nil 1185 } 1186 1187 // DistributionServices returns services controlling daemon storage 1188 func (daemon *Daemon) DistributionServices() images.DistributionServices { 1189 return daemon.imageService.DistributionServices() 1190 } 1191 1192 func (daemon *Daemon) waitForStartupDone() { 1193 <-daemon.startupDone 1194 } 1195 1196 func (daemon *Daemon) shutdownContainer(c *container.Container) error { 1197 stopTimeout := c.StopTimeout() 1198 1199 // If container failed to exit in stopTimeout seconds of SIGTERM, then using the force 1200 if err := daemon.containerStop(c, stopTimeout); err != nil { 1201 return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err) 1202 } 1203 1204 // Wait without timeout for the container to exit. 1205 // Ignore the result. 1206 <-c.Wait(context.Background(), container.WaitConditionNotRunning) 1207 return nil 1208 } 1209 1210 // ShutdownTimeout returns the timeout (in seconds) before containers are forcibly 1211 // killed during shutdown. The default timeout can be configured both on the daemon 1212 // and per container, and the longest timeout will be used. A grace-period of 1213 // 5 seconds is added to the configured timeout. 1214 // 1215 // A negative (-1) timeout means "indefinitely", which means that containers 1216 // are not forcibly killed, and the daemon shuts down after all containers exit. 1217 func (daemon *Daemon) ShutdownTimeout() int { 1218 shutdownTimeout := daemon.configStore.ShutdownTimeout 1219 if shutdownTimeout < 0 { 1220 return -1 1221 } 1222 if daemon.containers == nil { 1223 return shutdownTimeout 1224 } 1225 1226 graceTimeout := 5 1227 for _, c := range daemon.containers.List() { 1228 stopTimeout := c.StopTimeout() 1229 if stopTimeout < 0 { 1230 return -1 1231 } 1232 if stopTimeout+graceTimeout > shutdownTimeout { 1233 shutdownTimeout = stopTimeout + graceTimeout 1234 } 1235 } 1236 return shutdownTimeout 1237 } 1238 1239 // Shutdown stops the daemon. 1240 func (daemon *Daemon) Shutdown() error { 1241 daemon.shutdown = true 1242 // Keep mounts and networking running on daemon shutdown if 1243 // we are to keep containers running and restore them. 1244 1245 if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil { 1246 // check if there are any running containers, if none we should do some cleanup 1247 if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil { 1248 // metrics plugins still need some cleanup 1249 daemon.cleanupMetricsPlugins() 1250 return nil 1251 } 1252 } 1253 1254 if daemon.containers != nil { 1255 logrus.Debugf("daemon configured with a %d seconds minimum shutdown timeout", daemon.configStore.ShutdownTimeout) 1256 logrus.Debugf("start clean shutdown of all containers with a %d seconds timeout...", daemon.ShutdownTimeout()) 1257 daemon.containers.ApplyAll(func(c *container.Container) { 1258 if !c.IsRunning() { 1259 return 1260 } 1261 log := logrus.WithField("container", c.ID) 1262 log.Debug("shutting down container") 1263 if err := daemon.shutdownContainer(c); err != nil { 1264 log.WithError(err).Error("failed to shut down container") 1265 return 1266 } 1267 if mountid, err := daemon.imageService.GetLayerMountID(c.ID, c.OS); err == nil { 1268 daemon.cleanupMountsByID(mountid) 1269 } 1270 log.Debugf("shut down container") 1271 }) 1272 } 1273 1274 if daemon.volumes != nil { 1275 if err := daemon.volumes.Shutdown(); err != nil { 1276 logrus.Errorf("Error shutting down volume store: %v", err) 1277 } 1278 } 1279 1280 if daemon.imageService != nil { 1281 daemon.imageService.Cleanup() 1282 } 1283 1284 // If we are part of a cluster, clean up cluster's stuff 1285 if daemon.clusterProvider != nil { 1286 logrus.Debugf("start clean shutdown of cluster resources...") 1287 daemon.DaemonLeavesCluster() 1288 } 1289 1290 daemon.cleanupMetricsPlugins() 1291 1292 // Shutdown plugins after containers and layerstore. Don't change the order. 1293 daemon.pluginShutdown() 1294 1295 // trigger libnetwork Stop only if it's initialized 1296 if daemon.netController != nil { 1297 daemon.netController.Stop() 1298 } 1299 1300 if daemon.containerdCli != nil { 1301 daemon.containerdCli.Close() 1302 } 1303 1304 if daemon.mdDB != nil { 1305 daemon.mdDB.Close() 1306 } 1307 1308 return daemon.cleanupMounts() 1309 } 1310 1311 // Mount sets container.BaseFS 1312 // (is it not set coming in? why is it unset?) 1313 func (daemon *Daemon) Mount(container *container.Container) error { 1314 if container.RWLayer == nil { 1315 return errors.New("RWLayer of container " + container.ID + " is unexpectedly nil") 1316 } 1317 dir, err := container.RWLayer.Mount(container.GetMountLabel()) 1318 if err != nil { 1319 return err 1320 } 1321 logrus.WithField("container", container.ID).Debugf("container mounted via layerStore: %v", dir) 1322 1323 if container.BaseFS != nil && container.BaseFS.Path() != dir.Path() { 1324 // The mount path reported by the graph driver should always be trusted on Windows, since the 1325 // volume path for a given mounted layer may change over time. This should only be an error 1326 // on non-Windows operating systems. 1327 if runtime.GOOS != "windows" { 1328 daemon.Unmount(container) 1329 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 1330 daemon.imageService.GraphDriverForOS(container.OS), container.ID, container.BaseFS, dir) 1331 } 1332 } 1333 container.BaseFS = dir // TODO: combine these fields 1334 return nil 1335 } 1336 1337 // Unmount unsets the container base filesystem 1338 func (daemon *Daemon) Unmount(container *container.Container) error { 1339 if container.RWLayer == nil { 1340 return errors.New("RWLayer of container " + container.ID + " is unexpectedly nil") 1341 } 1342 if err := container.RWLayer.Unmount(); err != nil { 1343 logrus.WithField("container", container.ID).WithError(err).Error("error unmounting container") 1344 return err 1345 } 1346 1347 return nil 1348 } 1349 1350 // Subnets return the IPv4 and IPv6 subnets of networks that are manager by Docker. 1351 func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) { 1352 var v4Subnets []net.IPNet 1353 var v6Subnets []net.IPNet 1354 1355 managedNetworks := daemon.netController.Networks() 1356 1357 for _, managedNetwork := range managedNetworks { 1358 v4infos, v6infos := managedNetwork.Info().IpamInfo() 1359 for _, info := range v4infos { 1360 if info.IPAMData.Pool != nil { 1361 v4Subnets = append(v4Subnets, *info.IPAMData.Pool) 1362 } 1363 } 1364 for _, info := range v6infos { 1365 if info.IPAMData.Pool != nil { 1366 v6Subnets = append(v6Subnets, *info.IPAMData.Pool) 1367 } 1368 } 1369 } 1370 1371 return v4Subnets, v6Subnets 1372 } 1373 1374 // prepareTempDir prepares and returns the default directory to use 1375 // for temporary files. 1376 // If it doesn't exist, it is created. If it exists, its content is removed. 1377 func prepareTempDir(rootDir string) (string, error) { 1378 var tmpDir string 1379 if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 1380 tmpDir = filepath.Join(rootDir, "tmp") 1381 newName := tmpDir + "-old" 1382 if err := os.Rename(tmpDir, newName); err == nil { 1383 go func() { 1384 if err := os.RemoveAll(newName); err != nil { 1385 logrus.Warnf("failed to delete old tmp directory: %s", newName) 1386 } 1387 }() 1388 } else if !os.IsNotExist(err) { 1389 logrus.Warnf("failed to rename %s for background deletion: %s. Deleting synchronously", tmpDir, err) 1390 if err := os.RemoveAll(tmpDir); err != nil { 1391 logrus.Warnf("failed to delete old tmp directory: %s", tmpDir) 1392 } 1393 } 1394 } 1395 return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0700, idtools.CurrentIdentity()) 1396 } 1397 1398 func (daemon *Daemon) setGenericResources(conf *config.Config) error { 1399 genericResources, err := config.ParseGenericResources(conf.NodeGenericResources) 1400 if err != nil { 1401 return err 1402 } 1403 1404 daemon.genericResources = genericResources 1405 1406 return nil 1407 } 1408 1409 func setDefaultMtu(conf *config.Config) { 1410 // do nothing if the config does not have the default 0 value. 1411 if conf.Mtu != 0 { 1412 return 1413 } 1414 conf.Mtu = config.DefaultNetworkMtu 1415 } 1416 1417 // IsShuttingDown tells whether the daemon is shutting down or not 1418 func (daemon *Daemon) IsShuttingDown() bool { 1419 return daemon.shutdown 1420 } 1421 1422 // initDiscovery initializes the discovery watcher for this daemon. 1423 func (daemon *Daemon) initDiscovery(conf *config.Config) error { 1424 advertise, err := config.ParseClusterAdvertiseSettings(conf.ClusterStore, conf.ClusterAdvertise) 1425 if err != nil { 1426 if err == discovery.ErrDiscoveryDisabled { 1427 return nil 1428 } 1429 return err 1430 } 1431 1432 conf.ClusterAdvertise = advertise 1433 discoveryWatcher, err := discovery.Init(conf.ClusterStore, conf.ClusterAdvertise, conf.ClusterOpts) 1434 if err != nil { 1435 return fmt.Errorf("discovery initialization failed (%v)", err) 1436 } 1437 1438 daemon.discoveryWatcher = discoveryWatcher 1439 return nil 1440 } 1441 1442 func isBridgeNetworkDisabled(conf *config.Config) bool { 1443 return conf.BridgeConfig.Iface == config.DisableNetworkBridge 1444 } 1445 1446 func (daemon *Daemon) networkOptions(dconfig *config.Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) { 1447 options := []nwconfig.Option{} 1448 if dconfig == nil { 1449 return options, nil 1450 } 1451 1452 options = append(options, nwconfig.OptionExperimental(dconfig.Experimental)) 1453 options = append(options, nwconfig.OptionDataDir(dconfig.Root)) 1454 options = append(options, nwconfig.OptionExecRoot(dconfig.GetExecRoot())) 1455 1456 dd := runconfig.DefaultDaemonNetworkMode() 1457 dn := runconfig.DefaultDaemonNetworkMode().NetworkName() 1458 options = append(options, nwconfig.OptionDefaultDriver(string(dd))) 1459 options = append(options, nwconfig.OptionDefaultNetwork(dn)) 1460 1461 if strings.TrimSpace(dconfig.ClusterStore) != "" { 1462 kv := strings.Split(dconfig.ClusterStore, "://") 1463 if len(kv) != 2 { 1464 return nil, errors.New("kv store daemon config must be of the form KV-PROVIDER://KV-URL") 1465 } 1466 options = append(options, nwconfig.OptionKVProvider(kv[0])) 1467 options = append(options, nwconfig.OptionKVProviderURL(kv[1])) 1468 } 1469 if len(dconfig.ClusterOpts) > 0 { 1470 options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts)) 1471 } 1472 1473 if daemon.discoveryWatcher != nil { 1474 options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher)) 1475 } 1476 1477 if dconfig.ClusterAdvertise != "" { 1478 options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise)) 1479 } 1480 1481 options = append(options, nwconfig.OptionLabels(dconfig.Labels)) 1482 options = append(options, driverOptions(dconfig)...) 1483 1484 if len(dconfig.NetworkConfig.DefaultAddressPools.Value()) > 0 { 1485 options = append(options, nwconfig.OptionDefaultAddressPoolConfig(dconfig.NetworkConfig.DefaultAddressPools.Value())) 1486 } 1487 1488 if daemon.configStore != nil && daemon.configStore.LiveRestoreEnabled && len(activeSandboxes) != 0 { 1489 options = append(options, nwconfig.OptionActiveSandboxes(activeSandboxes)) 1490 } 1491 1492 if pg != nil { 1493 options = append(options, nwconfig.OptionPluginGetter(pg)) 1494 } 1495 1496 options = append(options, nwconfig.OptionNetworkControlPlaneMTU(dconfig.NetworkControlPlaneMTU)) 1497 1498 return options, nil 1499 } 1500 1501 // GetCluster returns the cluster 1502 func (daemon *Daemon) GetCluster() Cluster { 1503 return daemon.cluster 1504 } 1505 1506 // SetCluster sets the cluster 1507 func (daemon *Daemon) SetCluster(cluster Cluster) { 1508 daemon.cluster = cluster 1509 } 1510 1511 func (daemon *Daemon) pluginShutdown() { 1512 manager := daemon.pluginManager 1513 // Check for a valid manager object. In error conditions, daemon init can fail 1514 // and shutdown called, before plugin manager is initialized. 1515 if manager != nil { 1516 manager.Shutdown() 1517 } 1518 } 1519 1520 // PluginManager returns current pluginManager associated with the daemon 1521 func (daemon *Daemon) PluginManager() *plugin.Manager { // set up before daemon to avoid this method 1522 return daemon.pluginManager 1523 } 1524 1525 // PluginGetter returns current pluginStore associated with the daemon 1526 func (daemon *Daemon) PluginGetter() *plugin.Store { 1527 return daemon.PluginStore 1528 } 1529 1530 // CreateDaemonRoot creates the root for the daemon 1531 func CreateDaemonRoot(config *config.Config) error { 1532 // get the canonical path to the Docker root directory 1533 var realRoot string 1534 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 1535 realRoot = config.Root 1536 } else { 1537 realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) 1538 if err != nil { 1539 return fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 1540 } 1541 } 1542 1543 idMapping, err := setupRemappedRoot(config) 1544 if err != nil { 1545 return err 1546 } 1547 return setupDaemonRoot(config, realRoot, idMapping.RootPair()) 1548 } 1549 1550 // checkpointAndSave grabs a container lock to safely call container.CheckpointTo 1551 func (daemon *Daemon) checkpointAndSave(container *container.Container) error { 1552 container.Lock() 1553 defer container.Unlock() 1554 if err := container.CheckpointTo(daemon.containersReplica); err != nil { 1555 return fmt.Errorf("Error saving container state: %v", err) 1556 } 1557 return nil 1558 } 1559 1560 // because the CLI sends a -1 when it wants to unset the swappiness value 1561 // we need to clear it on the server side 1562 func fixMemorySwappiness(resources *containertypes.Resources) { 1563 if resources.MemorySwappiness != nil && *resources.MemorySwappiness == -1 { 1564 resources.MemorySwappiness = nil 1565 } 1566 } 1567 1568 // GetAttachmentStore returns current attachment store associated with the daemon 1569 func (daemon *Daemon) GetAttachmentStore() *network.AttachmentStore { 1570 return &daemon.attachmentStore 1571 } 1572 1573 // IdentityMapping returns uid/gid mapping or a SID (in the case of Windows) for the builder 1574 func (daemon *Daemon) IdentityMapping() *idtools.IdentityMapping { 1575 return daemon.idMapping 1576 } 1577 1578 // ImageService returns the Daemon's ImageService 1579 func (daemon *Daemon) ImageService() *images.ImageService { 1580 return daemon.imageService 1581 } 1582 1583 // BuilderBackend returns the backend used by builder 1584 func (daemon *Daemon) BuilderBackend() builder.Backend { 1585 return struct { 1586 *Daemon 1587 *images.ImageService 1588 }{daemon, daemon.imageService} 1589 }