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