github.com/jandre/docker@v1.7.0/daemon/daemon.go (about) 1 package daemon 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net" 9 "os" 10 "path" 11 "path/filepath" 12 "regexp" 13 "runtime" 14 "strings" 15 "sync" 16 "time" 17 18 "github.com/docker/libcontainer/label" 19 "github.com/docker/libnetwork" 20 "github.com/docker/libnetwork/netlabel" 21 "github.com/docker/libnetwork/options" 22 23 "github.com/Sirupsen/logrus" 24 "github.com/docker/docker/api" 25 "github.com/docker/docker/autogen/dockerversion" 26 "github.com/docker/docker/daemon/events" 27 "github.com/docker/docker/daemon/execdriver" 28 "github.com/docker/docker/daemon/execdriver/execdrivers" 29 "github.com/docker/docker/daemon/graphdriver" 30 _ "github.com/docker/docker/daemon/graphdriver/vfs" 31 "github.com/docker/docker/daemon/logger" 32 "github.com/docker/docker/daemon/network" 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/broadcastwriter" 37 "github.com/docker/docker/pkg/fileutils" 38 "github.com/docker/docker/pkg/graphdb" 39 "github.com/docker/docker/pkg/ioutils" 40 "github.com/docker/docker/pkg/namesgenerator" 41 "github.com/docker/docker/pkg/parsers" 42 "github.com/docker/docker/pkg/parsers/kernel" 43 "github.com/docker/docker/pkg/stringid" 44 "github.com/docker/docker/pkg/sysinfo" 45 "github.com/docker/docker/pkg/truncindex" 46 "github.com/docker/docker/registry" 47 "github.com/docker/docker/runconfig" 48 "github.com/docker/docker/trust" 49 "github.com/docker/docker/utils" 50 volumedrivers "github.com/docker/docker/volume/drivers" 51 "github.com/docker/docker/volume/local" 52 "github.com/docker/libcontainer/netlink" 53 ) 54 55 var ( 56 validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` 57 validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`) 58 ) 59 60 type contStore struct { 61 s map[string]*Container 62 sync.Mutex 63 } 64 65 func (c *contStore) Add(id string, cont *Container) { 66 c.Lock() 67 c.s[id] = cont 68 c.Unlock() 69 } 70 71 func (c *contStore) Get(id string) *Container { 72 c.Lock() 73 res := c.s[id] 74 c.Unlock() 75 return res 76 } 77 78 func (c *contStore) Delete(id string) { 79 c.Lock() 80 delete(c.s, id) 81 c.Unlock() 82 } 83 84 func (c *contStore) List() []*Container { 85 containers := new(History) 86 c.Lock() 87 for _, cont := range c.s { 88 containers.Add(cont) 89 } 90 c.Unlock() 91 containers.Sort() 92 return *containers 93 } 94 95 type Daemon struct { 96 ID string 97 repository string 98 sysInitPath string 99 containers *contStore 100 execCommands *execStore 101 graph *graph.Graph 102 repositories *graph.TagStore 103 idIndex *truncindex.TruncIndex 104 sysInfo *sysinfo.SysInfo 105 config *Config 106 containerGraph *graphdb.Database 107 driver graphdriver.Driver 108 execDriver execdriver.Driver 109 statsCollector *statsCollector 110 defaultLogConfig runconfig.LogConfig 111 RegistryService *registry.Service 112 EventsService *events.Events 113 netController libnetwork.NetworkController 114 root string 115 } 116 117 // Get looks for a container using the provided information, which could be 118 // one of the following inputs from the caller: 119 // - A full container ID, which will exact match a container in daemon's list 120 // - A container name, which will only exact match via the GetByName() function 121 // - A partial container ID prefix (e.g. short ID) of any length that is 122 // unique enough to only return a single container object 123 // If none of these searches succeed, an error is returned 124 func (daemon *Daemon) Get(prefixOrName string) (*Container, error) { 125 if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil { 126 // prefix is an exact match to a full container ID 127 return containerByID, nil 128 } 129 130 // GetByName will match only an exact name provided; we ignore errors 131 containerByName, _ := daemon.GetByName(prefixOrName) 132 containerId, indexError := daemon.idIndex.Get(prefixOrName) 133 134 if containerByName != nil { 135 // prefix is an exact match to a full container Name 136 return containerByName, nil 137 } 138 139 if containerId != "" { 140 // prefix is a fuzzy match to a container ID 141 return daemon.containers.Get(containerId), nil 142 } 143 return nil, indexError 144 } 145 146 // Exists returns a true if a container of the specified ID or name exists, 147 // false otherwise. 148 func (daemon *Daemon) Exists(id string) bool { 149 c, _ := daemon.Get(id) 150 return c != nil 151 } 152 153 func (daemon *Daemon) containerRoot(id string) string { 154 return path.Join(daemon.repository, id) 155 } 156 157 // Load reads the contents of a container from disk 158 // This is typically done at startup. 159 func (daemon *Daemon) load(id string) (*Container, error) { 160 container := &Container{ 161 CommonContainer: daemon.newBaseContainer(id), 162 } 163 164 if err := container.FromDisk(); err != nil { 165 return nil, err 166 } 167 168 if container.ID != id { 169 return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) 170 } 171 172 return container, nil 173 } 174 175 // Register makes a container object usable by the daemon as <container.ID> 176 // This is a wrapper for register 177 func (daemon *Daemon) Register(container *Container) error { 178 return daemon.register(container, true) 179 } 180 181 // register makes a container object usable by the daemon as <container.ID> 182 func (daemon *Daemon) register(container *Container, updateSuffixarray bool) error { 183 if container.daemon != nil || daemon.Exists(container.ID) { 184 return fmt.Errorf("Container is already loaded") 185 } 186 if err := validateID(container.ID); err != nil { 187 return err 188 } 189 if err := daemon.ensureName(container); err != nil { 190 return err 191 } 192 193 container.daemon = daemon 194 195 // Attach to stdout and stderr 196 container.stderr = broadcastwriter.New() 197 container.stdout = broadcastwriter.New() 198 // Attach to stdin 199 if container.Config.OpenStdin { 200 container.stdin, container.stdinPipe = io.Pipe() 201 } else { 202 container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin 203 } 204 // done 205 daemon.containers.Add(container.ID, container) 206 207 // don't update the Suffixarray if we're starting up 208 // we'll waste time if we update it for every container 209 daemon.idIndex.Add(container.ID) 210 211 if err := daemon.verifyVolumesInfo(container); err != nil { 212 return err 213 } 214 215 if err := container.prepareMountPoints(); err != nil { 216 return err 217 } 218 219 if container.IsRunning() { 220 logrus.Debugf("killing old running container %s", container.ID) 221 222 container.SetStopped(&execdriver.ExitStatus{ExitCode: 0}) 223 224 // use the current driver and ensure that the container is dead x.x 225 cmd := &execdriver.Command{ 226 ID: container.ID, 227 } 228 daemon.execDriver.Terminate(cmd) 229 230 if err := container.Unmount(); err != nil { 231 logrus.Debugf("unmount error %s", err) 232 } 233 if err := container.ToDisk(); err != nil { 234 logrus.Debugf("saving stopped state to disk %s", err) 235 } 236 } 237 238 return nil 239 } 240 241 func (daemon *Daemon) ensureName(container *Container) error { 242 if container.Name == "" { 243 name, err := daemon.generateNewName(container.ID) 244 if err != nil { 245 return err 246 } 247 container.Name = name 248 249 if err := container.ToDisk(); err != nil { 250 logrus.Debugf("Error saving container name %s", err) 251 } 252 } 253 return nil 254 } 255 256 func (daemon *Daemon) restore() error { 257 type cr struct { 258 container *Container 259 registered bool 260 } 261 262 var ( 263 debug = (os.Getenv("DEBUG") != "" || os.Getenv("TEST") != "") 264 currentDriver = daemon.driver.String() 265 containers = make(map[string]*cr) 266 ) 267 268 if !debug { 269 logrus.Info("Loading containers: start.") 270 } 271 dir, err := ioutil.ReadDir(daemon.repository) 272 if err != nil { 273 return err 274 } 275 276 for _, v := range dir { 277 id := v.Name() 278 container, err := daemon.load(id) 279 if !debug && logrus.GetLevel() == logrus.InfoLevel { 280 fmt.Print(".") 281 } 282 if err != nil { 283 logrus.Errorf("Failed to load container %v: %v", id, err) 284 continue 285 } 286 287 // Ignore the container if it does not support the current driver being used by the graph 288 if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { 289 logrus.Debugf("Loaded container %v", container.ID) 290 291 containers[container.ID] = &cr{container: container} 292 } else { 293 logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) 294 } 295 } 296 297 if entities := daemon.containerGraph.List("/", -1); entities != nil { 298 for _, p := range entities.Paths() { 299 if !debug && logrus.GetLevel() == logrus.InfoLevel { 300 fmt.Print(".") 301 } 302 303 e := entities[p] 304 305 if c, ok := containers[e.ID()]; ok { 306 c.registered = true 307 } 308 } 309 } 310 311 group := sync.WaitGroup{} 312 for _, c := range containers { 313 group.Add(1) 314 315 go func(container *Container, registered bool) { 316 defer group.Done() 317 318 if !registered { 319 // Try to set the default name for a container if it exists prior to links 320 container.Name, err = daemon.generateNewName(container.ID) 321 if err != nil { 322 logrus.Debugf("Setting default id - %s", err) 323 } 324 } 325 326 if err := daemon.register(container, false); err != nil { 327 logrus.Debugf("Failed to register container %s: %s", container.ID, err) 328 } 329 330 // check the restart policy on the containers and restart any container with 331 // the restart policy of "always" 332 if daemon.config.AutoRestart && container.shouldRestart() { 333 logrus.Debugf("Starting container %s", container.ID) 334 335 if err := container.Start(); err != nil { 336 logrus.Debugf("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) checkDeprecatedExpose(config *runconfig.Config) bool { 354 if config != nil { 355 if config.PortSpecs != nil { 356 for _, p := range config.PortSpecs { 357 if strings.Contains(p, ":") { 358 return true 359 } 360 } 361 } 362 } 363 return false 364 } 365 366 func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) ([]string, error) { 367 warnings := []string{} 368 if (img != nil && daemon.checkDeprecatedExpose(img.Config)) || daemon.checkDeprecatedExpose(config) { 369 warnings = append(warnings, "The mapping to public ports on your host via Dockerfile EXPOSE (host:port:port) has been deprecated. Use -p to publish the ports.") 370 } 371 if img != nil && img.Config != nil { 372 if err := runconfig.Merge(config, img.Config); err != nil { 373 return nil, err 374 } 375 } 376 if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 { 377 return nil, fmt.Errorf("No command specified") 378 } 379 return warnings, nil 380 } 381 382 func (daemon *Daemon) generateIdAndName(name string) (string, string, error) { 383 var ( 384 err error 385 id = stringid.GenerateRandomID() 386 ) 387 388 if name == "" { 389 if name, err = daemon.generateNewName(id); err != nil { 390 return "", "", err 391 } 392 return id, name, nil 393 } 394 395 if name, err = daemon.reserveName(id, name); err != nil { 396 return "", "", err 397 } 398 399 return id, name, nil 400 } 401 402 func (daemon *Daemon) reserveName(id, name string) (string, error) { 403 if !validContainerNamePattern.MatchString(name) { 404 return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) 405 } 406 407 if name[0] != '/' { 408 name = "/" + name 409 } 410 411 if _, err := daemon.containerGraph.Set(name, id); err != nil { 412 if !graphdb.IsNonUniqueNameError(err) { 413 return "", err 414 } 415 416 conflictingContainer, err := daemon.GetByName(name) 417 if err != nil { 418 if strings.Contains(err.Error(), "Could not find entity") { 419 return "", err 420 } 421 422 // Remove name and continue starting the container 423 if err := daemon.containerGraph.Delete(name); err != nil { 424 return "", err 425 } 426 } else { 427 nameAsKnownByUser := strings.TrimPrefix(name, "/") 428 return "", fmt.Errorf( 429 "Conflict. The name %q is already in use by container %s. You have to delete (or rename) that container to be able to reuse that name.", nameAsKnownByUser, 430 stringid.TruncateID(conflictingContainer.ID)) 431 } 432 } 433 return name, nil 434 } 435 436 func (daemon *Daemon) generateNewName(id string) (string, error) { 437 var name string 438 for i := 0; i < 6; i++ { 439 name = namesgenerator.GetRandomName(i) 440 if name[0] != '/' { 441 name = "/" + name 442 } 443 444 if _, err := daemon.containerGraph.Set(name, id); err != nil { 445 if !graphdb.IsNonUniqueNameError(err) { 446 return "", err 447 } 448 continue 449 } 450 return name, nil 451 } 452 453 name = "/" + stringid.TruncateID(id) 454 if _, err := daemon.containerGraph.Set(name, id); err != nil { 455 return "", err 456 } 457 return name, nil 458 } 459 460 func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { 461 // Generate default hostname 462 // FIXME: the lxc template no longer needs to set a default hostname 463 if config.Hostname == "" { 464 config.Hostname = id[:12] 465 } 466 } 467 468 func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *runconfig.Entrypoint, configCmd *runconfig.Command) (string, []string) { 469 var ( 470 entrypoint string 471 args []string 472 ) 473 474 cmdSlice := configCmd.Slice() 475 if configEntrypoint.Len() != 0 { 476 eSlice := configEntrypoint.Slice() 477 entrypoint = eSlice[0] 478 args = append(eSlice[1:], cmdSlice...) 479 } else { 480 entrypoint = cmdSlice[0] 481 args = cmdSlice[1:] 482 } 483 return entrypoint, args 484 } 485 486 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error { 487 var ( 488 labelOpts []string 489 err error 490 ) 491 492 for _, opt := range config.SecurityOpt { 493 con := strings.SplitN(opt, ":", 2) 494 if len(con) == 1 { 495 return fmt.Errorf("Invalid --security-opt: %q", opt) 496 } 497 switch con[0] { 498 case "label": 499 labelOpts = append(labelOpts, con[1]) 500 case "apparmor": 501 container.AppArmorProfile = con[1] 502 default: 503 return fmt.Errorf("Invalid --security-opt: %q", opt) 504 } 505 } 506 507 container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts) 508 return err 509 } 510 511 func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) { 512 var ( 513 id string 514 err error 515 ) 516 id, name, err = daemon.generateIdAndName(name) 517 if err != nil { 518 return nil, err 519 } 520 521 daemon.generateHostname(id, config) 522 entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) 523 524 base := daemon.newBaseContainer(id) 525 base.Created = time.Now().UTC() 526 base.Path = entrypoint 527 base.Args = args //FIXME: de-duplicate from config 528 base.Config = config 529 base.hostConfig = &runconfig.HostConfig{} 530 base.ImageID = imgID 531 base.NetworkSettings = &network.Settings{} 532 base.Name = name 533 base.Driver = daemon.driver.String() 534 base.ExecDriver = daemon.execDriver.Name() 535 536 container := &Container{ 537 CommonContainer: base, 538 } 539 540 return container, err 541 } 542 543 func (daemon *Daemon) createRootfs(container *Container) error { 544 // Step 1: create the container directory. 545 // This doubles as a barrier to avoid race conditions. 546 if err := os.Mkdir(container.root, 0700); err != nil { 547 return err 548 } 549 initID := fmt.Sprintf("%s-init", container.ID) 550 if err := daemon.driver.Create(initID, container.ImageID); err != nil { 551 return err 552 } 553 initPath, err := daemon.driver.Get(initID, "") 554 if err != nil { 555 return err 556 } 557 defer daemon.driver.Put(initID) 558 559 if err := graph.SetupInitLayer(initPath); err != nil { 560 return err 561 } 562 563 if err := daemon.driver.Create(container.ID, initID); err != nil { 564 return err 565 } 566 return nil 567 } 568 569 func GetFullContainerName(name string) (string, error) { 570 if name == "" { 571 return "", fmt.Errorf("Container name cannot be empty") 572 } 573 if name[0] != '/' { 574 name = "/" + name 575 } 576 return name, nil 577 } 578 579 func (daemon *Daemon) GetByName(name string) (*Container, error) { 580 fullName, err := GetFullContainerName(name) 581 if err != nil { 582 return nil, err 583 } 584 entity := daemon.containerGraph.Get(fullName) 585 if entity == nil { 586 return nil, fmt.Errorf("Could not find entity for %s", name) 587 } 588 e := daemon.containers.Get(entity.ID()) 589 if e == nil { 590 return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID()) 591 } 592 return e, nil 593 } 594 595 func (daemon *Daemon) Children(name string) (map[string]*Container, error) { 596 name, err := GetFullContainerName(name) 597 if err != nil { 598 return nil, err 599 } 600 children := make(map[string]*Container) 601 602 err = daemon.containerGraph.Walk(name, func(p string, e *graphdb.Entity) error { 603 c, err := daemon.Get(e.ID()) 604 if err != nil { 605 return err 606 } 607 children[p] = c 608 return nil 609 }, 0) 610 611 if err != nil { 612 return nil, err 613 } 614 return children, nil 615 } 616 617 func (daemon *Daemon) Parents(name string) ([]string, error) { 618 name, err := GetFullContainerName(name) 619 if err != nil { 620 return nil, err 621 } 622 623 return daemon.containerGraph.Parents(name) 624 } 625 626 func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error { 627 fullName := path.Join(parent.Name, alias) 628 if !daemon.containerGraph.Exists(fullName) { 629 _, err := daemon.containerGraph.Set(fullName, child.ID) 630 return err 631 } 632 return nil 633 } 634 635 func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error { 636 if hostConfig != nil && hostConfig.Links != nil { 637 for _, l := range hostConfig.Links { 638 name, alias, err := parsers.ParseLink(l) 639 if err != nil { 640 return err 641 } 642 child, err := daemon.Get(name) 643 if err != nil { 644 //An error from daemon.Get() means this name could not be found 645 return fmt.Errorf("Could not get container for %s", name) 646 } 647 for child.hostConfig.NetworkMode.IsContainer() { 648 parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2) 649 child, err = daemon.Get(parts[1]) 650 if err != nil { 651 return fmt.Errorf("Could not get container for %s", parts[1]) 652 } 653 } 654 if child.hostConfig.NetworkMode.IsHost() { 655 return runconfig.ErrConflictHostNetworkAndLinks 656 } 657 if err := daemon.RegisterLink(container, child, alias); err != nil { 658 return err 659 } 660 } 661 662 // After we load all the links into the daemon 663 // set them to nil on the hostconfig 664 hostConfig.Links = nil 665 if err := container.WriteHostConfig(); err != nil { 666 return err 667 } 668 } 669 return nil 670 } 671 672 func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) { 673 // Check for mutually incompatible config options 674 if config.Bridge.Iface != "" && config.Bridge.IP != "" { 675 return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") 676 } 677 setDefaultMtu(config) 678 679 if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication { 680 return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") 681 } 682 if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq { 683 config.Bridge.EnableIPMasq = false 684 } 685 config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge 686 687 // Check that the system is supported and we have sufficient privileges 688 if runtime.GOOS != "linux" { 689 return nil, fmt.Errorf("The Docker daemon is only supported on linux") 690 } 691 if os.Geteuid() != 0 { 692 return nil, fmt.Errorf("The Docker daemon needs to be run as root") 693 } 694 if err := checkKernel(); err != nil { 695 return nil, err 696 } 697 698 // set up SIGUSR1 handler to dump Go routine stacks 699 setupSigusr1Trap() 700 701 // set up the tmpDir to use a canonical path 702 tmp, err := tempDir(config.Root) 703 if err != nil { 704 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 705 } 706 realTmp, err := fileutils.ReadSymlinkedDirectory(tmp) 707 if err != nil { 708 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 709 } 710 os.Setenv("TMPDIR", realTmp) 711 712 // get the canonical path to the Docker root directory 713 var realRoot string 714 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 715 realRoot = config.Root 716 } else { 717 realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root) 718 if err != nil { 719 return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 720 } 721 } 722 config.Root = realRoot 723 // Create the root directory if it doesn't exists 724 if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { 725 return nil, err 726 } 727 728 // Set the default driver 729 graphdriver.DefaultDriver = config.GraphDriver 730 731 // Load storage driver 732 driver, err := graphdriver.New(config.Root, config.GraphOptions) 733 if err != nil { 734 return nil, fmt.Errorf("error initializing graphdriver: %v", err) 735 } 736 logrus.Debugf("Using graph driver %s", driver) 737 738 d := &Daemon{} 739 d.driver = driver 740 741 defer func() { 742 if err != nil { 743 if err := d.Shutdown(); err != nil { 744 logrus.Error(err) 745 } 746 } 747 }() 748 749 // Verify logging driver type 750 if config.LogConfig.Type != "none" { 751 if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil { 752 return nil, fmt.Errorf("error finding the logging driver: %v", err) 753 } 754 } 755 logrus.Debugf("Using default logging driver %s", config.LogConfig.Type) 756 757 if config.EnableSelinuxSupport { 758 if selinuxEnabled() { 759 // As Docker on btrfs and SELinux are incompatible at present, error on both being enabled 760 if d.driver.String() == "btrfs" { 761 return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver") 762 } 763 logrus.Debug("SELinux enabled successfully") 764 } else { 765 logrus.Warn("Docker could not enable SELinux on the host system") 766 } 767 } else { 768 selinuxSetDisabled() 769 } 770 771 daemonRepo := path.Join(config.Root, "containers") 772 773 if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) { 774 return nil, err 775 } 776 777 // Migrate the container if it is aufs and aufs is enabled 778 if err := migrateIfAufs(d.driver, config.Root); err != nil { 779 return nil, err 780 } 781 782 logrus.Debug("Creating images graph") 783 g, err := graph.NewGraph(path.Join(config.Root, "graph"), d.driver) 784 if err != nil { 785 return nil, err 786 } 787 788 volumesDriver, err := local.New(config.Root) 789 if err != nil { 790 return nil, err 791 } 792 volumedrivers.Register(volumesDriver, volumesDriver.Name()) 793 794 trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) 795 if err != nil { 796 return nil, err 797 } 798 799 trustDir := path.Join(config.Root, "trust") 800 if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { 801 return nil, err 802 } 803 trustService, err := trust.NewTrustStore(trustDir) 804 if err != nil { 805 return nil, fmt.Errorf("could not create trust store: %s", err) 806 } 807 808 eventsService := events.New() 809 logrus.Debug("Creating repository list") 810 tagCfg := &graph.TagStoreConfig{ 811 Graph: g, 812 Key: trustKey, 813 Registry: registryService, 814 Events: eventsService, 815 Trust: trustService, 816 } 817 repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+d.driver.String()), tagCfg) 818 if err != nil { 819 return nil, fmt.Errorf("Couldn't create Tag store: %s", err) 820 } 821 822 if !config.DisableNetwork { 823 d.netController, err = initNetworkController(config) 824 if err != nil { 825 return nil, fmt.Errorf("Error initializing network controller: %v", err) 826 } 827 } 828 829 graphdbPath := path.Join(config.Root, "linkgraph.db") 830 graph, err := graphdb.NewSqliteConn(graphdbPath) 831 if err != nil { 832 return nil, err 833 } 834 835 d.containerGraph = graph 836 837 localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) 838 sysInitPath := utils.DockerInitPath(localCopy) 839 if sysInitPath == "" { 840 return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/contributing/devenvironment for official build instructions.") 841 } 842 843 if sysInitPath != localCopy { 844 // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). 845 if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { 846 return nil, err 847 } 848 if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil { 849 return nil, err 850 } 851 if err := os.Chmod(localCopy, 0700); err != nil { 852 return nil, err 853 } 854 sysInitPath = localCopy 855 } 856 857 sysInfo := sysinfo.New(false) 858 ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo) 859 if err != nil { 860 return nil, err 861 } 862 863 d.ID = trustKey.PublicKey().KeyID() 864 d.repository = daemonRepo 865 d.containers = &contStore{s: make(map[string]*Container)} 866 d.execCommands = newExecStore() 867 d.graph = g 868 d.repositories = repositories 869 d.idIndex = truncindex.NewTruncIndex([]string{}) 870 d.sysInfo = sysInfo 871 d.config = config 872 d.sysInitPath = sysInitPath 873 d.execDriver = ed 874 d.statsCollector = newStatsCollector(1 * time.Second) 875 d.defaultLogConfig = config.LogConfig 876 d.RegistryService = registryService 877 d.EventsService = eventsService 878 d.root = config.Root 879 880 if err := d.restore(); err != nil { 881 return nil, err 882 } 883 884 return d, nil 885 } 886 887 func initNetworkController(config *Config) (libnetwork.NetworkController, error) { 888 controller, err := libnetwork.New() 889 if err != nil { 890 return nil, fmt.Errorf("error obtaining controller instance: %v", err) 891 } 892 893 // Initialize default driver "null" 894 895 if err := controller.ConfigureNetworkDriver("null", options.Generic{}); err != nil { 896 return nil, fmt.Errorf("Error initializing null driver: %v", err) 897 } 898 899 // Initialize default network on "null" 900 if _, err := controller.NewNetwork("null", "none"); err != nil { 901 return nil, fmt.Errorf("Error creating default \"null\" network: %v", err) 902 } 903 904 // Initialize default driver "host" 905 if err := controller.ConfigureNetworkDriver("host", options.Generic{}); err != nil { 906 return nil, fmt.Errorf("Error initializing host driver: %v", err) 907 } 908 909 // Initialize default network on "host" 910 if _, err := controller.NewNetwork("host", "host"); err != nil { 911 return nil, fmt.Errorf("Error creating default \"host\" network: %v", err) 912 } 913 914 // Initialize default driver "bridge" 915 option := options.Generic{ 916 "EnableIPForwarding": config.Bridge.EnableIPForward} 917 918 if err := controller.ConfigureNetworkDriver("bridge", options.Generic{netlabel.GenericData: option}); err != nil { 919 return nil, fmt.Errorf("Error initializing bridge driver: %v", err) 920 } 921 922 netOption := options.Generic{ 923 "BridgeName": config.Bridge.Iface, 924 "Mtu": config.Mtu, 925 "EnableIPTables": config.Bridge.EnableIPTables, 926 "EnableIPMasquerade": config.Bridge.EnableIPMasq, 927 "EnableICC": config.Bridge.InterContainerCommunication, 928 "EnableUserlandProxy": config.Bridge.EnableUserlandProxy, 929 } 930 931 if config.Bridge.IP != "" { 932 ip, bipNet, err := net.ParseCIDR(config.Bridge.IP) 933 if err != nil { 934 return nil, err 935 } 936 937 bipNet.IP = ip 938 netOption["AddressIPv4"] = bipNet 939 } 940 941 if config.Bridge.FixedCIDR != "" { 942 _, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR) 943 if err != nil { 944 return nil, err 945 } 946 947 netOption["FixedCIDR"] = fCIDR 948 } 949 950 if config.Bridge.FixedCIDRv6 != "" { 951 _, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6) 952 if err != nil { 953 return nil, err 954 } 955 956 netOption["FixedCIDRv6"] = fCIDRv6 957 } 958 959 if config.Bridge.DefaultGatewayIPv4 != nil { 960 netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4 961 } 962 963 if config.Bridge.DefaultGatewayIPv6 != nil { 964 netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6 965 } 966 967 // --ip processing 968 if config.Bridge.DefaultIP != nil { 969 netOption["DefaultBindingIP"] = config.Bridge.DefaultIP 970 } 971 972 // Initialize default network on "bridge" with the same name 973 _, err = controller.NewNetwork("bridge", "bridge", 974 libnetwork.NetworkOptionGeneric(options.Generic{ 975 netlabel.GenericData: netOption, 976 netlabel.EnableIPv6: config.Bridge.EnableIPv6, 977 })) 978 if err != nil { 979 return nil, fmt.Errorf("Error creating default \"bridge\" network: %v", err) 980 } 981 982 return controller, nil 983 } 984 985 func (daemon *Daemon) Shutdown() error { 986 if daemon.containers != nil { 987 group := sync.WaitGroup{} 988 logrus.Debug("starting clean shutdown of all containers...") 989 for _, container := range daemon.List() { 990 c := container 991 if c.IsRunning() { 992 logrus.Debugf("stopping %s", c.ID) 993 group.Add(1) 994 995 go func() { 996 defer group.Done() 997 // If container failed to exit in 10 seconds of SIGTERM, then using the force 998 if err := c.Stop(10); err != nil { 999 logrus.Errorf("Stop container %s with error: %v", c.ID, err) 1000 } 1001 c.WaitStop(-1 * time.Second) 1002 logrus.Debugf("container stopped %s", c.ID) 1003 }() 1004 } 1005 } 1006 group.Wait() 1007 1008 // trigger libnetwork GC only if it's initialized 1009 if daemon.netController != nil { 1010 daemon.netController.GC() 1011 } 1012 } 1013 1014 if daemon.containerGraph != nil { 1015 if err := daemon.containerGraph.Close(); err != nil { 1016 logrus.Errorf("Error during container graph.Close(): %v", err) 1017 } 1018 } 1019 1020 if daemon.driver != nil { 1021 if err := daemon.driver.Cleanup(); err != nil { 1022 logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err) 1023 } 1024 } 1025 1026 return nil 1027 } 1028 1029 func (daemon *Daemon) Mount(container *Container) error { 1030 dir, err := daemon.driver.Get(container.ID, container.GetMountLabel()) 1031 if err != nil { 1032 return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) 1033 } 1034 if container.basefs == "" { 1035 container.basefs = dir 1036 } else if container.basefs != dir { 1037 daemon.driver.Put(container.ID) 1038 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 1039 daemon.driver, container.ID, container.basefs, dir) 1040 } 1041 return nil 1042 } 1043 1044 func (daemon *Daemon) Unmount(container *Container) error { 1045 daemon.driver.Put(container.ID) 1046 return nil 1047 } 1048 1049 func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) { 1050 initID := fmt.Sprintf("%s-init", container.ID) 1051 return daemon.driver.Changes(container.ID, initID) 1052 } 1053 1054 func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) { 1055 initID := fmt.Sprintf("%s-init", container.ID) 1056 return daemon.driver.Diff(container.ID, initID) 1057 } 1058 1059 func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { 1060 return daemon.execDriver.Run(c.command, pipes, startCallback) 1061 } 1062 1063 func (daemon *Daemon) Kill(c *Container, sig int) error { 1064 return daemon.execDriver.Kill(c.command, sig) 1065 } 1066 1067 func (daemon *Daemon) Stats(c *Container) (*execdriver.ResourceStats, error) { 1068 return daemon.execDriver.Stats(c.ID) 1069 } 1070 1071 func (daemon *Daemon) SubscribeToContainerStats(name string) (chan interface{}, error) { 1072 c, err := daemon.Get(name) 1073 if err != nil { 1074 return nil, err 1075 } 1076 ch := daemon.statsCollector.collect(c) 1077 return ch, nil 1078 } 1079 1080 func (daemon *Daemon) UnsubscribeToContainerStats(name string, ch chan interface{}) error { 1081 c, err := daemon.Get(name) 1082 if err != nil { 1083 return err 1084 } 1085 daemon.statsCollector.unsubscribe(c, ch) 1086 return nil 1087 } 1088 1089 // FIXME: this is a convenience function for integration tests 1090 // which need direct access to daemon.graph. 1091 // Once the tests switch to using engine and jobs, this method 1092 // can go away. 1093 func (daemon *Daemon) Graph() *graph.Graph { 1094 return daemon.graph 1095 } 1096 1097 func (daemon *Daemon) Repositories() *graph.TagStore { 1098 return daemon.repositories 1099 } 1100 1101 func (daemon *Daemon) Config() *Config { 1102 return daemon.config 1103 } 1104 1105 func (daemon *Daemon) SystemConfig() *sysinfo.SysInfo { 1106 return daemon.sysInfo 1107 } 1108 1109 func (daemon *Daemon) SystemInitPath() string { 1110 return daemon.sysInitPath 1111 } 1112 1113 func (daemon *Daemon) GraphDriver() graphdriver.Driver { 1114 return daemon.driver 1115 } 1116 1117 func (daemon *Daemon) ExecutionDriver() execdriver.Driver { 1118 return daemon.execDriver 1119 } 1120 1121 func (daemon *Daemon) ContainerGraph() *graphdb.Database { 1122 return daemon.containerGraph 1123 } 1124 1125 func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) { 1126 // Retrieve all images 1127 images, err := daemon.Graph().Map() 1128 if err != nil { 1129 return nil, err 1130 } 1131 1132 // Store the tree in a map of map (map[parentId][childId]) 1133 imageMap := make(map[string]map[string]struct{}) 1134 for _, img := range images { 1135 if _, exists := imageMap[img.Parent]; !exists { 1136 imageMap[img.Parent] = make(map[string]struct{}) 1137 } 1138 imageMap[img.Parent][img.ID] = struct{}{} 1139 } 1140 1141 // Loop on the children of the given image and check the config 1142 var match *image.Image 1143 for elem := range imageMap[imgID] { 1144 img, ok := images[elem] 1145 if !ok { 1146 return nil, fmt.Errorf("unable to find image %q", elem) 1147 } 1148 if runconfig.Compare(&img.ContainerConfig, config) { 1149 if match == nil || match.Created.Before(img.Created) { 1150 match = img 1151 } 1152 } 1153 } 1154 return match, nil 1155 } 1156 1157 // tempDir returns the default directory to use for temporary files. 1158 func tempDir(rootDir string) (string, error) { 1159 var tmpDir string 1160 if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 1161 tmpDir = filepath.Join(rootDir, "tmp") 1162 } 1163 return tmpDir, os.MkdirAll(tmpDir, 0700) 1164 } 1165 1166 func checkKernel() error { 1167 // Check for unsupported kernel versions 1168 // FIXME: it would be cleaner to not test for specific versions, but rather 1169 // test for specific functionalities. 1170 // Unfortunately we can't test for the feature "does not cause a kernel panic" 1171 // without actually causing a kernel panic, so we need this workaround until 1172 // the circumstances of pre-3.10 crashes are clearer. 1173 // For details see https://github.com/docker/docker/issues/407 1174 if k, err := kernel.GetKernelVersion(); err != nil { 1175 logrus.Warnf("%s", err) 1176 } else { 1177 if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 10, Minor: 0}) < 0 { 1178 if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" { 1179 logrus.Warnf("You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.10.0.", k.String()) 1180 } 1181 } 1182 } 1183 return nil 1184 } 1185 1186 func (daemon *Daemon) verifyHostConfig(hostConfig *runconfig.HostConfig) ([]string, error) { 1187 var warnings []string 1188 1189 if hostConfig == nil { 1190 return warnings, nil 1191 } 1192 1193 if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") { 1194 return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name()) 1195 } 1196 if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { 1197 return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") 1198 } 1199 if hostConfig.Memory > 0 && !daemon.SystemConfig().MemoryLimit { 1200 warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") 1201 hostConfig.Memory = 0 1202 } 1203 if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !daemon.SystemConfig().SwapLimit { 1204 warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.") 1205 hostConfig.MemorySwap = -1 1206 } 1207 if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory { 1208 return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") 1209 } 1210 if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 { 1211 return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") 1212 } 1213 if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod { 1214 warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") 1215 hostConfig.CpuPeriod = 0 1216 } 1217 if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota { 1218 warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") 1219 hostConfig.CpuQuota = 0 1220 } 1221 if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { 1222 return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") 1223 } 1224 if hostConfig.OomKillDisable && !daemon.SystemConfig().OomKillDisable { 1225 hostConfig.OomKillDisable = false 1226 return warnings, fmt.Errorf("Your kernel does not support oom kill disable.") 1227 } 1228 1229 return warnings, nil 1230 } 1231 1232 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error { 1233 container.Lock() 1234 if err := parseSecurityOpt(container, hostConfig); err != nil { 1235 container.Unlock() 1236 return err 1237 } 1238 container.Unlock() 1239 1240 // Do not lock while creating volumes since this could be calling out to external plugins 1241 // Don't want to block other actions, like `docker ps` because we're waiting on an external plugin 1242 if err := daemon.registerMountPoints(container, hostConfig); err != nil { 1243 return err 1244 } 1245 1246 container.Lock() 1247 defer container.Unlock() 1248 // Register any links from the host config before starting the container 1249 if err := daemon.RegisterLinks(container, hostConfig); err != nil { 1250 return err 1251 } 1252 1253 container.hostConfig = hostConfig 1254 container.toDisk() 1255 return nil 1256 } 1257 1258 func (daemon *Daemon) newBaseContainer(id string) CommonContainer { 1259 return CommonContainer{ 1260 ID: id, 1261 State: NewState(), 1262 MountPoints: make(map[string]*mountPoint), 1263 Volumes: make(map[string]string), 1264 VolumesRW: make(map[string]bool), 1265 execCommands: newExecStore(), 1266 root: daemon.containerRoot(id), 1267 } 1268 } 1269 1270 func setDefaultMtu(config *Config) { 1271 // do nothing if the config does not have the default 0 value. 1272 if config.Mtu != 0 { 1273 return 1274 } 1275 config.Mtu = defaultNetworkMtu 1276 if routeMtu, err := getDefaultRouteMtu(); err == nil { 1277 config.Mtu = routeMtu 1278 } 1279 } 1280 1281 var errNoDefaultRoute = errors.New("no default route was found") 1282 1283 // getDefaultRouteMtu returns the MTU for the default route's interface. 1284 func getDefaultRouteMtu() (int, error) { 1285 routes, err := netlink.NetworkGetRoutes() 1286 if err != nil { 1287 return 0, err 1288 } 1289 for _, r := range routes { 1290 if r.Default { 1291 return r.Iface.MTU, nil 1292 } 1293 } 1294 return 0, errNoDefaultRoute 1295 }