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