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