github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/daemon/daemon.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path" 9 "regexp" 10 "runtime" 11 "strings" 12 "sync" 13 "time" 14 15 "github.com/docker/libcontainer/label" 16 17 log "github.com/Sirupsen/logrus" 18 "github.com/docker/docker/api" 19 "github.com/docker/docker/daemon/execdriver" 20 "github.com/docker/docker/daemon/execdriver/execdrivers" 21 "github.com/docker/docker/daemon/execdriver/lxc" 22 "github.com/docker/docker/daemon/graphdriver" 23 _ "github.com/docker/docker/daemon/graphdriver/vfs" 24 _ "github.com/docker/docker/daemon/networkdriver/bridge" 25 "github.com/docker/docker/daemon/networkdriver/portallocator" 26 "github.com/docker/docker/dockerversion" 27 "github.com/docker/docker/engine" 28 "github.com/docker/docker/graph" 29 "github.com/docker/docker/image" 30 "github.com/docker/docker/pkg/archive" 31 "github.com/docker/docker/pkg/broadcastwriter" 32 "github.com/docker/docker/pkg/graphdb" 33 "github.com/docker/docker/pkg/ioutils" 34 "github.com/docker/docker/pkg/namesgenerator" 35 "github.com/docker/docker/pkg/parsers" 36 "github.com/docker/docker/pkg/parsers/kernel" 37 "github.com/docker/docker/pkg/sysinfo" 38 "github.com/docker/docker/pkg/truncindex" 39 "github.com/docker/docker/runconfig" 40 "github.com/docker/docker/trust" 41 "github.com/docker/docker/utils" 42 "github.com/docker/docker/volumes" 43 ) 44 45 var ( 46 DefaultDns = []string{"8.8.8.8", "8.8.4.4"} 47 validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` 48 validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`) 49 ) 50 51 type contStore struct { 52 s map[string]*Container 53 sync.Mutex 54 } 55 56 func (c *contStore) Add(id string, cont *Container) { 57 c.Lock() 58 c.s[id] = cont 59 c.Unlock() 60 } 61 62 func (c *contStore) Get(id string) *Container { 63 c.Lock() 64 res := c.s[id] 65 c.Unlock() 66 return res 67 } 68 69 func (c *contStore) Delete(id string) { 70 c.Lock() 71 delete(c.s, id) 72 c.Unlock() 73 } 74 75 func (c *contStore) List() []*Container { 76 containers := new(History) 77 c.Lock() 78 for _, cont := range c.s { 79 containers.Add(cont) 80 } 81 c.Unlock() 82 containers.Sort() 83 return *containers 84 } 85 86 type Daemon struct { 87 ID string 88 repository string 89 sysInitPath string 90 containers *contStore 91 execCommands *execStore 92 graph *graph.Graph 93 repositories *graph.TagStore 94 idIndex *truncindex.TruncIndex 95 sysInfo *sysinfo.SysInfo 96 volumes *volumes.Repository 97 eng *engine.Engine 98 config *Config 99 containerGraph *graphdb.Database 100 driver graphdriver.Driver 101 execDriver execdriver.Driver 102 trustStore *trust.TrustStore 103 } 104 105 // Install installs daemon capabilities to eng. 106 func (daemon *Daemon) Install(eng *engine.Engine) error { 107 // FIXME: remove ImageDelete's dependency on Daemon, then move to graph/ 108 for name, method := range map[string]engine.Handler{ 109 "attach": daemon.ContainerAttach, 110 "commit": daemon.ContainerCommit, 111 "container_changes": daemon.ContainerChanges, 112 "container_copy": daemon.ContainerCopy, 113 "container_inspect": daemon.ContainerInspect, 114 "containers": daemon.Containers, 115 "create": daemon.ContainerCreate, 116 "rm": daemon.ContainerRm, 117 "export": daemon.ContainerExport, 118 "info": daemon.CmdInfo, 119 "kill": daemon.ContainerKill, 120 "logs": daemon.ContainerLogs, 121 "pause": daemon.ContainerPause, 122 "resize": daemon.ContainerResize, 123 "restart": daemon.ContainerRestart, 124 "start": daemon.ContainerStart, 125 "stop": daemon.ContainerStop, 126 "top": daemon.ContainerTop, 127 "unpause": daemon.ContainerUnpause, 128 "wait": daemon.ContainerWait, 129 "image_delete": daemon.ImageDelete, // FIXME: see above 130 "execCreate": daemon.ContainerExecCreate, 131 "execStart": daemon.ContainerExecStart, 132 "execResize": daemon.ContainerExecResize, 133 "execInspect": daemon.ContainerExecInspect, 134 } { 135 if err := eng.Register(name, method); err != nil { 136 return err 137 } 138 } 139 if err := daemon.Repositories().Install(eng); err != nil { 140 return err 141 } 142 if err := daemon.trustStore.Install(eng); err != nil { 143 return err 144 } 145 // FIXME: this hack is necessary for legacy integration tests to access 146 // the daemon object. 147 eng.Hack_SetGlobalVar("httpapi.daemon", daemon) 148 return nil 149 } 150 151 // Get looks for a container by the specified ID or name, and returns it. 152 // If the container is not found, or if an error occurs, nil is returned. 153 func (daemon *Daemon) Get(name string) *Container { 154 id, err := daemon.idIndex.Get(name) 155 if err == nil { 156 return daemon.containers.Get(id) 157 } 158 159 if c, _ := daemon.GetByName(name); c != nil { 160 return c 161 } 162 163 if err == truncindex.ErrDuplicateID { 164 log.Errorf("Short ID %s is ambiguous: please retry with more characters or use the full ID.\n", name) 165 } 166 return nil 167 } 168 169 // Exists returns a true if a container of the specified ID or name exists, 170 // false otherwise. 171 func (daemon *Daemon) Exists(id string) bool { 172 return daemon.Get(id) != nil 173 } 174 175 func (daemon *Daemon) containerRoot(id string) string { 176 return path.Join(daemon.repository, id) 177 } 178 179 // Load reads the contents of a container from disk 180 // This is typically done at startup. 181 func (daemon *Daemon) load(id string) (*Container, error) { 182 container := &Container{ 183 root: daemon.containerRoot(id), 184 State: NewState(), 185 execCommands: newExecStore(), 186 } 187 if err := container.FromDisk(); err != nil { 188 return nil, err 189 } 190 191 if container.ID != id { 192 return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) 193 } 194 195 container.readHostConfig() 196 197 return container, nil 198 } 199 200 // Register makes a container object usable by the daemon as <container.ID> 201 // This is a wrapper for register 202 func (daemon *Daemon) Register(container *Container) error { 203 return daemon.register(container, true) 204 } 205 206 // register makes a container object usable by the daemon as <container.ID> 207 func (daemon *Daemon) register(container *Container, updateSuffixarray bool) error { 208 if container.daemon != nil || daemon.Exists(container.ID) { 209 return fmt.Errorf("Container is already loaded") 210 } 211 if err := validateID(container.ID); err != nil { 212 return err 213 } 214 if err := daemon.ensureName(container); err != nil { 215 return err 216 } 217 218 container.daemon = daemon 219 220 // Attach to stdout and stderr 221 container.stderr = broadcastwriter.New() 222 container.stdout = broadcastwriter.New() 223 // Attach to stdin 224 if container.Config.OpenStdin { 225 container.stdin, container.stdinPipe = io.Pipe() 226 } else { 227 container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin 228 } 229 // done 230 daemon.containers.Add(container.ID, container) 231 232 // don't update the Suffixarray if we're starting up 233 // we'll waste time if we update it for every container 234 daemon.idIndex.Add(container.ID) 235 236 // FIXME: if the container is supposed to be running but is not, auto restart it? 237 // if so, then we need to restart monitor and init a new lock 238 // If the container is supposed to be running, make sure of it 239 if container.IsRunning() { 240 log.Debugf("killing old running container %s", container.ID) 241 242 existingPid := container.Pid 243 container.SetStopped(&execdriver.ExitStatus{ExitCode: 0}) 244 245 // We only have to handle this for lxc because the other drivers will ensure that 246 // no processes are left when docker dies 247 if container.ExecDriver == "" || strings.Contains(container.ExecDriver, "lxc") { 248 lxc.KillLxc(container.ID, 9) 249 } else { 250 // use the current driver and ensure that the container is dead x.x 251 cmd := &execdriver.Command{ 252 ID: container.ID, 253 } 254 var err error 255 cmd.ProcessConfig.Process, err = os.FindProcess(existingPid) 256 if err != nil { 257 log.Debugf("cannot find existing process for %d", existingPid) 258 } 259 daemon.execDriver.Terminate(cmd) 260 } 261 262 if err := container.Unmount(); err != nil { 263 log.Debugf("unmount error %s", err) 264 } 265 if err := container.ToDisk(); err != nil { 266 log.Debugf("saving stopped state to disk %s", err) 267 } 268 269 info := daemon.execDriver.Info(container.ID) 270 if !info.IsRunning() { 271 log.Debugf("Container %s was supposed to be running but is not.", container.ID) 272 273 log.Debugf("Marking as stopped") 274 275 container.SetStopped(&execdriver.ExitStatus{ExitCode: -127}) 276 if err := container.ToDisk(); err != nil { 277 return err 278 } 279 } 280 } 281 return nil 282 } 283 284 func (daemon *Daemon) ensureName(container *Container) error { 285 if container.Name == "" { 286 name, err := daemon.generateNewName(container.ID) 287 if err != nil { 288 return err 289 } 290 container.Name = name 291 292 if err := container.ToDisk(); err != nil { 293 log.Debugf("Error saving container name %s", err) 294 } 295 } 296 return nil 297 } 298 299 func (daemon *Daemon) LogToDisk(src *broadcastwriter.BroadcastWriter, dst, stream string) error { 300 log, err := os.OpenFile(dst, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600) 301 if err != nil { 302 return err 303 } 304 src.AddWriter(log, stream) 305 return nil 306 } 307 308 func (daemon *Daemon) restore() error { 309 var ( 310 debug = (os.Getenv("DEBUG") != "" || os.Getenv("TEST") != "") 311 containers = make(map[string]*Container) 312 currentDriver = daemon.driver.String() 313 ) 314 315 if !debug { 316 log.Infof("Loading containers: start.") 317 } 318 dir, err := ioutil.ReadDir(daemon.repository) 319 if err != nil { 320 return err 321 } 322 323 for _, v := range dir { 324 id := v.Name() 325 container, err := daemon.load(id) 326 if !debug { 327 fmt.Print(".") 328 } 329 if err != nil { 330 log.Errorf("Failed to load container %v: %v", id, err) 331 continue 332 } 333 334 // Ignore the container if it does not support the current driver being used by the graph 335 if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver { 336 log.Debugf("Loaded container %v", container.ID) 337 338 containers[container.ID] = container 339 } else { 340 log.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID) 341 } 342 } 343 344 registeredContainers := []*Container{} 345 346 if entities := daemon.containerGraph.List("/", -1); entities != nil { 347 for _, p := range entities.Paths() { 348 if !debug { 349 fmt.Print(".") 350 } 351 352 e := entities[p] 353 354 if container, ok := containers[e.ID()]; ok { 355 if err := daemon.register(container, false); err != nil { 356 log.Debugf("Failed to register container %s: %s", container.ID, err) 357 } 358 359 registeredContainers = append(registeredContainers, container) 360 361 // delete from the map so that a new name is not automatically generated 362 delete(containers, e.ID()) 363 } 364 } 365 } 366 367 // Any containers that are left over do not exist in the graph 368 for _, container := range containers { 369 // Try to set the default name for a container if it exists prior to links 370 container.Name, err = daemon.generateNewName(container.ID) 371 if err != nil { 372 log.Debugf("Setting default id - %s", err) 373 } 374 375 if err := daemon.register(container, false); err != nil { 376 log.Debugf("Failed to register container %s: %s", container.ID, err) 377 } 378 379 registeredContainers = append(registeredContainers, container) 380 } 381 382 // check the restart policy on the containers and restart any container with 383 // the restart policy of "always" 384 if daemon.config.AutoRestart { 385 log.Debugf("Restarting containers...") 386 387 for _, container := range registeredContainers { 388 if container.hostConfig.RestartPolicy.Name == "always" || 389 (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) { 390 log.Debugf("Starting container %s", container.ID) 391 392 if err := container.Start(); err != nil { 393 log.Debugf("Failed to start container %s: %s", container.ID, err) 394 } 395 } 396 } 397 } 398 399 for _, c := range registeredContainers { 400 c.registerVolumes() 401 } 402 403 if !debug { 404 fmt.Println() 405 log.Infof("Loading containers: done.") 406 } 407 408 return nil 409 } 410 411 func (daemon *Daemon) checkDeprecatedExpose(config *runconfig.Config) bool { 412 if config != nil { 413 if config.PortSpecs != nil { 414 for _, p := range config.PortSpecs { 415 if strings.Contains(p, ":") { 416 return true 417 } 418 } 419 } 420 } 421 return false 422 } 423 424 func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) ([]string, error) { 425 warnings := []string{} 426 if (img != nil && daemon.checkDeprecatedExpose(img.Config)) || daemon.checkDeprecatedExpose(config) { 427 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.") 428 } 429 if img != nil && img.Config != nil { 430 if err := runconfig.Merge(config, img.Config); err != nil { 431 return nil, err 432 } 433 } 434 if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { 435 return nil, fmt.Errorf("No command specified") 436 } 437 return warnings, nil 438 } 439 440 func (daemon *Daemon) generateIdAndName(name string) (string, string, error) { 441 var ( 442 err error 443 id = utils.GenerateRandomID() 444 ) 445 446 if name == "" { 447 if name, err = daemon.generateNewName(id); err != nil { 448 return "", "", err 449 } 450 return id, name, nil 451 } 452 453 if name, err = daemon.reserveName(id, name); err != nil { 454 return "", "", err 455 } 456 457 return id, name, nil 458 } 459 460 func (daemon *Daemon) reserveName(id, name string) (string, error) { 461 if !validContainerNamePattern.MatchString(name) { 462 return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars) 463 } 464 465 if name[0] != '/' { 466 name = "/" + name 467 } 468 469 if _, err := daemon.containerGraph.Set(name, id); err != nil { 470 if !graphdb.IsNonUniqueNameError(err) { 471 return "", err 472 } 473 474 conflictingContainer, err := daemon.GetByName(name) 475 if err != nil { 476 if strings.Contains(err.Error(), "Could not find entity") { 477 return "", err 478 } 479 480 // Remove name and continue starting the container 481 if err := daemon.containerGraph.Delete(name); err != nil { 482 return "", err 483 } 484 } else { 485 nameAsKnownByUser := strings.TrimPrefix(name, "/") 486 return "", fmt.Errorf( 487 "Conflict. The name %q is already in use by container %s. You have to delete that container to be able to reuse that name.", nameAsKnownByUser, 488 utils.TruncateID(conflictingContainer.ID)) 489 } 490 } 491 return name, nil 492 } 493 494 func (daemon *Daemon) generateNewName(id string) (string, error) { 495 var name string 496 for i := 0; i < 6; i++ { 497 name = namesgenerator.GetRandomName(i) 498 if name[0] != '/' { 499 name = "/" + name 500 } 501 502 if _, err := daemon.containerGraph.Set(name, id); err != nil { 503 if !graphdb.IsNonUniqueNameError(err) { 504 return "", err 505 } 506 continue 507 } 508 return name, nil 509 } 510 511 name = "/" + utils.TruncateID(id) 512 if _, err := daemon.containerGraph.Set(name, id); err != nil { 513 return "", err 514 } 515 return name, nil 516 } 517 518 func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { 519 // Generate default hostname 520 // FIXME: the lxc template no longer needs to set a default hostname 521 if config.Hostname == "" { 522 config.Hostname = id[:12] 523 } 524 } 525 526 func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint, configCmd []string) (string, []string) { 527 var ( 528 entrypoint string 529 args []string 530 ) 531 if len(configEntrypoint) != 0 { 532 entrypoint = configEntrypoint[0] 533 args = append(configEntrypoint[1:], configCmd...) 534 } else { 535 entrypoint = configCmd[0] 536 args = configCmd[1:] 537 } 538 return entrypoint, args 539 } 540 541 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error { 542 var ( 543 labelOpts []string 544 err error 545 ) 546 547 for _, opt := range config.SecurityOpt { 548 con := strings.SplitN(opt, ":", 2) 549 if len(con) == 1 { 550 return fmt.Errorf("Invalid --security-opt: %q", opt) 551 } 552 switch con[0] { 553 case "label": 554 labelOpts = append(labelOpts, con[1]) 555 case "apparmor": 556 container.AppArmorProfile = con[1] 557 default: 558 return fmt.Errorf("Invalid --security-opt: %q", opt) 559 } 560 } 561 562 container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts) 563 return err 564 } 565 566 func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) { 567 var ( 568 id string 569 err error 570 ) 571 id, name, err = daemon.generateIdAndName(name) 572 if err != nil { 573 return nil, err 574 } 575 576 daemon.generateHostname(id, config) 577 entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd) 578 579 container := &Container{ 580 // FIXME: we should generate the ID here instead of receiving it as an argument 581 ID: id, 582 Created: time.Now().UTC(), 583 Path: entrypoint, 584 Args: args, //FIXME: de-duplicate from config 585 Config: config, 586 hostConfig: &runconfig.HostConfig{}, 587 ImageID: imgID, 588 NetworkSettings: &NetworkSettings{}, 589 Name: name, 590 Driver: daemon.driver.String(), 591 ExecDriver: daemon.execDriver.Name(), 592 State: NewState(), 593 execCommands: newExecStore(), 594 } 595 container.root = daemon.containerRoot(container.ID) 596 return container, err 597 } 598 599 func (daemon *Daemon) createRootfs(container *Container) error { 600 // Step 1: create the container directory. 601 // This doubles as a barrier to avoid race conditions. 602 if err := os.Mkdir(container.root, 0700); err != nil { 603 return err 604 } 605 initID := fmt.Sprintf("%s-init", container.ID) 606 if err := daemon.driver.Create(initID, container.ImageID); err != nil { 607 return err 608 } 609 initPath, err := daemon.driver.Get(initID, "") 610 if err != nil { 611 return err 612 } 613 defer daemon.driver.Put(initID) 614 615 if err := graph.SetupInitLayer(initPath); err != nil { 616 return err 617 } 618 619 if err := daemon.driver.Create(container.ID, initID); err != nil { 620 return err 621 } 622 return nil 623 } 624 625 func GetFullContainerName(name string) (string, error) { 626 if name == "" { 627 return "", fmt.Errorf("Container name cannot be empty") 628 } 629 if name[0] != '/' { 630 name = "/" + name 631 } 632 return name, nil 633 } 634 635 func (daemon *Daemon) GetByName(name string) (*Container, error) { 636 fullName, err := GetFullContainerName(name) 637 if err != nil { 638 return nil, err 639 } 640 entity := daemon.containerGraph.Get(fullName) 641 if entity == nil { 642 return nil, fmt.Errorf("Could not find entity for %s", name) 643 } 644 e := daemon.containers.Get(entity.ID()) 645 if e == nil { 646 return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID()) 647 } 648 return e, nil 649 } 650 651 func (daemon *Daemon) Children(name string) (map[string]*Container, error) { 652 name, err := GetFullContainerName(name) 653 if err != nil { 654 return nil, err 655 } 656 children := make(map[string]*Container) 657 658 err = daemon.containerGraph.Walk(name, func(p string, e *graphdb.Entity) error { 659 c := daemon.Get(e.ID()) 660 if c == nil { 661 return fmt.Errorf("Could not get container for name %s and id %s", e.ID(), p) 662 } 663 children[p] = c 664 return nil 665 }, 0) 666 667 if err != nil { 668 return nil, err 669 } 670 return children, nil 671 } 672 673 func (daemon *Daemon) Parents(name string) ([]string, error) { 674 name, err := GetFullContainerName(name) 675 if err != nil { 676 return nil, err 677 } 678 679 return daemon.containerGraph.Parents(name) 680 } 681 682 func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error { 683 fullName := path.Join(parent.Name, alias) 684 if !daemon.containerGraph.Exists(fullName) { 685 _, err := daemon.containerGraph.Set(fullName, child.ID) 686 return err 687 } 688 return nil 689 } 690 691 func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error { 692 if hostConfig != nil && hostConfig.Links != nil { 693 for _, l := range hostConfig.Links { 694 parts, err := parsers.PartParser("name:alias", l) 695 if err != nil { 696 return err 697 } 698 child, err := daemon.GetByName(parts["name"]) 699 if err != nil { 700 return err 701 } 702 if child == nil { 703 return fmt.Errorf("Could not get container for %s", parts["name"]) 704 } 705 if child.hostConfig.NetworkMode.IsHost() { 706 return runconfig.ErrConflictHostNetworkAndLinks 707 } 708 if err := daemon.RegisterLink(container, child, parts["alias"]); err != nil { 709 return err 710 } 711 } 712 713 // After we load all the links into the daemon 714 // set them to nil on the hostconfig 715 hostConfig.Links = nil 716 if err := container.WriteHostConfig(); err != nil { 717 return err 718 } 719 } 720 return nil 721 } 722 723 // FIXME: harmonize with NewGraph() 724 func NewDaemon(config *Config, eng *engine.Engine) (*Daemon, error) { 725 daemon, err := NewDaemonFromDirectory(config, eng) 726 if err != nil { 727 return nil, err 728 } 729 return daemon, nil 730 } 731 732 func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) { 733 if config.Mtu == 0 { 734 config.Mtu = getDefaultNetworkMtu() 735 } 736 // Check for mutually incompatible config options 737 if config.BridgeIface != "" && config.BridgeIP != "" { 738 return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") 739 } 740 if !config.EnableIptables && !config.InterContainerCommunication { 741 return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") 742 } 743 if !config.EnableIptables && config.EnableIpMasq { 744 config.EnableIpMasq = false 745 } 746 config.DisableNetwork = config.BridgeIface == disableNetworkBridge 747 748 // Claim the pidfile first, to avoid any and all unexpected race conditions. 749 // Some of the init doesn't need a pidfile lock - but let's not try to be smart. 750 if config.Pidfile != "" { 751 if err := utils.CreatePidFile(config.Pidfile); err != nil { 752 return nil, err 753 } 754 eng.OnShutdown(func() { 755 // Always release the pidfile last, just in case 756 utils.RemovePidFile(config.Pidfile) 757 }) 758 } 759 760 // Check that the system is supported and we have sufficient privileges 761 if runtime.GOOS != "linux" { 762 return nil, fmt.Errorf("The Docker daemon is only supported on linux") 763 } 764 if os.Geteuid() != 0 { 765 return nil, fmt.Errorf("The Docker daemon needs to be run as root") 766 } 767 if err := checkKernelAndArch(); err != nil { 768 return nil, err 769 } 770 771 // set up the TempDir to use a canonical path 772 tmp, err := utils.TempDir(config.Root) 773 if err != nil { 774 return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err) 775 } 776 realTmp, err := utils.ReadSymlinkedDirectory(tmp) 777 if err != nil { 778 return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err) 779 } 780 os.Setenv("TMPDIR", realTmp) 781 if !config.EnableSelinuxSupport { 782 selinuxSetDisabled() 783 } 784 785 // get the canonical path to the Docker root directory 786 var realRoot string 787 if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) { 788 realRoot = config.Root 789 } else { 790 realRoot, err = utils.ReadSymlinkedDirectory(config.Root) 791 if err != nil { 792 return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err) 793 } 794 } 795 config.Root = realRoot 796 // Create the root directory if it doesn't exists 797 if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { 798 return nil, err 799 } 800 801 // Set the default driver 802 graphdriver.DefaultDriver = config.GraphDriver 803 804 // Load storage driver 805 driver, err := graphdriver.New(config.Root, config.GraphOptions) 806 if err != nil { 807 return nil, err 808 } 809 log.Debugf("Using graph driver %s", driver) 810 811 // As Docker on btrfs and SELinux are incompatible at present, error on both being enabled 812 if selinuxEnabled() && config.EnableSelinuxSupport && driver.String() == "btrfs" { 813 return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver!") 814 } 815 816 daemonRepo := path.Join(config.Root, "containers") 817 818 if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) { 819 return nil, err 820 } 821 822 // Migrate the container if it is aufs and aufs is enabled 823 if err = migrateIfAufs(driver, config.Root); err != nil { 824 return nil, err 825 } 826 827 log.Debugf("Creating images graph") 828 g, err := graph.NewGraph(path.Join(config.Root, "graph"), driver) 829 if err != nil { 830 return nil, err 831 } 832 833 volumesDriver, err := graphdriver.GetDriver("vfs", config.Root, config.GraphOptions) 834 if err != nil { 835 return nil, err 836 } 837 838 volumes, err := volumes.NewRepository(path.Join(config.Root, "volumes"), volumesDriver) 839 if err != nil { 840 return nil, err 841 } 842 843 log.Debugf("Creating repository list") 844 repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, config.Mirrors, config.InsecureRegistries) 845 if err != nil { 846 return nil, fmt.Errorf("Couldn't create Tag store: %s", err) 847 } 848 849 trustDir := path.Join(config.Root, "trust") 850 if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) { 851 return nil, err 852 } 853 t, err := trust.NewTrustStore(trustDir) 854 if err != nil { 855 return nil, fmt.Errorf("could not create trust store: %s", err) 856 } 857 858 if !config.DisableNetwork { 859 job := eng.Job("init_networkdriver") 860 861 job.SetenvBool("EnableIptables", config.EnableIptables) 862 job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication) 863 job.SetenvBool("EnableIpForward", config.EnableIpForward) 864 job.SetenvBool("EnableIpMasq", config.EnableIpMasq) 865 job.Setenv("BridgeIface", config.BridgeIface) 866 job.Setenv("BridgeIP", config.BridgeIP) 867 job.Setenv("FixedCIDR", config.FixedCIDR) 868 job.Setenv("DefaultBindingIP", config.DefaultIp.String()) 869 870 if err := job.Run(); err != nil { 871 return nil, err 872 } 873 } 874 875 graphdbPath := path.Join(config.Root, "linkgraph.db") 876 graph, err := graphdb.NewSqliteConn(graphdbPath) 877 if err != nil { 878 return nil, err 879 } 880 881 localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) 882 sysInitPath := utils.DockerInitPath(localCopy) 883 if sysInitPath == "" { 884 return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See http://docs.docker.com/contributing/devenvironment for official build instructions.") 885 } 886 887 if sysInitPath != localCopy { 888 // 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). 889 if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { 890 return nil, err 891 } 892 if _, err := utils.CopyFile(sysInitPath, localCopy); err != nil { 893 return nil, err 894 } 895 if err := os.Chmod(localCopy, 0700); err != nil { 896 return nil, err 897 } 898 sysInitPath = localCopy 899 } 900 901 sysInfo := sysinfo.New(false) 902 ed, err := execdrivers.NewDriver(config.ExecDriver, config.Root, sysInitPath, sysInfo) 903 if err != nil { 904 return nil, err 905 } 906 907 trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) 908 if err != nil { 909 return nil, err 910 } 911 912 daemon := &Daemon{ 913 ID: trustKey.PublicKey().KeyID(), 914 repository: daemonRepo, 915 containers: &contStore{s: make(map[string]*Container)}, 916 execCommands: newExecStore(), 917 graph: g, 918 repositories: repositories, 919 idIndex: truncindex.NewTruncIndex([]string{}), 920 sysInfo: sysInfo, 921 volumes: volumes, 922 config: config, 923 containerGraph: graph, 924 driver: driver, 925 sysInitPath: sysInitPath, 926 execDriver: ed, 927 eng: eng, 928 trustStore: t, 929 } 930 if err := daemon.restore(); err != nil { 931 return nil, err 932 } 933 // Setup shutdown handlers 934 // FIXME: can these shutdown handlers be registered closer to their source? 935 eng.OnShutdown(func() { 936 // FIXME: if these cleanup steps can be called concurrently, register 937 // them as separate handlers to speed up total shutdown time 938 if err := daemon.shutdown(); err != nil { 939 log.Errorf("daemon.shutdown(): %s", err) 940 } 941 if err := portallocator.ReleaseAll(); err != nil { 942 log.Errorf("portallocator.ReleaseAll(): %s", err) 943 } 944 if err := daemon.driver.Cleanup(); err != nil { 945 log.Errorf("daemon.driver.Cleanup(): %s", err.Error()) 946 } 947 if err := daemon.containerGraph.Close(); err != nil { 948 log.Errorf("daemon.containerGraph.Close(): %s", err.Error()) 949 } 950 }) 951 952 return daemon, nil 953 } 954 955 func (daemon *Daemon) shutdown() error { 956 group := sync.WaitGroup{} 957 log.Debugf("starting clean shutdown of all containers...") 958 for _, container := range daemon.List() { 959 c := container 960 if c.IsRunning() { 961 log.Debugf("stopping %s", c.ID) 962 group.Add(1) 963 964 go func() { 965 defer group.Done() 966 if err := c.KillSig(15); err != nil { 967 log.Debugf("kill 15 error for %s - %s", c.ID, err) 968 } 969 c.WaitStop(-1 * time.Second) 970 log.Debugf("container stopped %s", c.ID) 971 }() 972 } 973 } 974 group.Wait() 975 976 return nil 977 } 978 979 func (daemon *Daemon) Mount(container *Container) error { 980 dir, err := daemon.driver.Get(container.ID, container.GetMountLabel()) 981 if err != nil { 982 return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) 983 } 984 if container.basefs == "" { 985 container.basefs = dir 986 } else if container.basefs != dir { 987 daemon.driver.Put(container.ID) 988 return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')", 989 daemon.driver, container.ID, container.basefs, dir) 990 } 991 return nil 992 } 993 994 func (daemon *Daemon) Unmount(container *Container) error { 995 daemon.driver.Put(container.ID) 996 return nil 997 } 998 999 func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) { 1000 initID := fmt.Sprintf("%s-init", container.ID) 1001 return daemon.driver.Changes(container.ID, initID) 1002 } 1003 1004 func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) { 1005 initID := fmt.Sprintf("%s-init", container.ID) 1006 return daemon.driver.Diff(container.ID, initID) 1007 } 1008 1009 func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { 1010 return daemon.execDriver.Run(c.command, pipes, startCallback) 1011 } 1012 1013 func (daemon *Daemon) Pause(c *Container) error { 1014 if err := daemon.execDriver.Pause(c.command); err != nil { 1015 return err 1016 } 1017 c.SetPaused() 1018 return nil 1019 } 1020 1021 func (daemon *Daemon) Unpause(c *Container) error { 1022 if err := daemon.execDriver.Unpause(c.command); err != nil { 1023 return err 1024 } 1025 c.SetUnpaused() 1026 return nil 1027 } 1028 1029 func (daemon *Daemon) Kill(c *Container, sig int) error { 1030 return daemon.execDriver.Kill(c.command, sig) 1031 } 1032 1033 // Nuke kills all containers then removes all content 1034 // from the content root, including images, volumes and 1035 // container filesystems. 1036 // Again: this will remove your entire docker daemon! 1037 // FIXME: this is deprecated, and only used in legacy 1038 // tests. Please remove. 1039 func (daemon *Daemon) Nuke() error { 1040 var wg sync.WaitGroup 1041 for _, container := range daemon.List() { 1042 wg.Add(1) 1043 go func(c *Container) { 1044 c.Kill() 1045 wg.Done() 1046 }(container) 1047 } 1048 wg.Wait() 1049 1050 return os.RemoveAll(daemon.config.Root) 1051 } 1052 1053 // FIXME: this is a convenience function for integration tests 1054 // which need direct access to daemon.graph. 1055 // Once the tests switch to using engine and jobs, this method 1056 // can go away. 1057 func (daemon *Daemon) Graph() *graph.Graph { 1058 return daemon.graph 1059 } 1060 1061 func (daemon *Daemon) Repositories() *graph.TagStore { 1062 return daemon.repositories 1063 } 1064 1065 func (daemon *Daemon) Config() *Config { 1066 return daemon.config 1067 } 1068 1069 func (daemon *Daemon) SystemConfig() *sysinfo.SysInfo { 1070 return daemon.sysInfo 1071 } 1072 1073 func (daemon *Daemon) SystemInitPath() string { 1074 return daemon.sysInitPath 1075 } 1076 1077 func (daemon *Daemon) GraphDriver() graphdriver.Driver { 1078 return daemon.driver 1079 } 1080 1081 func (daemon *Daemon) ExecutionDriver() execdriver.Driver { 1082 return daemon.execDriver 1083 } 1084 1085 func (daemon *Daemon) ContainerGraph() *graphdb.Database { 1086 return daemon.containerGraph 1087 } 1088 1089 func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) { 1090 // Retrieve all images 1091 images, err := daemon.Graph().Map() 1092 if err != nil { 1093 return nil, err 1094 } 1095 1096 // Store the tree in a map of map (map[parentId][childId]) 1097 imageMap := make(map[string]map[string]struct{}) 1098 for _, img := range images { 1099 if _, exists := imageMap[img.Parent]; !exists { 1100 imageMap[img.Parent] = make(map[string]struct{}) 1101 } 1102 imageMap[img.Parent][img.ID] = struct{}{} 1103 } 1104 1105 // Loop on the children of the given image and check the config 1106 var match *image.Image 1107 for elem := range imageMap[imgID] { 1108 img, ok := images[elem] 1109 if !ok { 1110 return nil, fmt.Errorf("unable to find image %q", elem) 1111 } 1112 if runconfig.Compare(&img.ContainerConfig, config) { 1113 if match == nil || match.Created.Before(img.Created) { 1114 match = img 1115 } 1116 } 1117 } 1118 return match, nil 1119 } 1120 1121 func checkKernelAndArch() error { 1122 // Check for unsupported architectures 1123 if runtime.GOARCH != "amd64" { 1124 return fmt.Errorf("The Docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) 1125 } 1126 // Check for unsupported kernel versions 1127 // FIXME: it would be cleaner to not test for specific versions, but rather 1128 // test for specific functionalities. 1129 // Unfortunately we can't test for the feature "does not cause a kernel panic" 1130 // without actually causing a kernel panic, so we need this workaround until 1131 // the circumstances of pre-3.8 crashes are clearer. 1132 // For details see http://github.com/docker/docker/issues/407 1133 if k, err := kernel.GetKernelVersion(); err != nil { 1134 log.Infof("WARNING: %s", err) 1135 } else { 1136 if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 { 1137 if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" { 1138 log.Infof("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String()) 1139 } 1140 } 1141 } 1142 return nil 1143 }