github.com/gondor/docker@v1.9.0-rc1/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 "errors" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "regexp" 16 "runtime" 17 "strings" 18 "sync" 19 "time" 20 21 "github.com/Sirupsen/logrus" 22 "github.com/docker/docker/api" 23 "github.com/docker/docker/api/types" 24 "github.com/docker/docker/cliconfig" 25 "github.com/docker/docker/daemon/events" 26 "github.com/docker/docker/daemon/execdriver" 27 "github.com/docker/docker/daemon/execdriver/execdrivers" 28 "github.com/docker/docker/daemon/graphdriver" 29 _ "github.com/docker/docker/daemon/graphdriver/vfs" // register vfs 30 "github.com/docker/docker/daemon/logger" 31 "github.com/docker/docker/daemon/network" 32 derr "github.com/docker/docker/errors" 33 "github.com/docker/docker/graph" 34 "github.com/docker/docker/image" 35 "github.com/docker/docker/pkg/archive" 36 "github.com/docker/docker/pkg/broadcaster" 37 "github.com/docker/docker/pkg/discovery" 38 "github.com/docker/docker/pkg/fileutils" 39 "github.com/docker/docker/pkg/graphdb" 40 "github.com/docker/docker/pkg/idtools" 41 "github.com/docker/docker/pkg/ioutils" 42 "github.com/docker/docker/pkg/namesgenerator" 43 "github.com/docker/docker/pkg/nat" 44 "github.com/docker/docker/pkg/parsers/filters" 45 "github.com/docker/docker/pkg/signal" 46 "github.com/docker/docker/pkg/stringid" 47 "github.com/docker/docker/pkg/stringutils" 48 "github.com/docker/docker/pkg/sysinfo" 49 "github.com/docker/docker/pkg/system" 50 "github.com/docker/docker/pkg/truncindex" 51 "github.com/docker/docker/registry" 52 "github.com/docker/docker/runconfig" 53 volumedrivers "github.com/docker/docker/volume/drivers" 54 "github.com/docker/docker/volume/local" 55 "github.com/docker/docker/volume/store" 56 "github.com/docker/libnetwork" 57 ) 58 59 var ( 60 validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` 61 validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`) 62 63 errSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.") 64 ) 65 66 type contStore struct { 67 s map[string]*Container 68 sync.Mutex 69 } 70 71 func (c *contStore) Add(id string, cont *Container) { 72 c.Lock() 73 c.s[id] = cont 74 c.Unlock() 75 } 76 77 func (c *contStore) Get(id string) *Container { 78 c.Lock() 79 res := c.s[id] 80 c.Unlock() 81 return res 82 } 83 84 func (c *contStore) Delete(id string) { 85 c.Lock() 86 delete(c.s, id) 87 c.Unlock() 88 } 89 90 func (c *contStore) List() []*Container { 91 containers := new(History) 92 c.Lock() 93 for _, cont := range c.s { 94 containers.Add(cont) 95 } 96 c.Unlock() 97 containers.sort() 98 return *containers 99 } 100 101 // Daemon holds information about the Docker daemon. 102 type Daemon struct { 103 ID string 104 repository string 105 sysInitPath string 106 containers *contStore 107 execCommands *execStore 108 graph *graph.Graph 109 repositories *graph.TagStore 110 idIndex *truncindex.TruncIndex 111 configStore *Config 112 containerGraphDB *graphdb.Database 113 driver graphdriver.Driver 114 execDriver execdriver.Driver 115 statsCollector *statsCollector 116 defaultLogConfig runconfig.LogConfig 117 RegistryService *registry.Service 118 EventsService *events.Events 119 netController libnetwork.NetworkController 120 volumes *store.VolumeStore 121 discoveryWatcher discovery.Watcher 122 root string 123 shutdown bool 124 uidMaps []idtools.IDMap 125 gidMaps []idtools.IDMap 126 } 127 128 // Get looks for a container using the provided information, which could be 129 // one of the following inputs from the caller: 130 // - A full container ID, which will exact match a container in daemon's list 131 // - A container name, which will only exact match via the GetByName() function 132 // - A partial container ID prefix (e.g. short ID) of any length that is 133 // unique enough to only return a single container object 134 // If none of these searches succeed, an error is returned 135 func (daemon *Daemon) Get(prefixOrName string) (*Container, error) { 136 if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { 137 // prefix is an exact match to a full container ID 138 return containerByID, nil 139 } 140 141 // GetByName will match only an exact name provided; we ignore errors 142 if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil { 143 // prefix is an exact match to a full container Name 144 return containerByName, nil 145 } 146 147 containerID, indexError := daemon.idIndex.Get(prefixOrName) 148 if indexError != nil { 149 // When truncindex defines an error type, use that instead 150 if strings.Contains(indexError.Error(), "no such id") { 151 return nil, derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName) 152 } 153 return nil, indexError 154 } 155 return daemon.containers.Get(containerID), nil 156 } 157 158 // Exists returns a true if a container of the specified ID or name exists, 159 // false otherwise. 160 func (daemon *Daemon) Exists(id string) bool { 161 c, _ := daemon.Get(id) 162 return c != nil 163 } 164 165 func (daemon *Daemon) containerRoot(id string) string { 166 return filepath.Join(daemon.repository, id) 167 } 168 169 // Load reads the contents of a container from disk 170 // This is typically done at startup. 171 func (daemon *Daemon) load(id string) (*Container, error) { 172 container := daemon.newBaseContainer(id) 173 174 if err := container.fromDisk(); err != nil { 175 return nil, err 176 } 177 178 if container.ID != id { 179 return &container, fmt.Errorf("Container %s is stored at %s", container.ID, id) 180 } 181 182 return &container, nil 183 } 184 185 // Register makes a container object usable by the daemon as <container.ID> 186 func (daemon *Daemon) Register(container *Container) error { 187 if container.daemon != nil || daemon.Exists(container.ID) { 188 return fmt.Errorf("Container is already loaded") 189 } 190 if err := validateID(container.ID); err != nil { 191 return err 192 } 193 if err := daemon.ensureName(container); err != nil { 194 return err 195 } 196 197 container.daemon = daemon 198 199 // Attach to stdout and stderr 200 container.stderr = new(broadcaster.Unbuffered) 201 container.stdout = new(broadcaster.Unbuffered) 202 // Attach to stdin 203 if container.Config.OpenStdin { 204 container.stdin, container.stdinPipe = io.Pipe() 205 } else { 206 container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin 207 } 208 // done 209 daemon.containers.Add(container.ID, container) 210 211 // don't update the Suffixarray if we're starting up 212 // we'll waste time if we update it for every container 213 daemon.idIndex.Add(container.ID) 214 215 if container.IsRunning() { 216 logrus.Debugf("killing old running container %s", container.ID) 217 // Set exit code to 128 + SIGKILL (9) to properly represent unsuccessful exit 218 container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137}) 219 // use the current driver and ensure that the container is dead x.x 220 cmd := &execdriver.Command{ 221 ID: container.ID, 222 } 223 daemon.execDriver.Terminate(cmd) 224 225 if err := container.unmountIpcMounts(); err != nil { 226 logrus.Errorf("%s: Failed to umount ipc filesystems: %v", container.ID, err) 227 } 228 if err := container.Unmount(); err != nil { 229 logrus.Debugf("unmount error %s", err) 230 } 231 if err := container.toDiskLocking(); err != nil { 232 logrus.Errorf("Error saving stopped state to disk: %v", err) 233 } 234 } 235 236 if err := daemon.verifyVolumesInfo(container); err != nil { 237 return err 238 } 239 240 if err := container.prepareMountPoints(); err != nil { 241 return err 242 } 243 244 return nil 245 } 246 247 func (daemon *Daemon) ensureName(container *Container) error { 248 if container.Name == "" { 249 name, err := daemon.generateNewName(container.ID) 250 if err != nil { 251 return err 252 } 253 container.Name = name 254 255 if err := container.toDiskLocking(); err != nil { 256 logrus.Errorf("Error saving container name to disk: %v", err) 257 } 258 } 259 return nil 260 } 261 262 func (daemon *Daemon) restore() error { 263 type cr struct { 264 container *Container 265 registered bool 266 } 267 268 var ( 269 debug = os.Getenv("DEBUG") != "" 270 currentDriver = daemon.driver.String() 271 containers = make(map[string]*cr) 272 ) 273 274 if !debug { 275 logrus.Info("Loading containers: start.") 276 } 277 dir, err := ioutil.ReadDir(daemon.repository) 278 if err != nil { 279 return err 280 } 281 282 for _, v := range dir { 283 id := v.Name() 284 container, err := daemon.load(id) 285 if !debug && logrus.GetLevel() == logrus.InfoLevel { 286 fmt.Print(".") 287 } 288 if err != nil { 289 logrus.Errorf("Failed to load container %v: %v", id, err) 290 continue 291 } 292 293 // Ignore the container if it does not support the current driver being used by the graph 294 if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { 295 logrus.Debugf("Loaded container %v", container.ID) 296 297 containers[container.ID] = &cr{container: container} 298 } else { 299 logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) 300 } 301 } 302 303 if entities := daemon.containerGraphDB.List("/", -1); entities != nil { 304 for _, p := range entities.Paths() { 305 if !debug && logrus.GetLevel() == logrus.InfoLevel { 306 fmt.Print(".") 307 } 308 309 e := entities[p] 310 311 if c, ok := containers[e.ID()]; ok { 312 c.registered = true 313 } 314 } 315 } 316 317 group := sync.WaitGroup{} 318 for _, c := range containers { 319 group.Add(1) 320 321 go func(container *Container, registered bool) { 322 defer group.Done() 323 324 if !registered { 325 // Try to set the default name for a container if it exists prior to links 326 container.Name, err = daemon.generateNewName(container.ID) 327 if err != nil { 328 logrus.Debugf("Setting default id - %s", err) 329 } 330 } 331 332 if err := daemon.Register(container); err != nil { 333 logrus.Errorf("Failed to register container %s: %s", container.ID, err) 334 // The container register failed should not be started. 335 return 336 } 337 338 // check the restart policy on the containers and restart any container with 339 // the restart policy of "always" 340 if daemon.configStore.AutoRestart && container.shouldRestart() { 341 logrus.Debugf("Starting container %s", container.ID) 342 343 if err := container.Start(); err != nil { 344 logrus.Errorf("Failed to start container %s: %s", container.ID, err) 345 } 346 } 347 }(c.container, c.registered) 348 } 349 group.Wait() 350 351 if !debug { 352 if logrus.GetLevel() == logrus.InfoLevel { 353 fmt.Println() 354 } 355 logrus.Info("Loading containers: done.") 356 } 357 358 return nil 359 } 360 361 func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error { 362 if img != nil && img.Config != nil { 363 if err := runconfig.Merge(config, img.Config); err != nil { 364 return err 365 } 366 } 367 if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 { 368 return fmt.Errorf("No command specified") 369 } 370 return nil 371 } 372 373 func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { 374 var ( 375 err error 376 id = stringid.GenerateNonCryptoID() 377 ) 378 379 if name == "" { 380 if name, err = daemon.generateNewName(id); err != nil { 381 return "", "", err 382 } 383 return id, name, nil 384 } 385 386 if name, err = daemon.reserveName(id, name); err != nil { 387 return "", "", err 388 } 389 390 return id, name, nil 391 } 392 393 func (daemon *Daemon) reserveName(id, name string) (string, error) { 394 if !validContainerNamePattern.MatchString(name) { 395 return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) 396 } 397 398 if name[0] != '/' { 399 name = "/" + name 400 } 401 402 if _, err := daemon.containerGraphDB.Set(name, id); err != nil { 403 if !graphdb.IsNonUniqueNameError(err) { 404 return "", err 405 } 406 407 conflictingContainer, err := daemon.GetByName(name) 408 if err != nil { 409 if strings.Contains(err.Error(), "Could not find entity") { 410 return "", err 411 } 412 413 // Remove name and continue starting the container 414 if err := daemon.containerGraphDB.Delete(name); err != nil { 415 return "", err 416 } 417 } else { 418 nameAsKnownByUser := strings.TrimPrefix(name, "/") 419 return "", fmt.Errorf( 420 "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.", nameAsKnownByUser, 421 stringid.TruncateID(conflictingContainer.ID)) 422 } 423 } 424 return name, nil 425 } 426 427 func (daemon *Daemon) generateNewName(id string) (string, error) { 428 var name string 429 for i := 0; i < 6; i++ { 430 name = namesgenerator.GetRandomName(i) 431 if name[0] != '/' { 432 name = "/" + name 433 } 434 435 if _, err := daemon.containerGraphDB.Set(name, id); err != nil { 436 if !graphdb.IsNonUniqueNameError(err) { 437 return "", err 438 } 439 continue 440 } 441 return name, nil 442 } 443 444 name = "/" + stringid.TruncateID(id) 445 if _, err := daemon.containerGraphDB.Set(name, id); err != nil { 446 return "", err 447 } 448 return name, nil 449 } 450 451 func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { 452 // Generate default hostname 453 // FIXME: the lxc template no longer needs to set a default hostname 454 if config.Hostname == "" { 455 config.Hostname = id[:12] 456 } 457 } 458 459 func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) { 460 var ( 461 entrypoint string 462 args []string 463 ) 464 465 cmdSlice := configCmd.Slice() 466 if configEntrypoint.Len() != 0 { 467 eSlice := configEntrypoint.Slice() 468 entrypoint = eSlice[0] 469 args = append(eSlice[1:], cmdSlice...) 470 } else { 471 entrypoint = cmdSlice[0] 472 args = cmdSlice[1:] 473 } 474 return entrypoint, args 475 } 476 477 func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) { 478 var ( 479 id string 480 err error 481 ) 482 id, name, err = daemon.generateIDAndName(name) 483 if err != nil { 484 return nil, err 485 } 486 487 daemon.generateHostname(id, config) 488 entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) 489 490 base := daemon.newBaseContainer(id) 491 base.Created = time.Now().UTC() 492 base.Path = entrypoint 493 base.Args = args //FIXME: de-duplicate from config 494 base.Config = config 495 base.hostConfig = &runconfig.HostConfig{} 496 base.ImageID = imgID 497 base.NetworkSettings = &network.Settings{} 498 base.Name = name 499 base.Driver = daemon.driver.String() 500 base.ExecDriver = daemon.execDriver.Name() 501 502 return &base, err 503 } 504 505 // GetFullContainerName returns a constructed container name. I think 506 // it has to do with the fact that a container is a file on disk and 507 // this is sort of just creating a file name. 508 func GetFullContainerName(name string) (string, error) { 509 if name == "" { 510 return "", fmt.Errorf("Container name cannot be empty") 511 } 512 if name[0] != '/' { 513 name = "/" + name 514 } 515 return name, nil 516 } 517 518 // GetByName returns a container given a name. 519 func (daemon *Daemon) GetByName(name string) (*Container, error) { 520 fullName, err := GetFullContainerName(name) 521 if err != nil { 522 return nil, err 523 } 524 entity := daemon.containerGraphDB.Get(fullName) 525 if entity == nil { 526 return nil, fmt.Errorf("Could not find entity for %s", name) 527 } 528 e := daemon.containers.Get(entity.ID()) 529 if e == nil { 530 return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID()) 531 } 532 return e, nil 533 } 534 535 // GetEventFilter returns a filters.Filter for a set of filters 536 func (daemon *Daemon) GetEventFilter(filter filters.Args) *events.Filter { 537 // incoming container filter can be name, id or partial id, convert to 538 // a full container id 539 for i, cn := range filter["container"] { 540 c, err := daemon.Get(cn) 541 if err != nil { 542 filter["container"][i] = "" 543 } else { 544 filter["container"][i] = c.ID 545 } 546 } 547 return events.NewFilter(filter, daemon.GetLabels) 548 } 549 550 // GetLabels for a container or image id 551 func (daemon *Daemon) GetLabels(id string) map[string]string { 552 // TODO: TestCase 553 container := daemon.containers.Get(id) 554 if container != nil { 555 return container.Config.Labels 556 } 557 558 img, err := daemon.repositories.LookupImage(id) 559 if err == nil { 560 return img.ContainerConfig.Labels 561 } 562 return nil 563 } 564 565 // children returns all child containers of the container with the 566 // given name. The containers are returned as a map from the container 567 // name to a pointer to Container. 568 func (daemon *Daemon) children(name string) (map[string]*Container, error) { 569 name, err := GetFullContainerName(name) 570 if err != nil { 571 return nil, err 572 } 573 children := make(map[string]*Container) 574 575 err = daemon.containerGraphDB.Walk(name, func(p string, e *graphdb.Entity) error { 576 c, err := daemon.Get(e.ID()) 577 if err != nil { 578 return err 579 } 580 children[p] = c 581 return nil 582 }, 0) 583 584 if err != nil { 585 return nil, err 586 } 587 return children, nil 588 } 589 590 // parents returns the names of the parent containers of the container 591 // with the given name. 592 func (daemon *Daemon) parents(name string) ([]string, error) { 593 name, err := GetFullContainerName(name) 594 if err != nil { 595 return nil, err 596 } 597 598 return daemon.containerGraphDB.Parents(name) 599 } 600 601 func (daemon *Daemon) registerLink(parent, child *Container, alias string) error { 602 fullName := filepath.Join(parent.Name, alias) 603 if !daemon.containerGraphDB.Exists(fullName) { 604 _, err := daemon.containerGraphDB.Set(fullName, child.ID) 605 return err 606 } 607 return nil 608 } 609 610 // NewDaemon sets up everything for the daemon to be able to service 611 // requests from the webserver. 612 func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { 613 setDefaultMtu(config) 614 615 // Ensure we have compatible configuration options 616 if err := checkConfigOptions(config); err != nil { 617 return nil, err 618 } 619 620 // Do we have a disabled network? 621 config.DisableBridge = isBridgeNetworkDisabled(config) 622 623 // Verify the platform is supported as a daemon 624 if !platformSupported { 625 return nil, errSystemNotSupported 626 } 627 628 // Validate platform-specific requirements 629 if err := checkSystem(); err != nil { 630 return nil, err 631 } 632 633 // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event 634 // on Windows to dump Go routine stacks 635 setupDumpStackTrap() 636 637 uidMaps, gidMaps, err := setupRemappedRoot(config) 638 if err != nil { 639 return nil, err 640 } 641 rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) 642 if err != nil { 643 return nil, err 644 } 645 646 // get the canonical path to the Docker root directory 647 var realRoot string 648 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 649 realRoot = config.Root 650 } else { 651 realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) 652 if err != nil { 653 return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 654 } 655 } 656 657 if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { 658 return nil, err 659 } 660 661 // set up the tmpDir to use a canonical path 662 tmp, err := tempDir(config.Root, rootUID, rootGID) 663 if err != nil { 664 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 665 } 666 realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) 667 if err != nil { 668 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 669 } 670 os.Setenv("TMPDIR", realTmp) 671 672 // Set the default driver 673 graphdriver.DefaultDriver = config.GraphDriver 674 675 // Load storage driver 676 driver, err := graphdriver.New(config.Root, config.GraphOptions, uidMaps, gidMaps) 677 if err != nil { 678 return nil, fmt.Errorf("error initializing graphdriver: %v", err) 679 } 680 logrus.Debugf("Using graph driver %s", driver) 681 682 d := &Daemon{} 683 d.driver = driver 684 685 // Ensure the graph driver is shutdown at a later point 686 defer func() { 687 if err != nil { 688 if err := d.Shutdown(); err != nil { 689 logrus.Error(err) 690 } 691 } 692 }() 693 694 // Verify logging driver type 695 if config.LogConfig.Type != "none" { 696 if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { 697 return nil, fmt.Errorf("error finding the logging driver: %v", err) 698 } 699 } 700 logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) 701 702 // Configure and validate the kernels security support 703 if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil { 704 return nil, err 705 } 706 707 daemonRepo := filepath.Join(config.Root, "containers") 708 709 if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { 710 return nil, err 711 } 712 713 // Migrate the container if it is aufs and aufs is enabled 714 if err := migrateIfDownlevel(d.driver, config.Root); err != nil { 715 return nil, err 716 } 717 718 logrus.Debug("Creating images graph") 719 g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver, uidMaps, gidMaps) 720 if err != nil { 721 return nil, err 722 } 723 724 // Configure the volumes driver 725 volStore, err := configureVolumes(config, rootUID, rootGID) 726 if err != nil { 727 return nil, err 728 } 729 730 trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) 731 if err != nil { 732 return nil, err 733 } 734 735 trustDir := filepath.Join(config.Root, "trust") 736 737 if err := system.MkdirAll(trustDir, 0700); err != nil { 738 return nil, err 739 } 740 741 eventsService := events.New() 742 logrus.Debug("Creating repository list") 743 tagCfg := &graph.TagStoreConfig{ 744 Graph: g, 745 Key: trustKey, 746 Registry: registryService, 747 Events: eventsService, 748 } 749 repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) 750 if err != nil { 751 return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err) 752 } 753 754 if restorer, ok := d.driver.(graphdriver.ImageRestorer); ok { 755 if _, err := restorer.RestoreCustomImages(repositories, g); err != nil { 756 return nil, fmt.Errorf("Couldn't restore custom images: %s", err) 757 } 758 } 759 760 // Discovery is only enabled when the daemon is launched with an address to advertise. When 761 // initialized, the daemon is registered and we can store the discovery backend as its read-only 762 // DiscoveryWatcher version. 763 if config.ClusterStore != "" && config.ClusterAdvertise != "" { 764 var err error 765 if d.discoveryWatcher, err = initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts); err != nil { 766 return nil, fmt.Errorf("discovery initialization failed (%v)", err) 767 } 768 } 769 770 d.netController, err = d.initNetworkController(config) 771 if err != nil { 772 return nil, fmt.Errorf("Error initializing network controller: %v", err) 773 } 774 775 graphdbPath := filepath.Join(config.Root, "linkgraph.db") 776 graph, err := graphdb.NewSqliteConn(graphdbPath) 777 if err != nil { 778 return nil, err 779 } 780 781 d.containerGraphDB = graph 782 783 var sysInitPath string 784 if config.ExecDriver == "lxc" { 785 initPath, err := configureSysInit(config, rootUID, rootGID) 786 if err != nil { 787 return nil, err 788 } 789 sysInitPath = initPath 790 } 791 792 sysInfo := sysinfo.New(false) 793 // Check if Devices cgroup is mounted, it is hard requirement for container security, 794 // on Linux/FreeBSD. 795 if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled { 796 return nil, fmt.Errorf("Devices cgroup isn't mounted") 797 } 798 799 ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo) 800 if err != nil { 801 return nil, err 802 } 803 804 d.ID = trustKey.PublicKey().KeyID() 805 d.repository = daemonRepo 806 d.containers = &contStore{s: make(map[string]*Container)} 807 d.execCommands = newExecStore() 808 d.graph = g 809 d.repositories = repositories 810 d.idIndex = truncindex.NewTruncIndex([]string{}) 811 d.configStore = config 812 d.sysInitPath = sysInitPath 813 d.execDriver = ed 814 d.statsCollector = newStatsCollector(1 * time.Second) 815 d.defaultLogConfig = config.LogConfig 816 d.RegistryService = registryService 817 d.EventsService = eventsService 818 d.volumes = volStore 819 d.root = config.Root 820 d.uidMaps = uidMaps 821 d.gidMaps = gidMaps 822 823 if err := d.cleanupMounts(); err != nil { 824 return nil, err 825 } 826 827 go d.execCommandGC() 828 829 if err := d.restore(); err != nil { 830 return nil, err 831 } 832 833 return d, nil 834 } 835 836 // Shutdown stops the daemon. 837 func (daemon *Daemon) Shutdown() error { 838 daemon.shutdown = true 839 if daemon.containers != nil { 840 group := sync.WaitGroup{} 841 logrus.Debug("starting clean shutdown of all containers...") 842 for _, container := range daemon.List() { 843 c := container 844 if c.IsRunning() { 845 logrus.Debugf("stopping %s", c.ID) 846 group.Add(1) 847 848 go func() { 849 defer group.Done() 850 // TODO(windows): Handle docker restart with paused containers 851 if c.isPaused() { 852 // To terminate a process in freezer cgroup, we should send 853 // SIGTERM to this process then unfreeze it, and the process will 854 // force to terminate immediately. 855 logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID) 856 sig, ok := signal.SignalMap["TERM"] 857 if !ok { 858 logrus.Warnf("System does not support SIGTERM") 859 return 860 } 861 if err := daemon.kill(c, int(sig)); err != nil { 862 logrus.Debugf("sending SIGTERM to container %s with error: %v", c.ID, err) 863 return 864 } 865 if err := c.unpause(); err != nil { 866 logrus.Debugf("Failed to unpause container %s with error: %v", c.ID, err) 867 return 868 } 869 if _, err := c.WaitStop(10 * time.Second); err != nil { 870 logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID) 871 sig, ok := signal.SignalMap["KILL"] 872 if !ok { 873 logrus.Warnf("System does not support SIGKILL") 874 return 875 } 876 daemon.kill(c, int(sig)) 877 } 878 } else { 879 // If container failed to exit in 10 seconds of SIGTERM, then using the force 880 if err := c.Stop(10); err != nil { 881 logrus.Errorf("Stop container %s with error: %v", c.ID, err) 882 } 883 } 884 c.WaitStop(-1 * time.Second) 885 logrus.Debugf("container stopped %s", c.ID) 886 }() 887 } 888 } 889 group.Wait() 890 891 // trigger libnetwork Stop only if it's initialized 892 if daemon.netController != nil { 893 daemon.netController.Stop() 894 } 895 } 896 897 if daemon.containerGraphDB != nil { 898 if err := daemon.containerGraphDB.Close(); err != nil { 899 logrus.Errorf("Error during container graph.Close(): %v", err) 900 } 901 } 902 903 if daemon.driver != nil { 904 if err := daemon.driver.Cleanup(); err != nil { 905 logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err) 906 } 907 } 908 909 if err := daemon.cleanupMounts(); err != nil { 910 return err 911 } 912 913 return nil 914 } 915 916 // Mount sets container.basefs 917 // (is it not set coming in? why is it unset?) 918 func (daemon *Daemon) Mount(container *Container) error { 919 dir, err := daemon.driver.Get(container.ID, container.getMountLabel()) 920 if err != nil { 921 return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) 922 } 923 924 if container.basefs != dir { 925 // The mount path reported by the graph driver should always be trusted on Windows, since the 926 // volume path for a given mounted layer may change over time. This should only be an error 927 // on non-Windows operating systems. 928 if container.basefs != "" && runtime.GOOS != "windows" { 929 daemon.driver.Put(container.ID) 930 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 931 daemon.driver, container.ID, container.basefs, dir) 932 } 933 } 934 container.basefs = dir 935 return nil 936 } 937 938 func (daemon *Daemon) unmount(container *Container) error { 939 daemon.driver.Put(container.ID) 940 return nil 941 } 942 943 func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) { 944 hooks := execdriver.Hooks{ 945 Start: startCallback, 946 } 947 hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error { 948 return c.setNetworkNamespaceKey(pid) 949 }) 950 return daemon.execDriver.Run(c.command, pipes, hooks) 951 } 952 953 func (daemon *Daemon) kill(c *Container, sig int) error { 954 return daemon.execDriver.Kill(c.command, sig) 955 } 956 957 func (daemon *Daemon) stats(c *Container) (*execdriver.ResourceStats, error) { 958 return daemon.execDriver.Stats(c.ID) 959 } 960 961 func (daemon *Daemon) subscribeToContainerStats(c *Container) (chan interface{}, error) { 962 ch := daemon.statsCollector.collect(c) 963 return ch, nil 964 } 965 966 func (daemon *Daemon) unsubscribeToContainerStats(c *Container, ch chan interface{}) error { 967 daemon.statsCollector.unsubscribe(c, ch) 968 return nil 969 } 970 971 func (daemon *Daemon) changes(container *Container) ([]archive.Change, error) { 972 initID := fmt.Sprintf("%s-init", container.ID) 973 return daemon.driver.Changes(container.ID, initID) 974 } 975 976 func (daemon *Daemon) diff(container *Container) (archive.Archive, error) { 977 initID := fmt.Sprintf("%s-init", container.ID) 978 return daemon.driver.Diff(container.ID, initID) 979 } 980 981 func (daemon *Daemon) createRootfs(container *Container) error { 982 // Step 1: create the container directory. 983 // This doubles as a barrier to avoid race conditions. 984 rootUID, rootGID, err := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) 985 if err != nil { 986 return err 987 } 988 if err := idtools.MkdirAs(container.root, 0700, rootUID, rootGID); err != nil { 989 return err 990 } 991 initID := fmt.Sprintf("%s-init", container.ID) 992 if err := daemon.driver.Create(initID, container.ImageID); err != nil { 993 return err 994 } 995 initPath, err := daemon.driver.Get(initID, "") 996 if err != nil { 997 return err 998 } 999 1000 if err := setupInitLayer(initPath, rootUID, rootGID); err != nil { 1001 daemon.driver.Put(initID) 1002 return err 1003 } 1004 1005 // We want to unmount init layer before we take snapshot of it 1006 // for the actual container. 1007 daemon.driver.Put(initID) 1008 1009 if err := daemon.driver.Create(container.ID, initID); err != nil { 1010 return err 1011 } 1012 return nil 1013 } 1014 1015 // Graph needs to be removed. 1016 // 1017 // FIXME: this is a convenience function for integration tests 1018 // which need direct access to daemon.graph. 1019 // Once the tests switch to using engine and jobs, this method 1020 // can go away. 1021 func (daemon *Daemon) Graph() *graph.Graph { 1022 return daemon.graph 1023 } 1024 1025 // TagImage creates a tag in the repository reponame, pointing to the image named 1026 // imageName. If force is true, an existing tag with the same name may be 1027 // overwritten. 1028 func (daemon *Daemon) TagImage(repoName, tag, imageName string, force bool) error { 1029 return daemon.repositories.Tag(repoName, tag, imageName, force) 1030 } 1031 1032 // PullImage initiates a pull operation. image is the repository name to pull, and 1033 // tag may be either empty, or indicate a specific tag to pull. 1034 func (daemon *Daemon) PullImage(image string, tag string, imagePullConfig *graph.ImagePullConfig) error { 1035 return daemon.repositories.Pull(image, tag, imagePullConfig) 1036 } 1037 1038 // ImportImage imports an image, getting the archived layer data either from 1039 // inConfig (if src is "-"), or from a URI specified in src. Progress output is 1040 // written to outStream. Repository and tag names can optionally be given in 1041 // the repo and tag arguments, respectively. 1042 func (daemon *Daemon) ImportImage(src, repo, tag, msg string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error { 1043 return daemon.repositories.Import(src, repo, tag, msg, inConfig, outStream, containerConfig) 1044 } 1045 1046 // ExportImage exports a list of images to the given output stream. The 1047 // exported images are archived into a tar when written to the output 1048 // stream. All images with the given tag and all versions containing 1049 // the same tag are exported. names is the set of tags to export, and 1050 // outStream is the writer which the images are written to. 1051 func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { 1052 return daemon.repositories.ImageExport(names, outStream) 1053 } 1054 1055 // PushImage initiates a push operation on the repository named localName. 1056 func (daemon *Daemon) PushImage(localName string, imagePushConfig *graph.ImagePushConfig) error { 1057 return daemon.repositories.Push(localName, imagePushConfig) 1058 } 1059 1060 // LookupImage looks up an image by name and returns it as an ImageInspect 1061 // structure. 1062 func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { 1063 return daemon.repositories.Lookup(name) 1064 } 1065 1066 // LoadImage uploads a set of images into the repository. This is the 1067 // complement of ImageExport. The input stream is an uncompressed tar 1068 // ball containing images and metadata. 1069 func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer) error { 1070 return daemon.repositories.Load(inTar, outStream) 1071 } 1072 1073 // ListImages returns a filtered list of images. filterArgs is a JSON-encoded set 1074 // of filter arguments which will be interpreted by pkg/parsers/filters. 1075 // filter is a shell glob string applied to repository names. The argument 1076 // named all controls whether all images in the graph are filtered, or just 1077 // the heads. 1078 func (daemon *Daemon) ListImages(filterArgs, filter string, all bool) ([]*types.Image, error) { 1079 return daemon.repositories.Images(filterArgs, filter, all) 1080 } 1081 1082 // ImageHistory returns a slice of ImageHistory structures for the specified image 1083 // name by walking the image lineage. 1084 func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) { 1085 return daemon.repositories.History(name) 1086 } 1087 1088 // GetImage returns pointer to an Image struct corresponding to the given 1089 // name. The name can include an optional tag; otherwise the default tag will 1090 // be used. 1091 func (daemon *Daemon) GetImage(name string) (*image.Image, error) { 1092 return daemon.repositories.LookupImage(name) 1093 } 1094 1095 func (daemon *Daemon) config() *Config { 1096 return daemon.configStore 1097 } 1098 1099 func (daemon *Daemon) systemInitPath() string { 1100 return daemon.sysInitPath 1101 } 1102 1103 // GraphDriver returns the currently used driver for processing 1104 // container layers. 1105 func (daemon *Daemon) GraphDriver() graphdriver.Driver { 1106 return daemon.driver 1107 } 1108 1109 // ExecutionDriver returns the currently used driver for creating and 1110 // starting execs in a container. 1111 func (daemon *Daemon) ExecutionDriver() execdriver.Driver { 1112 return daemon.execDriver 1113 } 1114 1115 func (daemon *Daemon) containerGraph() *graphdb.Database { 1116 return daemon.containerGraphDB 1117 } 1118 1119 // GetUIDGIDMaps returns the current daemon's user namespace settings 1120 // for the full uid and gid maps which will be applied to containers 1121 // started in this instance. 1122 func (daemon *Daemon) GetUIDGIDMaps() ([]idtools.IDMap, []idtools.IDMap) { 1123 return daemon.uidMaps, daemon.gidMaps 1124 } 1125 1126 // GetRemappedUIDGID returns the current daemon's uid and gid values 1127 // if user namespaces are in use for this daemon instance. If not 1128 // this function will return "real" root values of 0, 0. 1129 func (daemon *Daemon) GetRemappedUIDGID() (int, int) { 1130 uid, gid, _ := idtools.GetRootUIDGID(daemon.uidMaps, daemon.gidMaps) 1131 return uid, gid 1132 } 1133 1134 // ImageGetCached returns the earliest created image that is a child 1135 // of the image with imgID, that had the same config when it was 1136 // created. nil is returned if a child cannot be found. An error is 1137 // returned if the parent image cannot be found. 1138 func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) { 1139 // Retrieve all images 1140 images := daemon.Graph().Map() 1141 1142 // Store the tree in a map of map (map[parentId][childId]) 1143 imageMap := make(map[string]map[string]struct{}) 1144 for _, img := range images { 1145 if _, exists := imageMap[img.Parent]; !exists { 1146 imageMap[img.Parent] = make(map[string]struct{}) 1147 } 1148 imageMap[img.Parent][img.ID] = struct{}{} 1149 } 1150 1151 // Loop on the children of the given image and check the config 1152 var match *image.Image 1153 for elem := range imageMap[imgID] { 1154 img, ok := images[elem] 1155 if !ok { 1156 return nil, fmt.Errorf("unable to find image %q", elem) 1157 } 1158 if runconfig.Compare(&img.ContainerConfig, config) { 1159 if match == nil || match.Created.Before(img.Created) { 1160 match = img 1161 } 1162 } 1163 } 1164 return match, nil 1165 } 1166 1167 // tempDir returns the default directory to use for temporary files. 1168 func tempDir(rootDir string, rootUID, rootGID int) (string, error) { 1169 var tmpDir string 1170 if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 1171 tmpDir = filepath.Join(rootDir, "tmp") 1172 } 1173 return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) 1174 } 1175 1176 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error { 1177 container.Lock() 1178 if err := parseSecurityOpt(container, hostConfig); err != nil { 1179 container.Unlock() 1180 return err 1181 } 1182 container.Unlock() 1183 1184 // Do not lock while creating volumes since this could be calling out to external plugins 1185 // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin 1186 if err := daemon.registerMountPoints(container, hostConfig); err != nil { 1187 return err 1188 } 1189 1190 container.Lock() 1191 defer container.Unlock() 1192 // Register any links from the host config before starting the container 1193 if err := daemon.registerLinks(container, hostConfig); err != nil { 1194 return err 1195 } 1196 1197 container.hostConfig = hostConfig 1198 container.toDisk() 1199 return nil 1200 } 1201 1202 func setDefaultMtu(config *Config) { 1203 // do nothing if the config does not have the default 0 value. 1204 if config.Mtu != 0 { 1205 return 1206 } 1207 config.Mtu = defaultNetworkMtu 1208 if routeMtu, err := getDefaultRouteMtu(); err == nil { 1209 config.Mtu = routeMtu 1210 } 1211 } 1212 1213 var errNoDefaultRoute = errors.New("no default route was found") 1214 1215 // verifyContainerSettings performs validation of the hostconfig and config 1216 // structures. 1217 func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { 1218 1219 // First perform verification of settings common across all platforms. 1220 if config != nil { 1221 if config.WorkingDir != "" { 1222 config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics 1223 if !system.IsAbs(config.WorkingDir) { 1224 return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir) 1225 } 1226 } 1227 1228 if len(config.StopSignal) > 0 { 1229 _, err := signal.ParseSignal(config.StopSignal) 1230 if err != nil { 1231 return nil, err 1232 } 1233 } 1234 } 1235 1236 if hostConfig == nil { 1237 return nil, nil 1238 } 1239 1240 for port := range hostConfig.PortBindings { 1241 _, portStr := nat.SplitProtoPort(string(port)) 1242 if _, err := nat.ParsePort(portStr); err != nil { 1243 return nil, fmt.Errorf("Invalid port specification: %q", portStr) 1244 } 1245 for _, pb := range hostConfig.PortBindings[port] { 1246 _, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort)) 1247 if err != nil { 1248 return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort) 1249 } 1250 } 1251 } 1252 1253 // Now do platform-specific verification 1254 return verifyPlatformContainerSettings(daemon, hostConfig, config) 1255 } 1256 1257 func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) { 1258 volumesDriver, err := local.New(config.Root, rootUID, rootGID) 1259 if err != nil { 1260 return nil, err 1261 } 1262 1263 volumedrivers.Register(volumesDriver, volumesDriver.Name()) 1264 s := store.New() 1265 s.AddAll(volumesDriver.List()) 1266 1267 return s, nil 1268 } 1269 1270 // AuthenticateToRegistry checks the validity of credentials in authConfig 1271 func (daemon *Daemon) AuthenticateToRegistry(authConfig *cliconfig.AuthConfig) (string, error) { 1272 return daemon.RegistryService.Auth(authConfig) 1273 } 1274 1275 // SearchRegistryForImages queries the registry for images matching 1276 // term. authConfig is used to login. 1277 func (daemon *Daemon) SearchRegistryForImages(term string, 1278 authConfig *cliconfig.AuthConfig, 1279 headers map[string][]string) (*registry.SearchResults, error) { 1280 return daemon.RegistryService.Search(term, authConfig, headers) 1281 }