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