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