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