github.com/uppal0016/docker_new@v0.0.0-20240123060250-1c98be13ac2c/daemon/daemon.go (about) 1 // Package daemon exposes the functions that occur on the host server 2 // that the Docker daemon is running. 3 // 4 // In implementing the various functions of the daemon, there is often 5 // a method-specific struct for configuring the runtime behavior. 6 package daemon 7 8 import ( 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net" 13 "os" 14 "path" 15 "path/filepath" 16 "runtime" 17 "strings" 18 "sync" 19 "syscall" 20 "time" 21 22 "github.com/Sirupsen/logrus" 23 containerd "github.com/docker/containerd/api/grpc/types" 24 "github.com/docker/docker/api" 25 "github.com/docker/docker/builder" 26 "github.com/docker/docker/container" 27 "github.com/docker/docker/daemon/events" 28 "github.com/docker/docker/daemon/exec" 29 "github.com/docker/docker/errors" 30 "github.com/docker/engine-api/types" 31 containertypes "github.com/docker/engine-api/types/container" 32 eventtypes "github.com/docker/engine-api/types/events" 33 "github.com/docker/engine-api/types/filters" 34 networktypes "github.com/docker/engine-api/types/network" 35 registrytypes "github.com/docker/engine-api/types/registry" 36 "github.com/docker/engine-api/types/strslice" 37 // register graph drivers 38 _ "github.com/docker/docker/daemon/graphdriver/register" 39 "github.com/docker/docker/daemon/logger" 40 "github.com/docker/docker/daemon/network" 41 dmetadata "github.com/docker/docker/distribution/metadata" 42 "github.com/docker/docker/distribution/xfer" 43 "github.com/docker/docker/dockerversion" 44 "github.com/docker/docker/image" 45 "github.com/docker/docker/image/tarexport" 46 "github.com/docker/docker/layer" 47 "github.com/docker/docker/libcontainerd" 48 "github.com/docker/docker/migrate/v1" 49 "github.com/docker/docker/pkg/archive" 50 "github.com/docker/docker/pkg/fileutils" 51 "github.com/docker/docker/pkg/graphdb" 52 "github.com/docker/docker/pkg/idtools" 53 "github.com/docker/docker/pkg/namesgenerator" 54 "github.com/docker/docker/pkg/progress" 55 "github.com/docker/docker/pkg/registrar" 56 "github.com/docker/docker/pkg/signal" 57 "github.com/docker/docker/pkg/streamformatter" 58 "github.com/docker/docker/pkg/stringid" 59 "github.com/docker/docker/pkg/sysinfo" 60 "github.com/docker/docker/pkg/system" 61 "github.com/docker/docker/pkg/truncindex" 62 "github.com/docker/docker/reference" 63 "github.com/docker/docker/registry" 64 "github.com/docker/docker/runconfig" 65 "github.com/docker/docker/utils" 66 volumedrivers "github.com/docker/docker/volume/drivers" 67 "github.com/docker/docker/volume/local" 68 "github.com/docker/docker/volume/store" 69 "github.com/docker/go-connections/nat" 70 "github.com/docker/libnetwork" 71 nwconfig "github.com/docker/libnetwork/config" 72 "github.com/docker/libtrust" 73 "golang.org/x/net/context" 74 ) 75 76 const ( 77 // maxDownloadConcurrency is the maximum number of downloads that 78 // may take place at a time for each pull. 79 maxDownloadConcurrency = 3 80 // maxUploadConcurrency is the maximum number of uploads that 81 // may take place at a time for each push. 82 maxUploadConcurrency = 5 83 ) 84 85 var ( 86 validContainerNameChars = utils.RestrictedNameChars 87 validContainerNamePattern = utils.RestrictedNamePattern 88 89 errSystemNotSupported = fmt.Errorf("The Docker daemon is not supported on this platform.") 90 ) 91 92 // ErrImageDoesNotExist is error returned when no image can be found for a reference. 93 type ErrImageDoesNotExist struct { 94 RefOrID string 95 } 96 97 func (e ErrImageDoesNotExist) Error() string { 98 return fmt.Sprintf("no such id: %s", e.RefOrID) 99 } 100 101 // Daemon holds information about the Docker daemon. 102 type Daemon struct { 103 ID string 104 repository string 105 containers container.Store 106 execCommands *exec.Store 107 referenceStore reference.Store 108 downloadManager *xfer.LayerDownloadManager 109 uploadManager *xfer.LayerUploadManager 110 distributionMetadataStore dmetadata.Store 111 trustKey libtrust.PrivateKey 112 idIndex *truncindex.TruncIndex 113 configStore *Config 114 statsCollector *statsCollector 115 defaultLogConfig containertypes.LogConfig 116 RegistryService *registry.Service 117 EventsService *events.Events 118 netController libnetwork.NetworkController 119 volumes *store.VolumeStore 120 discoveryWatcher discoveryReloader 121 root string 122 seccompEnabled bool 123 shutdown bool 124 uidMaps []idtools.IDMap 125 gidMaps []idtools.IDMap 126 layerStore layer.Store 127 imageStore image.Store 128 nameIndex *registrar.Registrar 129 linkIndex *linkIndex 130 containerd libcontainerd.Client 131 defaultIsolation containertypes.Isolation // Default isolation mode on Windows 132 } 133 134 // GetContainer looks for a container using the provided information, which could be 135 // one of the following inputs from the caller: 136 // - A full container ID, which will exact match a container in daemon's list 137 // - A container name, which will only exact match via the GetByName() function 138 // - A partial container ID prefix (e.g. short ID) of any length that is 139 // unique enough to only return a single container object 140 // If none of these searches succeed, an error is returned 141 func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, error) { 142 if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { 143 // prefix is an exact match to a full container ID 144 return containerByID, nil 145 } 146 147 // GetByName will match only an exact name provided; we ignore errors 148 if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { 149 // prefix is an exact match to a full container Name 150 return containerByName, nil 151 } 152 153 containerID, indexError := daemon.idIndex.Get(prefixOrName) 154 if indexError != nil { 155 // When truncindex defines an error type, use that instead 156 if indexError == truncindex.ErrNotExist { 157 err := fmt.Errorf("No such container: %s", prefixOrName) 158 return nil, errors.NewRequestNotFoundError(err) 159 } 160 return nil, indexError 161 } 162 return daemon.containers.Get(containerID), nil 163 } 164 165 // Exists returns a true if a container of the specified ID or name exists, 166 // false otherwise. 167 func (daemon *Daemon) Exists(id string) bool { 168 c, _ := daemon.GetContainer(id) 169 return c != nil 170 } 171 172 // IsPaused returns a bool indicating if the specified container is paused. 173 func (daemon *Daemon) IsPaused(id string) bool { 174 c, _ := daemon.GetContainer(id) 175 return c.State.IsPaused() 176 } 177 178 func (daemon *Daemon) containerRoot(id string) string { 179 return filepath.Join(daemon.repository, id) 180 } 181 182 // Load reads the contents of a container from disk 183 // This is typically done at startup. 184 func (daemon *Daemon) load(id string) (*container.Container, error) { 185 container := daemon.newBaseContainer(id) 186 187 if err := container.FromDisk(); err != nil { 188 return nil, err 189 } 190 191 if container.ID != id { 192 return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) 193 } 194 195 return container, nil 196 } 197 198 func (daemon *Daemon) registerName(container *container.Container) error { 199 if daemon.Exists(container.ID) { 200 return fmt.Errorf("Container is already loaded") 201 } 202 if err := validateID(container.ID); err != nil { 203 return err 204 } 205 if container.Name == "" { 206 name, err := daemon.generateNewName(container.ID) 207 if err != nil { 208 return err 209 } 210 container.Name = name 211 212 if err := container.ToDiskLocking(); err != nil { 213 logrus.Errorf("Error saving container name to disk: %v", err) 214 } 215 } 216 return daemon.nameIndex.Reserve(container.Name, container.ID) 217 } 218 219 // Register makes a container object usable by the daemon as <container.ID> 220 func (daemon *Daemon) Register(c *container.Container) error { 221 // Attach to stdout and stderr 222 if c.Config.OpenStdin { 223 c.NewInputPipes() 224 } else { 225 c.NewNopInputPipe() 226 } 227 228 daemon.containers.Add(c.ID, c) 229 daemon.idIndex.Add(c.ID) 230 231 return nil 232 } 233 234 func (daemon *Daemon) restore() error { 235 var ( 236 debug = utils.IsDebugEnabled() 237 currentDriver = daemon.GraphDriverName() 238 containers = make(map[string]*container.Container) 239 ) 240 241 if !debug { 242 logrus.Info("Loading containers: start.") 243 } 244 dir, err := ioutil.ReadDir(daemon.repository) 245 if err != nil { 246 return err 247 } 248 249 for _, v := range dir { 250 id := v.Name() 251 container, err := daemon.load(id) 252 if !debug && logrus.GetLevel() == logrus.InfoLevel { 253 fmt.Print(".") 254 } 255 if err != nil { 256 logrus.Errorf("Failed to load container %v: %v", id, err) 257 continue 258 } 259 260 // Ignore the container if it does not support the current driver being used by the graph 261 if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { 262 rwlayer, err := daemon.layerStore.GetRWLayer(container.ID) 263 if err != nil { 264 logrus.Errorf("Failed to load container mount %v: %v", id, err) 265 continue 266 } 267 container.RWLayer = rwlayer 268 logrus.Debugf("Loaded container %v", container.ID) 269 270 containers[container.ID] = container 271 } else { 272 logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) 273 } 274 } 275 276 var migrateLegacyLinks bool 277 restartContainers := make(map[*container.Container]chan struct{}) 278 for _, c := range containers { 279 if err := daemon.registerName(c); err != nil { 280 logrus.Errorf("Failed to register container %s: %s", c.ID, err) 281 continue 282 } 283 if err := daemon.Register(c); err != nil { 284 logrus.Errorf("Failed to register container %s: %s", c.ID, err) 285 continue 286 } 287 } 288 var wg sync.WaitGroup 289 var mapLock sync.Mutex 290 for _, c := range containers { 291 wg.Add(1) 292 go func(c *container.Container) { 293 defer wg.Done() 294 rm := c.RestartManager(false) 295 if c.IsRunning() || c.IsPaused() { 296 // Fix activityCount such that graph mounts can be unmounted later 297 if err := daemon.layerStore.ReinitRWLayer(c.RWLayer); err != nil { 298 logrus.Errorf("Failed to ReinitRWLayer for %s due to %s", c.ID, err) 299 return 300 } 301 if err := daemon.containerd.Restore(c.ID, libcontainerd.WithRestartManager(rm)); err != nil { 302 logrus.Errorf("Failed to restore with containerd: %q", err) 303 return 304 } 305 } 306 // fixme: only if not running 307 // get list of containers we need to restart 308 if daemon.configStore.AutoRestart && !c.IsRunning() && !c.IsPaused() && c.ShouldRestart() { 309 mapLock.Lock() 310 restartContainers[c] = make(chan struct{}) 311 mapLock.Unlock() 312 } 313 314 // if c.hostConfig.Links is nil (not just empty), then it is using the old sqlite links and needs to be migrated 315 if c.HostConfig != nil && c.HostConfig.Links == nil { 316 migrateLegacyLinks = true 317 } 318 }(c) 319 } 320 wg.Wait() 321 322 // migrate any legacy links from sqlite 323 linkdbFile := filepath.Join(daemon.root, "linkgraph.db") 324 var legacyLinkDB *graphdb.Database 325 if migrateLegacyLinks { 326 legacyLinkDB, err = graphdb.NewSqliteConn(linkdbFile) 327 if err != nil { 328 return fmt.Errorf("error connecting to legacy link graph DB %s, container links may be lost: %v", linkdbFile, err) 329 } 330 defer legacyLinkDB.Close() 331 } 332 333 // Now that all the containers are registered, register the links 334 for _, c := range containers { 335 if migrateLegacyLinks { 336 if err := daemon.migrateLegacySqliteLinks(legacyLinkDB, c); err != nil { 337 return err 338 } 339 } 340 if err := daemon.registerLinks(c, c.HostConfig); err != nil { 341 logrus.Errorf("failed to register link for container %s: %v", c.ID, err) 342 } 343 } 344 345 group := sync.WaitGroup{} 346 for c, notifier := range restartContainers { 347 group.Add(1) 348 349 go func(c *container.Container, chNotify chan struct{}) { 350 defer group.Done() 351 352 logrus.Debugf("Starting container %s", c.ID) 353 354 // ignore errors here as this is a best effort to wait for children to be 355 // running before we try to start the container 356 children := daemon.children(c) 357 timeout := time.After(5 * time.Second) 358 for _, child := range children { 359 if notifier, exists := restartContainers[child]; exists { 360 select { 361 case <-notifier: 362 case <-timeout: 363 } 364 } 365 } 366 if err := daemon.containerStart(c); err != nil { 367 logrus.Errorf("Failed to start container %s: %s", c.ID, err) 368 } 369 close(chNotify) 370 }(c, notifier) 371 372 } 373 group.Wait() 374 375 // any containers that were started above would already have had this done, 376 // however we need to now prepare the mountpoints for the rest of the containers as well. 377 // This shouldn't cause any issue running on the containers that already had this run. 378 // This must be run after any containers with a restart policy so that containerized plugins 379 // can have a chance to be running before we try to initialize them. 380 for _, c := range containers { 381 // if the container has restart policy, do not 382 // prepare the mountpoints since it has been done on restarting. 383 // This is to speed up the daemon start when a restart container 384 // has a volume and the volume dirver is not available. 385 if _, ok := restartContainers[c]; ok { 386 continue 387 } 388 group.Add(1) 389 go func(c *container.Container) { 390 defer group.Done() 391 if err := daemon.prepareMountPoints(c); err != nil { 392 logrus.Error(err) 393 } 394 }(c) 395 } 396 397 group.Wait() 398 399 if !debug { 400 if logrus.GetLevel() == logrus.InfoLevel { 401 fmt.Println() 402 } 403 logrus.Info("Loading containers: done.") 404 } 405 406 return nil 407 } 408 409 func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error { 410 if img != nil && img.Config != nil { 411 if err := merge(config, img.Config); err != nil { 412 return err 413 } 414 } 415 if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { 416 return fmt.Errorf("No command specified") 417 } 418 return nil 419 } 420 421 func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { 422 var ( 423 err error 424 id = stringid.GenerateNonCryptoID() 425 ) 426 427 if name == "" { 428 if name, err = daemon.generateNewName(id); err != nil { 429 return "", "", err 430 } 431 return id, name, nil 432 } 433 434 if name, err = daemon.reserveName(id, name); err != nil { 435 return "", "", err 436 } 437 438 return id, name, nil 439 } 440 441 func (daemon *Daemon) reserveName(id, name string) (string, error) { 442 if !validContainerNamePattern.MatchString(name) { 443 return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) 444 } 445 if name[0] != '/' { 446 name = "/" + name 447 } 448 449 if err := daemon.nameIndex.Reserve(name, id); err != nil { 450 if err == registrar.ErrNameReserved { 451 id, err := daemon.nameIndex.Get(name) 452 if err != nil { 453 logrus.Errorf("got unexpected error while looking up reserved name: %v", err) 454 return "", err 455 } 456 return "", fmt.Errorf("Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", name, id) 457 } 458 return "", fmt.Errorf("error reserving name: %s, error: %v", name, err) 459 } 460 return name, nil 461 } 462 463 func (daemon *Daemon) releaseName(name string) { 464 daemon.nameIndex.Release(name) 465 } 466 467 func (daemon *Daemon) generateNewName(id string) (string, error) { 468 var name string 469 for i := 0; i < 6; i++ { 470 name = namesgenerator.GetRandomName(i) 471 if name[0] != '/' { 472 name = "/" + name 473 } 474 475 if err := daemon.nameIndex.Reserve(name, id); err != nil { 476 if err == registrar.ErrNameReserved { 477 continue 478 } 479 return "", err 480 } 481 return name, nil 482 } 483 484 name = "/" + stringid.TruncateID(id) 485 if err := daemon.nameIndex.Reserve(name, id); err != nil { 486 return "", err 487 } 488 return name, nil 489 } 490 491 func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) { 492 // Generate default hostname 493 if config.Hostname == "" { 494 config.Hostname = id[:12] 495 } 496 } 497 498 func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint strslice.StrSlice, configCmd strslice.StrSlice) (string, []string) { 499 if len(configEntrypoint) != 0 { 500 return configEntrypoint[0], append(configEntrypoint[1:], configCmd...) 501 } 502 return configCmd[0], configCmd[1:] 503 } 504 505 func (daemon *Daemon) newContainer(name string, config *containertypes.Config, imgID image.ID) (*container.Container, error) { 506 var ( 507 id string 508 err error 509 noExplicitName = name == "" 510 ) 511 id, name, err = daemon.generateIDAndName(name) 512 if err != nil { 513 return nil, err 514 } 515 516 daemon.generateHostname(id, config) 517 entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) 518 519 base := daemon.newBaseContainer(id) 520 base.Created = time.Now().UTC() 521 base.Path = entrypoint 522 base.Args = args //FIXME: de-duplicate from config 523 base.Config = config 524 base.HostConfig = &containertypes.HostConfig{} 525 base.ImageID = imgID 526 base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} 527 base.Name = name 528 base.Driver = daemon.GraphDriverName() 529 530 return base, err 531 } 532 533 // GetByName returns a container given a name. 534 func (daemon *Daemon) GetByName(name string) (*container.Container, error) { 535 fullName := name 536 if name[0] != '/' { 537 fullName = "/" + name 538 } 539 id, err := daemon.nameIndex.Get(fullName) 540 if err != nil { 541 return nil, fmt.Errorf("Could not find entity for %s", name) 542 } 543 e := daemon.containers.Get(id) 544 if e == nil { 545 return nil, fmt.Errorf("Could not find container for entity id %s", id) 546 } 547 return e, nil 548 } 549 550 // SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events. 551 func (daemon *Daemon) SubscribeToEvents(since, sinceNano int64, filter filters.Args) ([]eventtypes.Message, chan interface{}) { 552 ef := events.NewFilter(filter) 553 return daemon.EventsService.SubscribeTopic(since, sinceNano, ef) 554 } 555 556 // UnsubscribeFromEvents stops the event subscription for a client by closing the 557 // channel where the daemon sends events to. 558 func (daemon *Daemon) UnsubscribeFromEvents(listener chan interface{}) { 559 daemon.EventsService.Evict(listener) 560 } 561 562 // GetLabels for a container or image id 563 func (daemon *Daemon) GetLabels(id string) map[string]string { 564 // TODO: TestCase 565 container := daemon.containers.Get(id) 566 if container != nil { 567 return container.Config.Labels 568 } 569 570 img, err := daemon.GetImage(id) 571 if err == nil { 572 return img.ContainerConfig.Labels 573 } 574 return nil 575 } 576 577 func (daemon *Daemon) children(c *container.Container) map[string]*container.Container { 578 return daemon.linkIndex.children(c) 579 } 580 581 // parents returns the names of the parent containers of the container 582 // with the given name. 583 func (daemon *Daemon) parents(c *container.Container) map[string]*container.Container { 584 return daemon.linkIndex.parents(c) 585 } 586 587 func (daemon *Daemon) registerLink(parent, child *container.Container, alias string) error { 588 fullName := path.Join(parent.Name, alias) 589 if err := daemon.nameIndex.Reserve(fullName, child.ID); err != nil { 590 if err == registrar.ErrNameReserved { 591 logrus.Warnf("error registering link for %s, to %s, as alias %s, ignoring: %v", parent.ID, child.ID, alias, err) 592 return nil 593 } 594 return err 595 } 596 daemon.linkIndex.link(parent, child, fullName) 597 return nil 598 } 599 600 // NewDaemon sets up everything for the daemon to be able to service 601 // requests from the webserver. 602 func NewDaemon(config *Config, registryService *registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) { 603 setDefaultMtu(config) 604 605 // Ensure we have compatible and valid configuration options 606 if err := verifyDaemonSettings(config); err != nil { 607 return nil, err 608 } 609 610 // Do we have a disabled network? 611 config.DisableBridge = isBridgeNetworkDisabled(config) 612 613 // Verify the platform is supported as a daemon 614 if !platformSupported { 615 return nil, errSystemNotSupported 616 } 617 618 // Validate platform-specific requirements 619 if err := checkSystem(); err != nil { 620 return nil, err 621 } 622 623 // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event 624 // on Windows to dump Go routine stacks 625 setupDumpStackTrap() 626 627 uidMaps, gidMaps, err := setupRemappedRoot(config) 628 if err != nil { 629 return nil, err 630 } 631 rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) 632 if err != nil { 633 return nil, err 634 } 635 636 // get the canonical path to the Docker root directory 637 var realRoot string 638 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 639 realRoot = config.Root 640 } else { 641 realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) 642 if err != nil { 643 return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 644 } 645 } 646 647 if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { 648 return nil, err 649 } 650 651 // set up the tmpDir to use a canonical path 652 tmp, err := tempDir(config.Root, rootUID, rootGID) 653 if err != nil { 654 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 655 } 656 realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) 657 if err != nil { 658 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 659 } 660 os.Setenv("TMPDIR", realTmp) 661 662 d := &Daemon{configStore: config} 663 // Ensure the daemon is properly shutdown if there is a failure during 664 // initialization 665 defer func() { 666 if err != nil { 667 if err := d.Shutdown(); err != nil { 668 logrus.Error(err) 669 } 670 } 671 }() 672 673 // Set the default isolation mode (only applicable on Windows) 674 if err := d.setDefaultIsolation(); err != nil { 675 return nil, fmt.Errorf("error setting default isolation mode: %v", err) 676 } 677 678 // Verify logging driver type 679 if config.LogConfig.Type != "none" { 680 if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { 681 return nil, fmt.Errorf("error finding the logging driver: %v", err) 682 } 683 } 684 logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) 685 686 if err := configureMaxThreads(config); err != nil { 687 logrus.Warnf("Failed to configure golang's threads limit: %v", err) 688 } 689 690 installDefaultAppArmorProfile() 691 daemonRepo := filepath.Join(config.Root, "containers") 692 if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { 693 return nil, err 694 } 695 696 driverName := os.Getenv("DOCKER_DRIVER") 697 if driverName == "" { 698 driverName = config.GraphDriver 699 } 700 d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{ 701 StorePath: config.Root, 702 MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), 703 GraphDriver: driverName, 704 GraphDriverOptions: config.GraphOptions, 705 UIDMaps: uidMaps, 706 GIDMaps: gidMaps, 707 }) 708 if err != nil { 709 return nil, err 710 } 711 712 graphDriver := d.layerStore.DriverName() 713 imageRoot := filepath.Join(config.Root, "image", graphDriver) 714 715 // Configure and validate the kernels security support 716 if err := configureKernelSecuritySupport(config, graphDriver); err != nil { 717 return nil, err 718 } 719 720 d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, maxDownloadConcurrency) 721 d.uploadManager = xfer.NewLayerUploadManager(maxUploadConcurrency) 722 723 ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) 724 if err != nil { 725 return nil, err 726 } 727 728 d.imageStore, err = image.NewImageStore(ifs, d.layerStore) 729 if err != nil { 730 return nil, err 731 } 732 733 // Configure the volumes driver 734 volStore, err := configureVolumes(config, rootUID, rootGID) 735 if err != nil { 736 return nil, err 737 } 738 739 trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) 740 if err != nil { 741 return nil, err 742 } 743 744 trustDir := filepath.Join(config.Root, "trust") 745 746 if err := system.MkdirAll(trustDir, 0700); err != nil { 747 return nil, err 748 } 749 750 distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution")) 751 if err != nil { 752 return nil, err 753 } 754 755 eventsService := events.New() 756 757 referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json")) 758 if err != nil { 759 return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err) 760 } 761 762 if err := restoreCustomImage(d.imageStore, d.layerStore, referenceStore); err != nil { 763 return nil, fmt.Errorf("Couldn't restore custom images: %s", err) 764 } 765 766 migrationStart := time.Now() 767 if err := v1.Migrate(config.Root, graphDriver, d.layerStore, d.imageStore, referenceStore, distributionMetadataStore); err != nil { 768 logrus.Errorf("Graph migration failed: %q. Your old graph data was found to be too inconsistent for upgrading to content-addressable storage. Some of the old data was probably not upgraded. We recommend starting over with a clean storage directory if possible.", err) 769 } 770 logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) 771 772 // Discovery is only enabled when the daemon is launched with an address to advertise. When 773 // initialized, the daemon is registered and we can store the discovery backend as its read-only 774 if err := d.initDiscovery(config); err != nil { 775 return nil, err 776 } 777 778 d.netController, err = d.initNetworkController(config) 779 if err != nil { 780 return nil, fmt.Errorf("Error initializing network controller: %v", err) 781 } 782 783 sysInfo := sysinfo.New(false) 784 // Check if Devices cgroup is mounted, it is hard requirement for container security, 785 // on Linux/FreeBSD. 786 if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { 787 return nil, fmt.Errorf("Devices cgroup isn't mounted") 788 } 789 790 d.ID = trustKey.PublicKey().KeyID() 791 d.repository = daemonRepo 792 d.containers = container.NewMemoryStore() 793 d.execCommands = exec.NewStore() 794 d.referenceStore = referenceStore 795 d.distributionMetadataStore = distributionMetadataStore 796 d.trustKey = trustKey 797 d.idIndex = truncindex.NewTruncIndex([]string{}) 798 d.statsCollector = d.newStatsCollector(1 * time.Second) 799 d.defaultLogConfig = containertypes.LogConfig{ 800 Type: config.LogConfig.Type, 801 Config: config.LogConfig.Config, 802 } 803 d.RegistryService = registryService 804 d.EventsService = eventsService 805 d.volumes = volStore 806 d.root = config.Root 807 d.uidMaps = uidMaps 808 d.gidMaps = gidMaps 809 d.seccompEnabled = sysInfo.Seccomp 810 811 d.nameIndex = registrar.NewRegistrar() 812 d.linkIndex = newLinkIndex() 813 814 go d.execCommandGC() 815 816 d.containerd, err = containerdRemote.Client(d) 817 if err != nil { 818 return nil, err 819 } 820 821 if err := d.restore(); err != nil { 822 return nil, err 823 } 824 825 return d, nil 826 } 827 828 func (daemon *Daemon) shutdownContainer(c *container.Container) error { 829 // TODO(windows): Handle docker restart with paused containers 830 if c.IsPaused() { 831 // To terminate a process in freezer cgroup, we should send 832 // SIGTERM to this process then unfreeze it, and the process will 833 // force to terminate immediately. 834 logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID) 835 sig, ok := signal.SignalMap["TERM"] 836 if !ok { 837 return fmt.Errorf("System doesn not support SIGTERM") 838 } 839 if err := daemon.kill(c, int(sig)); err != nil { 840 return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err) 841 } 842 if err := daemon.containerUnpause(c); err != nil { 843 return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err) 844 } 845 if _, err := c.WaitStop(10 * time.Second); err != nil { 846 logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID) 847 sig, ok := signal.SignalMap["KILL"] 848 if !ok { 849 return fmt.Errorf("System does not support SIGKILL") 850 } 851 if err := daemon.kill(c, int(sig)); err != nil { 852 logrus.Errorf("Failed to SIGKILL container %s", c.ID) 853 } 854 c.WaitStop(-1 * time.Second) 855 return err 856 } 857 } 858 // If container failed to exit in 10 seconds of SIGTERM, then using the force 859 if err := daemon.containerStop(c, 10); err != nil { 860 return fmt.Errorf("Stop container %s with error: %v", c.ID, err) 861 } 862 863 c.WaitStop(-1 * time.Second) 864 return nil 865 } 866 867 // Shutdown stops the daemon. 868 func (daemon *Daemon) Shutdown() error { 869 daemon.shutdown = true 870 if daemon.containers != nil { 871 logrus.Debug("starting clean shutdown of all containers...") 872 daemon.containers.ApplyAll(func(c *container.Container) { 873 if !c.IsRunning() { 874 return 875 } 876 logrus.Debugf("stopping %s", c.ID) 877 if err := daemon.shutdownContainer(c); err != nil { 878 logrus.Errorf("Stop container error: %v", err) 879 return 880 } 881 if mountid, err := daemon.layerStore.GetMountID(c.ID); err == nil { 882 daemon.cleanupMountsByID(mountid) 883 } 884 logrus.Debugf("container stopped %s", c.ID) 885 }) 886 } 887 888 // trigger libnetwork Stop only if it's initialized 889 if daemon.netController != nil { 890 daemon.netController.Stop() 891 } 892 893 if daemon.layerStore != nil { 894 if err := daemon.layerStore.Cleanup(); err != nil { 895 logrus.Errorf("Error during layer Store.Cleanup(): %v", err) 896 } 897 } 898 899 if err := daemon.cleanupMounts(); err != nil { 900 return err 901 } 902 903 return nil 904 } 905 906 // Mount sets container.BaseFS 907 // (is it not set coming in? why is it unset?) 908 func (daemon *Daemon) Mount(container *container.Container) error { 909 dir, err := container.RWLayer.Mount(container.GetMountLabel()) 910 if err != nil { 911 return err 912 } 913 logrus.Debugf("container mounted via layerStore: %v", dir) 914 915 if container.BaseFS != dir { 916 // The mount path reported by the graph driver should always be trusted on Windows, since the 917 // volume path for a given mounted layer may change over time. This should only be an error 918 // on non-Windows operating systems. 919 if container.BaseFS != "" && runtime.GOOS != "windows" { 920 daemon.Unmount(container) 921 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 922 daemon.GraphDriverName(), container.ID, container.BaseFS, dir) 923 } 924 } 925 container.BaseFS = dir // TODO: combine these fields 926 return nil 927 } 928 929 // Unmount unsets the container base filesystem 930 func (daemon *Daemon) Unmount(container *container.Container) error { 931 if err := container.RWLayer.Unmount(); err != nil { 932 logrus.Errorf("Error unmounting container %s: %s", container.ID, err) 933 return err 934 } 935 return nil 936 } 937 938 func (daemon *Daemon) kill(c *container.Container, sig int) error { 939 return daemon.containerd.Signal(c.ID, sig) 940 } 941 942 func (daemon *Daemon) subscribeToContainerStats(c *container.Container) chan interface{} { 943 return daemon.statsCollector.collect(c) 944 } 945 946 func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch chan interface{}) { 947 daemon.statsCollector.unsubscribe(c, ch) 948 } 949 950 func (daemon *Daemon) changes(container *container.Container) ([]archive.Change, error) { 951 return container.RWLayer.Changes() 952 } 953 954 func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) { 955 progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false) 956 operationCancelled := false 957 958 for prog := range progressChan { 959 if err := progressOutput.WriteProgress(prog); err != nil && !operationCancelled { 960 // don't log broken pipe errors as this is the normal case when a client aborts 961 if isBrokenPipe(err) { 962 logrus.Info("Pull session cancelled") 963 } else { 964 logrus.Errorf("error writing progress to client: %v", err) 965 } 966 cancelFunc() 967 operationCancelled = true 968 // Don't return, because we need to continue draining 969 // progressChan until it's closed to avoid a deadlock. 970 } 971 } 972 } 973 974 func isBrokenPipe(e error) bool { 975 if netErr, ok := e.(*net.OpError); ok { 976 e = netErr.Err 977 if sysErr, ok := netErr.Err.(*os.SyscallError); ok { 978 e = sysErr.Err 979 } 980 } 981 return e == syscall.EPIPE 982 } 983 984 // ExportImage exports a list of images to the given output stream. The 985 // exported images are archived into a tar when written to the output 986 // stream. All images with the given tag and all versions containing 987 // the same tag are exported. names is the set of tags to export, and 988 // outStream is the writer which the images are written to. 989 func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { 990 imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore) 991 return imageExporter.Save(names, outStream) 992 } 993 994 // LookupImage looks up an image by name and returns it as an ImageInspect 995 // structure. 996 func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { 997 img, err := daemon.GetImage(name) 998 if err != nil { 999 return nil, fmt.Errorf("No such image: %s", name) 1000 } 1001 1002 refs := daemon.referenceStore.References(img.ID()) 1003 repoTags := []string{} 1004 repoDigests := []string{} 1005 for _, ref := range refs { 1006 switch ref.(type) { 1007 case reference.NamedTagged: 1008 repoTags = append(repoTags, ref.String()) 1009 case reference.Canonical: 1010 repoDigests = append(repoDigests, ref.String()) 1011 } 1012 } 1013 1014 var size int64 1015 var layerMetadata map[string]string 1016 layerID := img.RootFS.ChainID() 1017 if layerID != "" { 1018 l, err := daemon.layerStore.Get(layerID) 1019 if err != nil { 1020 return nil, err 1021 } 1022 defer layer.ReleaseAndLog(daemon.layerStore, l) 1023 size, err = l.Size() 1024 if err != nil { 1025 return nil, err 1026 } 1027 1028 layerMetadata, err = l.Metadata() 1029 if err != nil { 1030 return nil, err 1031 } 1032 } 1033 1034 comment := img.Comment 1035 if len(comment) == 0 && len(img.History) > 0 { 1036 comment = img.History[len(img.History)-1].Comment 1037 } 1038 1039 imageInspect := &types.ImageInspect{ 1040 ID: img.ID().String(), 1041 RepoTags: repoTags, 1042 RepoDigests: repoDigests, 1043 Parent: img.Parent.String(), 1044 Comment: comment, 1045 Created: img.Created.Format(time.RFC3339Nano), 1046 Container: img.Container, 1047 ContainerConfig: &img.ContainerConfig, 1048 DockerVersion: img.DockerVersion, 1049 Author: img.Author, 1050 Config: img.Config, 1051 Architecture: img.Architecture, 1052 Os: img.OS, 1053 Size: size, 1054 VirtualSize: size, // TODO: field unused, deprecate 1055 RootFS: rootFSToAPIType(img.RootFS), 1056 } 1057 1058 imageInspect.GraphDriver.Name = daemon.GraphDriverName() 1059 1060 imageInspect.GraphDriver.Data = layerMetadata 1061 1062 return imageInspect, nil 1063 } 1064 1065 // LoadImage uploads a set of images into the repository. This is the 1066 // complement of ImageExport. The input stream is an uncompressed tar 1067 // ball containing images and metadata. 1068 func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error { 1069 imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore) 1070 return imageExporter.Load(inTar, outStream, quiet) 1071 } 1072 1073 // ImageHistory returns a slice of ImageHistory structures for the specified image 1074 // name by walking the image lineage. 1075 func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) { 1076 img, err := daemon.GetImage(name) 1077 if err != nil { 1078 return nil, err 1079 } 1080 1081 history := []*types.ImageHistory{} 1082 1083 layerCounter := 0 1084 rootFS := *img.RootFS 1085 rootFS.DiffIDs = nil 1086 1087 for _, h := range img.History { 1088 var layerSize int64 1089 1090 if !h.EmptyLayer { 1091 if len(img.RootFS.DiffIDs) <= layerCounter { 1092 return nil, fmt.Errorf("too many non-empty layers in History section") 1093 } 1094 1095 rootFS.Append(img.RootFS.DiffIDs[layerCounter]) 1096 l, err := daemon.layerStore.Get(rootFS.ChainID()) 1097 if err != nil { 1098 return nil, err 1099 } 1100 layerSize, err = l.DiffSize() 1101 layer.ReleaseAndLog(daemon.layerStore, l) 1102 if err != nil { 1103 return nil, err 1104 } 1105 1106 layerCounter++ 1107 } 1108 1109 history = append([]*types.ImageHistory{{ 1110 ID: "<missing>", 1111 Created: h.Created.Unix(), 1112 CreatedBy: h.CreatedBy, 1113 Comment: h.Comment, 1114 Size: layerSize, 1115 }}, history...) 1116 } 1117 1118 // Fill in image IDs and tags 1119 histImg := img 1120 id := img.ID() 1121 for _, h := range history { 1122 h.ID = id.String() 1123 1124 var tags []string 1125 for _, r := range daemon.referenceStore.References(id) { 1126 if _, ok := r.(reference.NamedTagged); ok { 1127 tags = append(tags, r.String()) 1128 } 1129 } 1130 1131 h.Tags = tags 1132 1133 id = histImg.Parent 1134 if id == "" { 1135 break 1136 } 1137 histImg, err = daemon.GetImage(id.String()) 1138 if err != nil { 1139 break 1140 } 1141 } 1142 1143 return history, nil 1144 } 1145 1146 // GetImageID returns an image ID corresponding to the image referred to by 1147 // refOrID. 1148 func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) { 1149 id, ref, err := reference.ParseIDOrReference(refOrID) 1150 if err != nil { 1151 return "", err 1152 } 1153 if id != "" { 1154 if _, err := daemon.imageStore.Get(image.ID(id)); err != nil { 1155 return "", ErrImageDoesNotExist{refOrID} 1156 } 1157 return image.ID(id), nil 1158 } 1159 1160 if id, err := daemon.referenceStore.Get(ref); err == nil { 1161 return id, nil 1162 } 1163 if tagged, ok := ref.(reference.NamedTagged); ok { 1164 if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil { 1165 for _, namedRef := range daemon.referenceStore.References(id) { 1166 if namedRef.Name() == ref.Name() { 1167 return id, nil 1168 } 1169 } 1170 } 1171 } 1172 1173 // Search based on ID 1174 if id, err := daemon.imageStore.Search(refOrID); err == nil { 1175 return id, nil 1176 } 1177 1178 return "", ErrImageDoesNotExist{refOrID} 1179 } 1180 1181 // GetImage returns an image corresponding to the image referred to by refOrID. 1182 func (daemon *Daemon) GetImage(refOrID string) (*image.Image, error) { 1183 imgID, err := daemon.GetImageID(refOrID) 1184 if err != nil { 1185 return nil, err 1186 } 1187 return daemon.imageStore.Get(imgID) 1188 } 1189 1190 // GetImageOnBuild looks up a Docker image referenced by `name`. 1191 func (daemon *Daemon) GetImageOnBuild(name string) (builder.Image, error) { 1192 img, err := daemon.GetImage(name) 1193 if err != nil { 1194 return nil, err 1195 } 1196 return img, nil 1197 } 1198 1199 // GraphDriverName returns the name of the graph driver used by the layer.Store 1200 func (daemon *Daemon) GraphDriverName() string { 1201 return daemon.layerStore.DriverName() 1202 } 1203 1204 // GetUIDGIDMaps returns the current daemon's user namespace settings 1205 // for the full uid and gid maps which will be applied to containers 1206 // started in this instance. 1207 func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) { 1208 return daemon.uidMaps, daemon.gidMaps 1209 } 1210 1211 // GetRemappedUIDGID returns the current daemon's uid and gid values 1212 // if user namespaces are in use for this daemon instance. If not 1213 // this function will return "real" root values of 0, 0. 1214 func (daemon *Daemon) GetRemappedUIDGID() (int, int) { 1215 uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) 1216 return uid, gid 1217 } 1218 1219 // GetCachedImage returns the most recent created image that is a child 1220 // of the image with imgID, that had the same config when it was 1221 // created. nil is returned if a child cannot be found. An error is 1222 // returned if the parent image cannot be found. 1223 func (daemon *Daemon) GetCachedImage(imgID image.ID, config *containertypes.Config) (*image.Image, error) { 1224 // Loop on the children of the given image and check the config 1225 getMatch := func(siblings []image.ID) (*image.Image, error) { 1226 var match *image.Image 1227 for _, id := range siblings { 1228 img, err := daemon.imageStore.Get(id) 1229 if err != nil { 1230 return nil, fmt.Errorf("unable to find image %q", id) 1231 } 1232 1233 if runconfig.Compare(&img.ContainerConfig, config) { 1234 // check for the most up to date match 1235 if match == nil || match.Created.Before(img.Created) { 1236 match = img 1237 } 1238 } 1239 } 1240 return match, nil 1241 } 1242 1243 // In this case, this is `FROM scratch`, which isn't an actual image. 1244 if imgID == "" { 1245 images := daemon.imageStore.Map() 1246 var siblings []image.ID 1247 for id, img := range images { 1248 if img.Parent == imgID { 1249 siblings = append(siblings, id) 1250 } 1251 } 1252 return getMatch(siblings) 1253 } 1254 1255 // find match from child images 1256 siblings := daemon.imageStore.Children(imgID) 1257 return getMatch(siblings) 1258 } 1259 1260 // GetCachedImageOnBuild returns a reference to a cached image whose parent equals `parent` 1261 // and runconfig equals `cfg`. A cache miss is expected to return an empty ID and a nil error. 1262 func (daemon *Daemon) GetCachedImageOnBuild(imgID string, cfg *containertypes.Config) (string, error) { 1263 cache, err := daemon.GetCachedImage(image.ID(imgID), cfg) 1264 if cache == nil || err != nil { 1265 return "", err 1266 } 1267 return cache.ID().String(), nil 1268 } 1269 1270 // tempDir returns the default directory to use for temporary files. 1271 func tempDir(rootDir string, rootUID, rootGID int) (string, error) { 1272 var tmpDir string 1273 if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 1274 tmpDir = filepath.Join(rootDir, "tmp") 1275 } 1276 return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) 1277 } 1278 1279 func (daemon *Daemon) setSecurityOptions(container *container.Container, hostConfig *containertypes.HostConfig) error { 1280 container.Lock() 1281 defer container.Unlock() 1282 return parseSecurityOpt(container, hostConfig) 1283 } 1284 1285 func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error { 1286 // Do not lock while creating volumes since this could be calling out to external plugins 1287 // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin 1288 if err := daemon.registerMountPoints(container, hostConfig); err != nil { 1289 return err 1290 } 1291 1292 container.Lock() 1293 defer container.Unlock() 1294 1295 // Register any links from the host config before starting the container 1296 if err := daemon.registerLinks(container, hostConfig); err != nil { 1297 return err 1298 } 1299 1300 // make sure links is not nil 1301 // this ensures that on the next daemon restart we don't try to migrate from legacy sqlite links 1302 if hostConfig.Links == nil { 1303 hostConfig.Links = []string{} 1304 } 1305 1306 container.HostConfig = hostConfig 1307 return container.ToDisk() 1308 } 1309 1310 func (daemon *Daemon) setupInitLayer(initPath string) error { 1311 rootUID, rootGID := daemon.GetRemappedUIDGID() 1312 return setupInitLayer(initPath, rootUID, rootGID) 1313 } 1314 1315 func setDefaultMtu(config *Config) { 1316 // do nothing if the config does not have the default 0 value. 1317 if config.Mtu != 0 { 1318 return 1319 } 1320 config.Mtu = defaultNetworkMtu 1321 } 1322 1323 // verifyContainerSettings performs validation of the hostconfig and config 1324 // structures. 1325 func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { 1326 1327 // First perform verification of settings common across all platforms. 1328 if config != nil { 1329 if config.WorkingDir != "" { 1330 config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics 1331 if !system.IsAbs(config.WorkingDir) { 1332 return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path", config.WorkingDir) 1333 } 1334 } 1335 1336 if len(config.StopSignal) > 0 { 1337 _, err := signal.ParseSignal(config.StopSignal) 1338 if err != nil { 1339 return nil, err 1340 } 1341 } 1342 } 1343 1344 if hostConfig == nil { 1345 return nil, nil 1346 } 1347 1348 logCfg := daemon.getLogConfig(hostConfig.LogConfig) 1349 if err := logger.ValidateLogOpts(logCfg.Type, logCfg.Config); err != nil { 1350 return nil, err 1351 } 1352 1353 for port := range hostConfig.PortBindings { 1354 _, portStr := nat.SplitProtoPort(string(port)) 1355 if _, err := nat.ParsePort(portStr); err != nil { 1356 return nil, fmt.Errorf("Invalid port specification: %q", portStr) 1357 } 1358 for _, pb := range hostConfig.PortBindings[port] { 1359 _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort)) 1360 if err != nil { 1361 return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort) 1362 } 1363 } 1364 } 1365 1366 // Now do platform-specific verification 1367 return verifyPlatformContainerSettings(daemon, hostConfig, config, update) 1368 } 1369 1370 // Checks if the client set configurations for more than one network while creating a container 1371 func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error { 1372 if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 { 1373 return nil 1374 } 1375 l := make([]string, 0, len(nwConfig.EndpointsConfig)) 1376 for k := range nwConfig.EndpointsConfig { 1377 l = append(l, k) 1378 } 1379 err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", ")) 1380 return errors.NewBadRequestError(err) 1381 } 1382 1383 func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) { 1384 volumesDriver, err := local.New(config.Root, rootUID, rootGID) 1385 if err != nil { 1386 return nil, err 1387 } 1388 1389 volumedrivers.Register(volumesDriver, volumesDriver.Name()) 1390 return store.New(config.Root) 1391 } 1392 1393 // AuthenticateToRegistry checks the validity of credentials in authConfig 1394 func (daemon *Daemon) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) { 1395 return daemon.RegistryService.Auth(authConfig, dockerversion.DockerUserAgent(ctx)) 1396 } 1397 1398 // SearchRegistryForImages queries the registry for images matching 1399 // term. authConfig is used to login. 1400 func (daemon *Daemon) SearchRegistryForImages(ctx context.Context, term string, 1401 authConfig *types.AuthConfig, 1402 headers map[string][]string) (*registrytypes.SearchResults, error) { 1403 return daemon.RegistryService.Search(term, authConfig, dockerversion.DockerUserAgent(ctx), headers) 1404 } 1405 1406 // IsShuttingDown tells whether the daemon is shutting down or not 1407 func (daemon *Daemon) IsShuttingDown() bool { 1408 return daemon.shutdown 1409 } 1410 1411 // GetContainerStats collects all the stats published by a container 1412 func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.StatsJSON, error) { 1413 stats, err := daemon.stats(container) 1414 if err != nil { 1415 return nil, err 1416 } 1417 1418 if stats.Networks, err = daemon.getNetworkStats(container); err != nil { 1419 return nil, err 1420 } 1421 1422 return stats, nil 1423 } 1424 1425 // Resolve Network SandboxID in case the container reuse another container's network stack 1426 func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) { 1427 curr := c 1428 for curr.HostConfig.NetworkMode.IsContainer() { 1429 containerID := curr.HostConfig.NetworkMode.ConnectedContainer() 1430 connected, err := daemon.GetContainer(containerID) 1431 if err != nil { 1432 return "", fmt.Errorf("Could not get container for %s", containerID) 1433 } 1434 curr = connected 1435 } 1436 return curr.NetworkSettings.SandboxID, nil 1437 } 1438 1439 func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) { 1440 sandboxID, err := daemon.getNetworkSandboxID(c) 1441 if err != nil { 1442 return nil, err 1443 } 1444 1445 sb, err := daemon.netController.SandboxByID(sandboxID) 1446 if err != nil { 1447 return nil, err 1448 } 1449 1450 lnstats, err := sb.Statistics() 1451 if err != nil { 1452 return nil, err 1453 } 1454 1455 stats := make(map[string]types.NetworkStats) 1456 // Convert libnetwork nw stats into engine-api stats 1457 for ifName, ifStats := range lnstats { 1458 stats[ifName] = types.NetworkStats{ 1459 RxBytes: ifStats.RxBytes, 1460 RxPackets: ifStats.RxPackets, 1461 RxErrors: ifStats.RxErrors, 1462 RxDropped: ifStats.RxDropped, 1463 TxBytes: ifStats.TxBytes, 1464 TxPackets: ifStats.TxPackets, 1465 TxErrors: ifStats.TxErrors, 1466 TxDropped: ifStats.TxDropped, 1467 } 1468 } 1469 1470 return stats, nil 1471 } 1472 1473 // newBaseContainer creates a new container with its initial 1474 // configuration based on the root storage from the daemon. 1475 func (daemon *Daemon) newBaseContainer(id string) *container.Container { 1476 return container.NewBaseContainer(id, daemon.containerRoot(id)) 1477 } 1478 1479 // initDiscovery initializes the discovery watcher for this daemon. 1480 func (daemon *Daemon) initDiscovery(config *Config) error { 1481 advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise) 1482 if err != nil { 1483 if err == errDiscoveryDisabled { 1484 return nil 1485 } 1486 return err 1487 } 1488 1489 config.ClusterAdvertise = advertise 1490 discoveryWatcher, err := initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts) 1491 if err != nil { 1492 return fmt.Errorf("discovery initialization failed (%v)", err) 1493 } 1494 1495 daemon.discoveryWatcher = discoveryWatcher 1496 return nil 1497 } 1498 1499 // Reload reads configuration changes and modifies the 1500 // daemon according to those changes. 1501 // These are the settings that Reload changes: 1502 // - Daemon labels. 1503 // - Daemon debug log level. 1504 // - Cluster discovery (reconfigure and restart). 1505 func (daemon *Daemon) Reload(config *Config) error { 1506 daemon.configStore.reloadLock.Lock() 1507 defer daemon.configStore.reloadLock.Unlock() 1508 if config.IsValueSet("label") { 1509 daemon.configStore.Labels = config.Labels 1510 } 1511 if config.IsValueSet("debug") { 1512 daemon.configStore.Debug = config.Debug 1513 } 1514 return daemon.reloadClusterDiscovery(config) 1515 } 1516 1517 func (daemon *Daemon) reloadClusterDiscovery(config *Config) error { 1518 var err error 1519 newAdvertise := daemon.configStore.ClusterAdvertise 1520 newClusterStore := daemon.configStore.ClusterStore 1521 if config.IsValueSet("cluster-advertise") { 1522 if config.IsValueSet("cluster-store") { 1523 newClusterStore = config.ClusterStore 1524 } 1525 newAdvertise, err = parseClusterAdvertiseSettings(newClusterStore, config.ClusterAdvertise) 1526 if err != nil && err != errDiscoveryDisabled { 1527 return err 1528 } 1529 } 1530 1531 // check discovery modifications 1532 if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) { 1533 return nil 1534 } 1535 1536 // enable discovery for the first time if it was not previously enabled 1537 if daemon.discoveryWatcher == nil { 1538 discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts) 1539 if err != nil { 1540 return fmt.Errorf("discovery initialization failed (%v)", err) 1541 } 1542 daemon.discoveryWatcher = discoveryWatcher 1543 } else { 1544 if err == errDiscoveryDisabled { 1545 // disable discovery if it was previously enabled and it's disabled now 1546 daemon.discoveryWatcher.Stop() 1547 } else { 1548 // reload discovery 1549 if err = daemon.discoveryWatcher.Reload(config.ClusterStore, newAdvertise, config.ClusterOpts); err != nil { 1550 return err 1551 } 1552 } 1553 } 1554 1555 daemon.configStore.ClusterStore = newClusterStore 1556 daemon.configStore.ClusterOpts = config.ClusterOpts 1557 daemon.configStore.ClusterAdvertise = newAdvertise 1558 1559 if daemon.netController == nil { 1560 return nil 1561 } 1562 netOptions, err := daemon.networkOptions(daemon.configStore) 1563 if err != nil { 1564 logrus.Warnf("Failed to reload configuration with network controller: %v", err) 1565 return nil 1566 } 1567 err = daemon.netController.ReloadConfiguration(netOptions...) 1568 if err != nil { 1569 logrus.Warnf("Failed to reload configuration with network controller: %v", err) 1570 } 1571 1572 return nil 1573 } 1574 1575 func validateID(id string) error { 1576 if id == "" { 1577 return fmt.Errorf("Invalid empty id") 1578 } 1579 return nil 1580 } 1581 1582 func isBridgeNetworkDisabled(config *Config) bool { 1583 return config.bridgeConfig.Iface == disableNetworkBridge 1584 } 1585 1586 func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) { 1587 options := []nwconfig.Option{} 1588 if dconfig == nil { 1589 return options, nil 1590 } 1591 1592 options = append(options, nwconfig.OptionDataDir(dconfig.Root)) 1593 1594 dd := runconfig.DefaultDaemonNetworkMode() 1595 dn := runconfig.DefaultDaemonNetworkMode().NetworkName() 1596 options = append(options, nwconfig.OptionDefaultDriver(string(dd))) 1597 options = append(options, nwconfig.OptionDefaultNetwork(dn)) 1598 1599 if strings.TrimSpace(dconfig.ClusterStore) != "" { 1600 kv := strings.Split(dconfig.ClusterStore, "://") 1601 if len(kv) != 2 { 1602 return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL") 1603 } 1604 options = append(options, nwconfig.OptionKVProvider(kv[0])) 1605 options = append(options, nwconfig.OptionKVProviderURL(kv[1])) 1606 } 1607 if len(dconfig.ClusterOpts) > 0 { 1608 options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts)) 1609 } 1610 1611 if daemon.discoveryWatcher != nil { 1612 options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher)) 1613 } 1614 1615 if dconfig.ClusterAdvertise != "" { 1616 options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise)) 1617 } 1618 1619 options = append(options, nwconfig.OptionLabels(dconfig.Labels)) 1620 options = append(options, driverOptions(dconfig)...) 1621 return options, nil 1622 } 1623 1624 func copyBlkioEntry(entries []*containerd.BlkioStatsEntry) []types.BlkioStatEntry { 1625 out := make([]types.BlkioStatEntry, len(entries)) 1626 for i, re := range entries { 1627 out[i] = types.BlkioStatEntry{ 1628 Major: re.Major, 1629 Minor: re.Minor, 1630 Op: re.Op, 1631 Value: re.Value, 1632 } 1633 } 1634 return out 1635 }