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