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