github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/daemon/container.go (about)

     1  package daemon
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  	"path"
    12  	"path/filepath"
    13  	"strings"
    14  	"syscall"
    15  	"time"
    16  
    17  	"github.com/docker/libcontainer/devices"
    18  	"github.com/docker/libcontainer/label"
    19  
    20  	log "github.com/Sirupsen/logrus"
    21  	"github.com/docker/docker/daemon/execdriver"
    22  	"github.com/docker/docker/engine"
    23  	"github.com/docker/docker/image"
    24  	"github.com/docker/docker/links"
    25  	"github.com/docker/docker/nat"
    26  	"github.com/docker/docker/pkg/archive"
    27  	"github.com/docker/docker/pkg/broadcastwriter"
    28  	"github.com/docker/docker/pkg/ioutils"
    29  	"github.com/docker/docker/pkg/networkfs/etchosts"
    30  	"github.com/docker/docker/pkg/networkfs/resolvconf"
    31  	"github.com/docker/docker/pkg/promise"
    32  	"github.com/docker/docker/pkg/symlink"
    33  	"github.com/docker/docker/runconfig"
    34  	"github.com/docker/docker/utils"
    35  )
    36  
    37  const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    38  
    39  var (
    40  	ErrNotATTY               = errors.New("The PTY is not a file")
    41  	ErrNoTTY                 = errors.New("No PTY found")
    42  	ErrContainerStart        = errors.New("The container failed to start. Unknown error")
    43  	ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
    44  )
    45  
    46  type StreamConfig struct {
    47  	stdout    *broadcastwriter.BroadcastWriter
    48  	stderr    *broadcastwriter.BroadcastWriter
    49  	stdin     io.ReadCloser
    50  	stdinPipe io.WriteCloser
    51  }
    52  
    53  type Container struct {
    54  	*State `json:"State"` // Needed for remote api version <= 1.11
    55  	root   string         // Path to the "home" of the container, including metadata.
    56  	basefs string         // Path to the graphdriver mountpoint
    57  
    58  	ID string
    59  
    60  	Created time.Time
    61  
    62  	Path string
    63  	Args []string
    64  
    65  	Config  *runconfig.Config
    66  	ImageID string `json:"Image"`
    67  
    68  	NetworkSettings *NetworkSettings
    69  
    70  	ResolvConfPath string
    71  	HostnamePath   string
    72  	HostsPath      string
    73  	Name           string
    74  	Driver         string
    75  	ExecDriver     string
    76  
    77  	command *execdriver.Command
    78  	StreamConfig
    79  
    80  	daemon                   *Daemon
    81  	MountLabel, ProcessLabel string
    82  	AppArmorProfile          string
    83  	RestartCount             int
    84  
    85  	// Maps container paths to volume paths.  The key in this is the path to which
    86  	// the volume is being mounted inside the container.  Value is the path of the
    87  	// volume on disk
    88  	Volumes map[string]string
    89  	// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
    90  	// Easier than migrating older container configs :)
    91  	VolumesRW  map[string]bool
    92  	hostConfig *runconfig.HostConfig
    93  
    94  	activeLinks  map[string]*links.Link
    95  	monitor      *containerMonitor
    96  	execCommands *execStore
    97  }
    98  
    99  func (container *Container) FromDisk() error {
   100  	pth, err := container.jsonPath()
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	jsonSource, err := os.Open(pth)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	defer jsonSource.Close()
   110  
   111  	dec := json.NewDecoder(jsonSource)
   112  
   113  	// Load container settings
   114  	// udp broke compat of docker.PortMapping, but it's not used when loading a container, we can skip it
   115  	if err := dec.Decode(container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
   116  		return err
   117  	}
   118  
   119  	if err := label.ReserveLabel(container.ProcessLabel); err != nil {
   120  		return err
   121  	}
   122  	return container.readHostConfig()
   123  }
   124  
   125  func (container *Container) toDisk() error {
   126  	data, err := json.Marshal(container)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	pth, err := container.jsonPath()
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	err = ioutil.WriteFile(pth, data, 0666)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	return container.WriteHostConfig()
   142  }
   143  
   144  func (container *Container) ToDisk() error {
   145  	container.Lock()
   146  	err := container.toDisk()
   147  	container.Unlock()
   148  	return err
   149  }
   150  
   151  func (container *Container) readHostConfig() error {
   152  	container.hostConfig = &runconfig.HostConfig{}
   153  	// If the hostconfig file does not exist, do not read it.
   154  	// (We still have to initialize container.hostConfig,
   155  	// but that's OK, since we just did that above.)
   156  	pth, err := container.hostConfigPath()
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	_, err = os.Stat(pth)
   162  	if os.IsNotExist(err) {
   163  		return nil
   164  	}
   165  
   166  	data, err := ioutil.ReadFile(pth)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	return json.Unmarshal(data, container.hostConfig)
   171  }
   172  
   173  func (container *Container) WriteHostConfig() error {
   174  	data, err := json.Marshal(container.hostConfig)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	pth, err := container.hostConfigPath()
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	return ioutil.WriteFile(pth, data, 0666)
   185  }
   186  
   187  func (container *Container) LogEvent(action string) {
   188  	d := container.daemon
   189  	if err := d.eng.Job("log", action, container.ID, d.Repositories().ImageName(container.ImageID)).Run(); err != nil {
   190  		log.Errorf("Error logging event %s for %s: %s", action, container.ID, err)
   191  	}
   192  }
   193  
   194  func (container *Container) getResourcePath(path string) (string, error) {
   195  	cleanPath := filepath.Join("/", path)
   196  	return symlink.FollowSymlinkInScope(filepath.Join(container.basefs, cleanPath), container.basefs)
   197  }
   198  
   199  func (container *Container) getRootResourcePath(path string) (string, error) {
   200  	cleanPath := filepath.Join("/", path)
   201  	return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
   202  }
   203  
   204  func populateCommand(c *Container, env []string) error {
   205  	en := &execdriver.Network{
   206  		Mtu:       c.daemon.config.Mtu,
   207  		Interface: nil,
   208  	}
   209  
   210  	parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
   211  	switch parts[0] {
   212  	case "none":
   213  	case "host":
   214  		en.HostNetworking = true
   215  	case "bridge", "": // empty string to support existing containers
   216  		if !c.Config.NetworkDisabled {
   217  			network := c.NetworkSettings
   218  			en.Interface = &execdriver.NetworkInterface{
   219  				Gateway:     network.Gateway,
   220  				Bridge:      network.Bridge,
   221  				IPAddress:   network.IPAddress,
   222  				IPPrefixLen: network.IPPrefixLen,
   223  				MacAddress:  network.MacAddress,
   224  			}
   225  		}
   226  	case "container":
   227  		nc, err := c.getNetworkedContainer()
   228  		if err != nil {
   229  			return err
   230  		}
   231  		en.ContainerID = nc.ID
   232  	default:
   233  		return fmt.Errorf("invalid network mode: %s", c.hostConfig.NetworkMode)
   234  	}
   235  
   236  	ipc := &execdriver.Ipc{}
   237  
   238  	if c.hostConfig.IpcMode.IsContainer() {
   239  		ic, err := c.getIpcContainer()
   240  		if err != nil {
   241  			return err
   242  		}
   243  		ipc.ContainerID = ic.ID
   244  	} else {
   245  		ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
   246  	}
   247  
   248  	// Build lists of devices allowed and created within the container.
   249  	userSpecifiedDevices := make([]*devices.Device, len(c.hostConfig.Devices))
   250  	for i, deviceMapping := range c.hostConfig.Devices {
   251  		device, err := devices.GetDevice(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
   252  		if err != nil {
   253  			return fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
   254  		}
   255  		device.Path = deviceMapping.PathInContainer
   256  		userSpecifiedDevices[i] = device
   257  	}
   258  	allowedDevices := append(devices.DefaultAllowedDevices, userSpecifiedDevices...)
   259  
   260  	autoCreatedDevices := append(devices.DefaultAutoCreatedDevices, userSpecifiedDevices...)
   261  
   262  	// TODO: this can be removed after lxc-conf is fully deprecated
   263  	lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
   264  	if err != nil {
   265  		return err
   266  	}
   267  
   268  	resources := &execdriver.Resources{
   269  		Memory:     c.Config.Memory,
   270  		MemorySwap: c.Config.MemorySwap,
   271  		CpuShares:  c.Config.CpuShares,
   272  		Cpuset:     c.Config.Cpuset,
   273  	}
   274  
   275  	processConfig := execdriver.ProcessConfig{
   276  		Privileged: c.hostConfig.Privileged,
   277  		Entrypoint: c.Path,
   278  		Arguments:  c.Args,
   279  		Tty:        c.Config.Tty,
   280  		User:       c.Config.User,
   281  	}
   282  
   283  	processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
   284  	processConfig.Env = env
   285  
   286  	c.command = &execdriver.Command{
   287  		ID:                 c.ID,
   288  		Rootfs:             c.RootfsPath(),
   289  		InitPath:           "/.dockerinit",
   290  		WorkingDir:         c.Config.WorkingDir,
   291  		Network:            en,
   292  		Ipc:                ipc,
   293  		Resources:          resources,
   294  		AllowedDevices:     allowedDevices,
   295  		AutoCreatedDevices: autoCreatedDevices,
   296  		CapAdd:             c.hostConfig.CapAdd,
   297  		CapDrop:            c.hostConfig.CapDrop,
   298  		ProcessConfig:      processConfig,
   299  		ProcessLabel:       c.GetProcessLabel(),
   300  		MountLabel:         c.GetMountLabel(),
   301  		LxcConfig:          lxcConfig,
   302  		AppArmorProfile:    c.AppArmorProfile,
   303  	}
   304  
   305  	return nil
   306  }
   307  
   308  func (container *Container) Start() (err error) {
   309  	container.Lock()
   310  	defer container.Unlock()
   311  
   312  	if container.Running {
   313  		return nil
   314  	}
   315  
   316  	// if we encounter and error during start we need to ensure that any other
   317  	// setup has been cleaned up properly
   318  	defer func() {
   319  		if err != nil {
   320  			container.setError(err)
   321  			// if no one else has set it, make sure we don't leave it at zero
   322  			if container.ExitCode == 0 {
   323  				container.ExitCode = 128
   324  			}
   325  			container.toDisk()
   326  			container.cleanup()
   327  		}
   328  	}()
   329  
   330  	if err := container.setupContainerDns(); err != nil {
   331  		return err
   332  	}
   333  	if err := container.Mount(); err != nil {
   334  		return err
   335  	}
   336  	if err := container.initializeNetworking(); err != nil {
   337  		return err
   338  	}
   339  	if err := container.updateParentsHosts(); err != nil {
   340  		return err
   341  	}
   342  	container.verifyDaemonSettings()
   343  	if err := container.prepareVolumes(); err != nil {
   344  		return err
   345  	}
   346  	linkedEnv, err := container.setupLinkedContainers()
   347  	if err != nil {
   348  		return err
   349  	}
   350  	if err := container.setupWorkingDirectory(); err != nil {
   351  		return err
   352  	}
   353  	env := container.createDaemonEnvironment(linkedEnv)
   354  	if err := populateCommand(container, env); err != nil {
   355  		return err
   356  	}
   357  	if err := container.setupMounts(); err != nil {
   358  		return err
   359  	}
   360  
   361  	return container.waitForStart()
   362  }
   363  
   364  func (container *Container) Run() error {
   365  	if err := container.Start(); err != nil {
   366  		return err
   367  	}
   368  	container.WaitStop(-1 * time.Second)
   369  	return nil
   370  }
   371  
   372  func (container *Container) Output() (output []byte, err error) {
   373  	pipe := container.StdoutPipe()
   374  	defer pipe.Close()
   375  	if err := container.Start(); err != nil {
   376  		return nil, err
   377  	}
   378  	output, err = ioutil.ReadAll(pipe)
   379  	container.WaitStop(-1 * time.Second)
   380  	return output, err
   381  }
   382  
   383  // StreamConfig.StdinPipe returns a WriteCloser which can be used to feed data
   384  // to the standard input of the container's active process.
   385  // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
   386  // which can be used to retrieve the standard output (and error) generated
   387  // by the container's active process. The output (and error) are actually
   388  // copied and delivered to all StdoutPipe and StderrPipe consumers, using
   389  // a kind of "broadcaster".
   390  
   391  func (streamConfig *StreamConfig) StdinPipe() io.WriteCloser {
   392  	return streamConfig.stdinPipe
   393  }
   394  
   395  func (streamConfig *StreamConfig) StdoutPipe() io.ReadCloser {
   396  	reader, writer := io.Pipe()
   397  	streamConfig.stdout.AddWriter(writer, "")
   398  	return ioutils.NewBufReader(reader)
   399  }
   400  
   401  func (streamConfig *StreamConfig) StderrPipe() io.ReadCloser {
   402  	reader, writer := io.Pipe()
   403  	streamConfig.stderr.AddWriter(writer, "")
   404  	return ioutils.NewBufReader(reader)
   405  }
   406  
   407  func (streamConfig *StreamConfig) StdoutLogPipe() io.ReadCloser {
   408  	reader, writer := io.Pipe()
   409  	streamConfig.stdout.AddWriter(writer, "stdout")
   410  	return ioutils.NewBufReader(reader)
   411  }
   412  
   413  func (streamConfig *StreamConfig) StderrLogPipe() io.ReadCloser {
   414  	reader, writer := io.Pipe()
   415  	streamConfig.stderr.AddWriter(writer, "stderr")
   416  	return ioutils.NewBufReader(reader)
   417  }
   418  
   419  func (container *Container) buildHostnameFile() error {
   420  	hostnamePath, err := container.getRootResourcePath("hostname")
   421  	if err != nil {
   422  		return err
   423  	}
   424  	container.HostnamePath = hostnamePath
   425  
   426  	if container.Config.Domainname != "" {
   427  		return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
   428  	}
   429  	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
   430  }
   431  
   432  func (container *Container) buildHostsFiles(IP string) error {
   433  
   434  	hostsPath, err := container.getRootResourcePath("hosts")
   435  	if err != nil {
   436  		return err
   437  	}
   438  	container.HostsPath = hostsPath
   439  
   440  	var extraContent []etchosts.Record
   441  
   442  	children, err := container.daemon.Children(container.Name)
   443  	if err != nil {
   444  		return err
   445  	}
   446  
   447  	for linkAlias, child := range children {
   448  		_, alias := path.Split(linkAlias)
   449  		extraContent = append(extraContent, etchosts.Record{Hosts: alias, IP: child.NetworkSettings.IPAddress})
   450  	}
   451  
   452  	for _, extraHost := range container.hostConfig.ExtraHosts {
   453  		parts := strings.Split(extraHost, ":")
   454  		extraContent = append(extraContent, etchosts.Record{Hosts: parts[0], IP: parts[1]})
   455  	}
   456  
   457  	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, extraContent)
   458  }
   459  
   460  func (container *Container) buildHostnameAndHostsFiles(IP string) error {
   461  	if err := container.buildHostnameFile(); err != nil {
   462  		return err
   463  	}
   464  
   465  	return container.buildHostsFiles(IP)
   466  }
   467  
   468  func (container *Container) AllocateNetwork() error {
   469  	mode := container.hostConfig.NetworkMode
   470  	if container.Config.NetworkDisabled || !mode.IsPrivate() {
   471  		return nil
   472  	}
   473  
   474  	var (
   475  		env *engine.Env
   476  		err error
   477  		eng = container.daemon.eng
   478  	)
   479  
   480  	job := eng.Job("allocate_interface", container.ID)
   481  	job.Setenv("RequestedMac", container.Config.MacAddress)
   482  	if env, err = job.Stdout.AddEnv(); err != nil {
   483  		return err
   484  	}
   485  	if err = job.Run(); err != nil {
   486  		return err
   487  	}
   488  
   489  	// Error handling: At this point, the interface is allocated so we have to
   490  	// make sure that it is always released in case of error, otherwise we
   491  	// might leak resources.
   492  
   493  	if container.Config.PortSpecs != nil {
   494  		if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
   495  			eng.Job("release_interface", container.ID).Run()
   496  			return err
   497  		}
   498  		container.Config.PortSpecs = nil
   499  		if err = container.WriteHostConfig(); err != nil {
   500  			eng.Job("release_interface", container.ID).Run()
   501  			return err
   502  		}
   503  	}
   504  
   505  	var (
   506  		portSpecs = make(nat.PortSet)
   507  		bindings  = make(nat.PortMap)
   508  	)
   509  
   510  	if container.Config.ExposedPorts != nil {
   511  		portSpecs = container.Config.ExposedPorts
   512  	}
   513  
   514  	if container.hostConfig.PortBindings != nil {
   515  		for p, b := range container.hostConfig.PortBindings {
   516  			bindings[p] = []nat.PortBinding{}
   517  			for _, bb := range b {
   518  				bindings[p] = append(bindings[p], nat.PortBinding{
   519  					HostIp:   bb.HostIp,
   520  					HostPort: bb.HostPort,
   521  				})
   522  			}
   523  		}
   524  	}
   525  
   526  	container.NetworkSettings.PortMapping = nil
   527  
   528  	for port := range portSpecs {
   529  		if err = container.allocatePort(eng, port, bindings); err != nil {
   530  			eng.Job("release_interface", container.ID).Run()
   531  			return err
   532  		}
   533  	}
   534  	container.WriteHostConfig()
   535  
   536  	container.NetworkSettings.Ports = bindings
   537  	container.NetworkSettings.Bridge = env.Get("Bridge")
   538  	container.NetworkSettings.IPAddress = env.Get("IP")
   539  	container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
   540  	container.NetworkSettings.MacAddress = env.Get("MacAddress")
   541  	container.NetworkSettings.Gateway = env.Get("Gateway")
   542  
   543  	return nil
   544  }
   545  
   546  func (container *Container) ReleaseNetwork() {
   547  	if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
   548  		return
   549  	}
   550  	eng := container.daemon.eng
   551  
   552  	job := eng.Job("release_interface", container.ID)
   553  	job.SetenvBool("overrideShutdown", true)
   554  	job.Run()
   555  	container.NetworkSettings = &NetworkSettings{}
   556  }
   557  
   558  func (container *Container) isNetworkAllocated() bool {
   559  	return container.NetworkSettings.IPAddress != ""
   560  }
   561  
   562  func (container *Container) RestoreNetwork() error {
   563  	mode := container.hostConfig.NetworkMode
   564  	// Don't attempt a restore if we previously didn't allocate networking.
   565  	// This might be a legacy container with no network allocated, in which case the
   566  	// allocation will happen once and for all at start.
   567  	if !container.isNetworkAllocated() || container.Config.NetworkDisabled || !mode.IsPrivate() {
   568  		return nil
   569  	}
   570  
   571  	eng := container.daemon.eng
   572  
   573  	// Re-allocate the interface with the same IP and MAC address.
   574  	job := eng.Job("allocate_interface", container.ID)
   575  	job.Setenv("RequestedIP", container.NetworkSettings.IPAddress)
   576  	job.Setenv("RequestedMac", container.NetworkSettings.MacAddress)
   577  	if err := job.Run(); err != nil {
   578  		return err
   579  	}
   580  
   581  	// Re-allocate any previously allocated ports.
   582  	for port := range container.NetworkSettings.Ports {
   583  		if err := container.allocatePort(eng, port, container.NetworkSettings.Ports); err != nil {
   584  			return err
   585  		}
   586  	}
   587  	return nil
   588  }
   589  
   590  // cleanup releases any network resources allocated to the container along with any rules
   591  // around how containers are linked together.  It also unmounts the container's root filesystem.
   592  func (container *Container) cleanup() {
   593  	container.ReleaseNetwork()
   594  
   595  	// Disable all active links
   596  	if container.activeLinks != nil {
   597  		for _, link := range container.activeLinks {
   598  			link.Disable()
   599  		}
   600  	}
   601  
   602  	if err := container.Unmount(); err != nil {
   603  		log.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
   604  	}
   605  
   606  	for _, eConfig := range container.execCommands.s {
   607  		container.daemon.unregisterExecCommand(eConfig)
   608  	}
   609  }
   610  
   611  func (container *Container) KillSig(sig int) error {
   612  	log.Debugf("Sending %d to %s", sig, container.ID)
   613  	container.Lock()
   614  	defer container.Unlock()
   615  
   616  	// We could unpause the container for them rather than returning this error
   617  	if container.Paused {
   618  		return fmt.Errorf("Container %s is paused. Unpause the container before stopping", container.ID)
   619  	}
   620  
   621  	if !container.Running {
   622  		return nil
   623  	}
   624  
   625  	// signal to the monitor that it should not restart the container
   626  	// after we send the kill signal
   627  	container.monitor.ExitOnNext()
   628  
   629  	// if the container is currently restarting we do not need to send the signal
   630  	// to the process.  Telling the monitor that it should exit on it's next event
   631  	// loop is enough
   632  	if container.Restarting {
   633  		return nil
   634  	}
   635  
   636  	return container.daemon.Kill(container, sig)
   637  }
   638  
   639  func (container *Container) Pause() error {
   640  	if container.IsPaused() {
   641  		return fmt.Errorf("Container %s is already paused", container.ID)
   642  	}
   643  	if !container.IsRunning() {
   644  		return fmt.Errorf("Container %s is not running", container.ID)
   645  	}
   646  	return container.daemon.Pause(container)
   647  }
   648  
   649  func (container *Container) Unpause() error {
   650  	if !container.IsPaused() {
   651  		return fmt.Errorf("Container %s is not paused", container.ID)
   652  	}
   653  	if !container.IsRunning() {
   654  		return fmt.Errorf("Container %s is not running", container.ID)
   655  	}
   656  	return container.daemon.Unpause(container)
   657  }
   658  
   659  func (container *Container) Kill() error {
   660  	if !container.IsRunning() {
   661  		return nil
   662  	}
   663  
   664  	// 1. Send SIGKILL
   665  	if err := container.KillSig(9); err != nil {
   666  		return err
   667  	}
   668  
   669  	// 2. Wait for the process to die, in last resort, try to kill the process directly
   670  	if _, err := container.WaitStop(10 * time.Second); err != nil {
   671  		// Ensure that we don't kill ourselves
   672  		if pid := container.GetPid(); pid != 0 {
   673  			log.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", utils.TruncateID(container.ID))
   674  			if err := syscall.Kill(pid, 9); err != nil {
   675  				return err
   676  			}
   677  		}
   678  	}
   679  
   680  	container.WaitStop(-1 * time.Second)
   681  	return nil
   682  }
   683  
   684  func (container *Container) Stop(seconds int) error {
   685  	if !container.IsRunning() {
   686  		return nil
   687  	}
   688  
   689  	// 1. Send a SIGTERM
   690  	if err := container.KillSig(15); err != nil {
   691  		log.Infof("Failed to send SIGTERM to the process, force killing")
   692  		if err := container.KillSig(9); err != nil {
   693  			return err
   694  		}
   695  	}
   696  
   697  	// 2. Wait for the process to exit on its own
   698  	if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
   699  		log.Infof("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
   700  		// 3. If it doesn't, then send SIGKILL
   701  		if err := container.Kill(); err != nil {
   702  			container.WaitStop(-1 * time.Second)
   703  			return err
   704  		}
   705  	}
   706  	return nil
   707  }
   708  
   709  func (container *Container) Restart(seconds int) error {
   710  	// Avoid unnecessarily unmounting and then directly mounting
   711  	// the container when the container stops and then starts
   712  	// again
   713  	if err := container.Mount(); err == nil {
   714  		defer container.Unmount()
   715  	}
   716  
   717  	if err := container.Stop(seconds); err != nil {
   718  		return err
   719  	}
   720  	return container.Start()
   721  }
   722  
   723  func (container *Container) Resize(h, w int) error {
   724  	if !container.IsRunning() {
   725  		return fmt.Errorf("Cannot resize container %s, container is not running", container.ID)
   726  	}
   727  	return container.command.ProcessConfig.Terminal.Resize(h, w)
   728  }
   729  
   730  func (container *Container) ExportRw() (archive.Archive, error) {
   731  	if err := container.Mount(); err != nil {
   732  		return nil, err
   733  	}
   734  	if container.daemon == nil {
   735  		return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
   736  	}
   737  	archive, err := container.daemon.Diff(container)
   738  	if err != nil {
   739  		container.Unmount()
   740  		return nil, err
   741  	}
   742  	return ioutils.NewReadCloserWrapper(archive, func() error {
   743  			err := archive.Close()
   744  			container.Unmount()
   745  			return err
   746  		}),
   747  		nil
   748  }
   749  
   750  func (container *Container) Export() (archive.Archive, error) {
   751  	if err := container.Mount(); err != nil {
   752  		return nil, err
   753  	}
   754  
   755  	archive, err := archive.Tar(container.basefs, archive.Uncompressed)
   756  	if err != nil {
   757  		container.Unmount()
   758  		return nil, err
   759  	}
   760  	return ioutils.NewReadCloserWrapper(archive, func() error {
   761  			err := archive.Close()
   762  			container.Unmount()
   763  			return err
   764  		}),
   765  		nil
   766  }
   767  
   768  func (container *Container) Mount() error {
   769  	return container.daemon.Mount(container)
   770  }
   771  
   772  func (container *Container) changes() ([]archive.Change, error) {
   773  	return container.daemon.Changes(container)
   774  }
   775  
   776  func (container *Container) Changes() ([]archive.Change, error) {
   777  	container.Lock()
   778  	defer container.Unlock()
   779  	return container.changes()
   780  }
   781  
   782  func (container *Container) GetImage() (*image.Image, error) {
   783  	if container.daemon == nil {
   784  		return nil, fmt.Errorf("Can't get image of unregistered container")
   785  	}
   786  	return container.daemon.graph.Get(container.ImageID)
   787  }
   788  
   789  func (container *Container) Unmount() error {
   790  	return container.daemon.Unmount(container)
   791  }
   792  
   793  func (container *Container) logPath(name string) (string, error) {
   794  	return container.getRootResourcePath(fmt.Sprintf("%s-%s.log", container.ID, name))
   795  }
   796  
   797  func (container *Container) ReadLog(name string) (io.Reader, error) {
   798  	pth, err := container.logPath(name)
   799  	if err != nil {
   800  		return nil, err
   801  	}
   802  	return os.Open(pth)
   803  }
   804  
   805  func (container *Container) hostConfigPath() (string, error) {
   806  	return container.getRootResourcePath("hostconfig.json")
   807  }
   808  
   809  func (container *Container) jsonPath() (string, error) {
   810  	return container.getRootResourcePath("config.json")
   811  }
   812  
   813  // This method must be exported to be used from the lxc template
   814  // This directory is only usable when the container is running
   815  func (container *Container) RootfsPath() string {
   816  	return container.basefs
   817  }
   818  
   819  func validateID(id string) error {
   820  	if id == "" {
   821  		return fmt.Errorf("Invalid empty id")
   822  	}
   823  	return nil
   824  }
   825  
   826  // GetSize, return real size, virtual size
   827  func (container *Container) GetSize() (int64, int64) {
   828  	var (
   829  		sizeRw, sizeRootfs int64
   830  		err                error
   831  		driver             = container.daemon.driver
   832  	)
   833  
   834  	if err := container.Mount(); err != nil {
   835  		log.Errorf("Warning: failed to compute size of container rootfs %s: %s", container.ID, err)
   836  		return sizeRw, sizeRootfs
   837  	}
   838  	defer container.Unmount()
   839  
   840  	initID := fmt.Sprintf("%s-init", container.ID)
   841  	sizeRw, err = driver.DiffSize(container.ID, initID)
   842  	if err != nil {
   843  		log.Errorf("Warning: driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
   844  		// FIXME: GetSize should return an error. Not changing it now in case
   845  		// there is a side-effect.
   846  		sizeRw = -1
   847  	}
   848  
   849  	if _, err = os.Stat(container.basefs); err != nil {
   850  		if sizeRootfs, err = utils.TreeSize(container.basefs); err != nil {
   851  			sizeRootfs = -1
   852  		}
   853  	}
   854  	return sizeRw, sizeRootfs
   855  }
   856  
   857  func (container *Container) Copy(resource string) (io.ReadCloser, error) {
   858  	if err := container.Mount(); err != nil {
   859  		return nil, err
   860  	}
   861  
   862  	basePath, err := container.getResourcePath(resource)
   863  	if err != nil {
   864  		container.Unmount()
   865  		return nil, err
   866  	}
   867  
   868  	// Check if this is actually in a volume
   869  	for _, mnt := range container.VolumeMounts() {
   870  		if len(mnt.MountToPath) > 0 && strings.HasPrefix(resource, mnt.MountToPath[1:]) {
   871  			return mnt.Export(resource)
   872  		}
   873  	}
   874  
   875  	stat, err := os.Stat(basePath)
   876  	if err != nil {
   877  		container.Unmount()
   878  		return nil, err
   879  	}
   880  	var filter []string
   881  	if !stat.IsDir() {
   882  		d, f := path.Split(basePath)
   883  		basePath = d
   884  		filter = []string{f}
   885  	} else {
   886  		filter = []string{path.Base(basePath)}
   887  		basePath = path.Dir(basePath)
   888  	}
   889  
   890  	archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
   891  		Compression:  archive.Uncompressed,
   892  		IncludeFiles: filter,
   893  	})
   894  	if err != nil {
   895  		container.Unmount()
   896  		return nil, err
   897  	}
   898  	return ioutils.NewReadCloserWrapper(archive, func() error {
   899  			err := archive.Close()
   900  			container.Unmount()
   901  			return err
   902  		}),
   903  		nil
   904  }
   905  
   906  // Returns true if the container exposes a certain port
   907  func (container *Container) Exposes(p nat.Port) bool {
   908  	_, exists := container.Config.ExposedPorts[p]
   909  	return exists
   910  }
   911  
   912  func (container *Container) GetPtyMaster() (*os.File, error) {
   913  	ttyConsole, ok := container.command.ProcessConfig.Terminal.(execdriver.TtyTerminal)
   914  	if !ok {
   915  		return nil, ErrNoTTY
   916  	}
   917  	return ttyConsole.Master(), nil
   918  }
   919  
   920  func (container *Container) HostConfig() *runconfig.HostConfig {
   921  	container.Lock()
   922  	res := container.hostConfig
   923  	container.Unlock()
   924  	return res
   925  }
   926  
   927  func (container *Container) SetHostConfig(hostConfig *runconfig.HostConfig) {
   928  	container.Lock()
   929  	container.hostConfig = hostConfig
   930  	container.Unlock()
   931  }
   932  
   933  func (container *Container) DisableLink(name string) {
   934  	if container.activeLinks != nil {
   935  		if link, exists := container.activeLinks[name]; exists {
   936  			link.Disable()
   937  		} else {
   938  			log.Debugf("Could not find active link for %s", name)
   939  		}
   940  	}
   941  }
   942  
   943  func (container *Container) setupContainerDns() error {
   944  	if container.ResolvConfPath != "" {
   945  		return nil
   946  	}
   947  
   948  	var (
   949  		config = container.hostConfig
   950  		daemon = container.daemon
   951  	)
   952  
   953  	resolvConf, err := resolvconf.Get()
   954  	if err != nil {
   955  		return err
   956  	}
   957  	container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf")
   958  	if err != nil {
   959  		return err
   960  	}
   961  
   962  	if config.NetworkMode != "host" {
   963  		// check configurations for any container/daemon dns settings
   964  		if len(config.Dns) > 0 || len(daemon.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(daemon.config.DnsSearch) > 0 {
   965  			var (
   966  				dns       = resolvconf.GetNameservers(resolvConf)
   967  				dnsSearch = resolvconf.GetSearchDomains(resolvConf)
   968  			)
   969  			if len(config.Dns) > 0 {
   970  				dns = config.Dns
   971  			} else if len(daemon.config.Dns) > 0 {
   972  				dns = daemon.config.Dns
   973  			}
   974  			if len(config.DnsSearch) > 0 {
   975  				dnsSearch = config.DnsSearch
   976  			} else if len(daemon.config.DnsSearch) > 0 {
   977  				dnsSearch = daemon.config.DnsSearch
   978  			}
   979  			return resolvconf.Build(container.ResolvConfPath, dns, dnsSearch)
   980  		}
   981  
   982  		// replace any localhost/127.* nameservers
   983  		resolvConf = utils.RemoveLocalDns(resolvConf)
   984  		// if the resulting resolvConf is empty, use DefaultDns
   985  		if !bytes.Contains(resolvConf, []byte("nameserver")) {
   986  			log.Infof("No non localhost DNS resolver found in resolv.conf and containers can't use it. Using default external servers : %v", DefaultDns)
   987  			// prefix the default dns options with nameserver
   988  			resolvConf = append(resolvConf, []byte("\nnameserver "+strings.Join(DefaultDns, "\nnameserver "))...)
   989  		}
   990  	}
   991  	return ioutil.WriteFile(container.ResolvConfPath, resolvConf, 0644)
   992  }
   993  
   994  func (container *Container) updateParentsHosts() error {
   995  	parents, err := container.daemon.Parents(container.Name)
   996  	if err != nil {
   997  		return err
   998  	}
   999  	for _, cid := range parents {
  1000  		if cid == "0" {
  1001  			continue
  1002  		}
  1003  
  1004  		c := container.daemon.Get(cid)
  1005  		if c != nil && !container.daemon.config.DisableNetwork && container.hostConfig.NetworkMode.IsPrivate() {
  1006  			if err := etchosts.Update(c.HostsPath, container.NetworkSettings.IPAddress, container.Name[1:]); err != nil {
  1007  				log.Errorf("Failed to update /etc/hosts in parent container: %v", err)
  1008  			}
  1009  		}
  1010  	}
  1011  	return nil
  1012  }
  1013  
  1014  func (container *Container) initializeNetworking() error {
  1015  	var err error
  1016  	if container.hostConfig.NetworkMode.IsHost() {
  1017  		container.Config.Hostname, err = os.Hostname()
  1018  		if err != nil {
  1019  			return err
  1020  		}
  1021  
  1022  		parts := strings.SplitN(container.Config.Hostname, ".", 2)
  1023  		if len(parts) > 1 {
  1024  			container.Config.Hostname = parts[0]
  1025  			container.Config.Domainname = parts[1]
  1026  		}
  1027  
  1028  		content, err := ioutil.ReadFile("/etc/hosts")
  1029  		if os.IsNotExist(err) {
  1030  			return container.buildHostnameAndHostsFiles("")
  1031  		} else if err != nil {
  1032  			return err
  1033  		}
  1034  
  1035  		if err := container.buildHostnameFile(); err != nil {
  1036  			return err
  1037  		}
  1038  
  1039  		hostsPath, err := container.getRootResourcePath("hosts")
  1040  		if err != nil {
  1041  			return err
  1042  		}
  1043  		container.HostsPath = hostsPath
  1044  
  1045  		return ioutil.WriteFile(container.HostsPath, content, 0644)
  1046  	}
  1047  	if container.hostConfig.NetworkMode.IsContainer() {
  1048  		// we need to get the hosts files from the container to join
  1049  		nc, err := container.getNetworkedContainer()
  1050  		if err != nil {
  1051  			return err
  1052  		}
  1053  		container.HostsPath = nc.HostsPath
  1054  		container.ResolvConfPath = nc.ResolvConfPath
  1055  		container.Config.Hostname = nc.Config.Hostname
  1056  		container.Config.Domainname = nc.Config.Domainname
  1057  		return nil
  1058  	}
  1059  	if container.daemon.config.DisableNetwork {
  1060  		container.Config.NetworkDisabled = true
  1061  		return container.buildHostnameAndHostsFiles("127.0.1.1")
  1062  	}
  1063  	if err := container.AllocateNetwork(); err != nil {
  1064  		return err
  1065  	}
  1066  	return container.buildHostnameAndHostsFiles(container.NetworkSettings.IPAddress)
  1067  }
  1068  
  1069  // Make sure the config is compatible with the current kernel
  1070  func (container *Container) verifyDaemonSettings() {
  1071  	if container.Config.Memory > 0 && !container.daemon.sysInfo.MemoryLimit {
  1072  		log.Infof("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
  1073  		container.Config.Memory = 0
  1074  	}
  1075  	if container.Config.Memory > 0 && !container.daemon.sysInfo.SwapLimit {
  1076  		log.Infof("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.")
  1077  		container.Config.MemorySwap = -1
  1078  	}
  1079  	if container.daemon.sysInfo.IPv4ForwardingDisabled {
  1080  		log.Infof("WARNING: IPv4 forwarding is disabled. Networking will not work")
  1081  	}
  1082  }
  1083  
  1084  func (container *Container) setupLinkedContainers() ([]string, error) {
  1085  	var (
  1086  		env    []string
  1087  		daemon = container.daemon
  1088  	)
  1089  	children, err := daemon.Children(container.Name)
  1090  	if err != nil {
  1091  		return nil, err
  1092  	}
  1093  
  1094  	if len(children) > 0 {
  1095  		container.activeLinks = make(map[string]*links.Link, len(children))
  1096  
  1097  		// If we encounter an error make sure that we rollback any network
  1098  		// config and ip table changes
  1099  		rollback := func() {
  1100  			for _, link := range container.activeLinks {
  1101  				link.Disable()
  1102  			}
  1103  			container.activeLinks = nil
  1104  		}
  1105  
  1106  		for linkAlias, child := range children {
  1107  			if !child.IsRunning() {
  1108  				return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
  1109  			}
  1110  
  1111  			link, err := links.NewLink(
  1112  				container.NetworkSettings.IPAddress,
  1113  				child.NetworkSettings.IPAddress,
  1114  				linkAlias,
  1115  				child.Config.Env,
  1116  				child.Config.ExposedPorts,
  1117  				daemon.eng)
  1118  
  1119  			if err != nil {
  1120  				rollback()
  1121  				return nil, err
  1122  			}
  1123  
  1124  			container.activeLinks[link.Alias()] = link
  1125  			if err := link.Enable(); err != nil {
  1126  				rollback()
  1127  				return nil, err
  1128  			}
  1129  
  1130  			for _, envVar := range link.ToEnv() {
  1131  				env = append(env, envVar)
  1132  			}
  1133  		}
  1134  	}
  1135  	return env, nil
  1136  }
  1137  
  1138  func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
  1139  	// if a domain name was specified, append it to the hostname (see #7851)
  1140  	fullHostname := container.Config.Hostname
  1141  	if container.Config.Domainname != "" {
  1142  		fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
  1143  	}
  1144  	// Setup environment
  1145  	env := []string{
  1146  		"PATH=" + DefaultPathEnv,
  1147  		"HOSTNAME=" + fullHostname,
  1148  		// Note: we don't set HOME here because it'll get autoset intelligently
  1149  		// based on the value of USER inside dockerinit, but only if it isn't
  1150  		// set already (ie, that can be overridden by setting HOME via -e or ENV
  1151  		// in a Dockerfile).
  1152  	}
  1153  	if container.Config.Tty {
  1154  		env = append(env, "TERM=xterm")
  1155  	}
  1156  	env = append(env, linkedEnv...)
  1157  	// because the env on the container can override certain default values
  1158  	// we need to replace the 'env' keys where they match and append anything
  1159  	// else.
  1160  	env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
  1161  
  1162  	return env
  1163  }
  1164  
  1165  func (container *Container) setupWorkingDirectory() error {
  1166  	if container.Config.WorkingDir != "" {
  1167  		container.Config.WorkingDir = path.Clean(container.Config.WorkingDir)
  1168  
  1169  		pth, err := container.getResourcePath(container.Config.WorkingDir)
  1170  		if err != nil {
  1171  			return err
  1172  		}
  1173  
  1174  		pthInfo, err := os.Stat(pth)
  1175  		if err != nil {
  1176  			if !os.IsNotExist(err) {
  1177  				return err
  1178  			}
  1179  
  1180  			if err := os.MkdirAll(pth, 0755); err != nil {
  1181  				return err
  1182  			}
  1183  		}
  1184  		if pthInfo != nil && !pthInfo.IsDir() {
  1185  			return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
  1186  		}
  1187  	}
  1188  	return nil
  1189  }
  1190  
  1191  func (container *Container) startLoggingToDisk() error {
  1192  	// Setup logging of stdout and stderr to disk
  1193  	pth, err := container.logPath("json")
  1194  	if err != nil {
  1195  		return err
  1196  	}
  1197  
  1198  	if err := container.daemon.LogToDisk(container.stdout, pth, "stdout"); err != nil {
  1199  		return err
  1200  	}
  1201  
  1202  	if err := container.daemon.LogToDisk(container.stderr, pth, "stderr"); err != nil {
  1203  		return err
  1204  	}
  1205  
  1206  	return nil
  1207  }
  1208  
  1209  func (container *Container) waitForStart() error {
  1210  	container.monitor = newContainerMonitor(container, container.hostConfig.RestartPolicy)
  1211  
  1212  	// block until we either receive an error from the initial start of the container's
  1213  	// process or until the process is running in the container
  1214  	select {
  1215  	case <-container.monitor.startSignal:
  1216  	case err := <-promise.Go(container.monitor.Start):
  1217  		return err
  1218  	}
  1219  
  1220  	return nil
  1221  }
  1222  
  1223  func (container *Container) allocatePort(eng *engine.Engine, port nat.Port, bindings nat.PortMap) error {
  1224  	binding := bindings[port]
  1225  	if container.hostConfig.PublishAllPorts && len(binding) == 0 {
  1226  		binding = append(binding, nat.PortBinding{})
  1227  	}
  1228  
  1229  	for i := 0; i < len(binding); i++ {
  1230  		b := binding[i]
  1231  
  1232  		job := eng.Job("allocate_port", container.ID)
  1233  		job.Setenv("HostIP", b.HostIp)
  1234  		job.Setenv("HostPort", b.HostPort)
  1235  		job.Setenv("Proto", port.Proto())
  1236  		job.Setenv("ContainerPort", port.Port())
  1237  
  1238  		portEnv, err := job.Stdout.AddEnv()
  1239  		if err != nil {
  1240  			return err
  1241  		}
  1242  		if err := job.Run(); err != nil {
  1243  			return err
  1244  		}
  1245  		b.HostIp = portEnv.Get("HostIP")
  1246  		b.HostPort = portEnv.Get("HostPort")
  1247  
  1248  		binding[i] = b
  1249  	}
  1250  	bindings[port] = binding
  1251  	return nil
  1252  }
  1253  
  1254  func (container *Container) GetProcessLabel() string {
  1255  	// even if we have a process label return "" if we are running
  1256  	// in privileged mode
  1257  	if container.hostConfig.Privileged {
  1258  		return ""
  1259  	}
  1260  	return container.ProcessLabel
  1261  }
  1262  
  1263  func (container *Container) GetMountLabel() string {
  1264  	if container.hostConfig.Privileged {
  1265  		return ""
  1266  	}
  1267  	return container.MountLabel
  1268  }
  1269  
  1270  func (container *Container) getIpcContainer() (*Container, error) {
  1271  	containerID := container.hostConfig.IpcMode.Container()
  1272  	c := container.daemon.Get(containerID)
  1273  	if c == nil {
  1274  		return nil, fmt.Errorf("no such container to join IPC: %s", containerID)
  1275  	}
  1276  	if !c.IsRunning() {
  1277  		return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
  1278  	}
  1279  	return c, nil
  1280  }
  1281  
  1282  func (container *Container) getNetworkedContainer() (*Container, error) {
  1283  	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
  1284  	switch parts[0] {
  1285  	case "container":
  1286  		if len(parts) != 2 {
  1287  			return nil, fmt.Errorf("no container specified to join network")
  1288  		}
  1289  		nc := container.daemon.Get(parts[1])
  1290  		if nc == nil {
  1291  			return nil, fmt.Errorf("no such container to join network: %s", parts[1])
  1292  		}
  1293  		if !nc.IsRunning() {
  1294  			return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
  1295  		}
  1296  		return nc, nil
  1297  	default:
  1298  		return nil, fmt.Errorf("network mode not set to container")
  1299  	}
  1300  }