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