github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/daemon/container_unix.go (about)

     1  // +build linux freebsd
     2  
     3  package daemon
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  	"strconv"
    13  	"strings"
    14  	"syscall"
    15  	"time"
    16  
    17  	"github.com/Sirupsen/logrus"
    18  	"github.com/docker/docker/daemon/execdriver"
    19  	"github.com/docker/docker/daemon/links"
    20  	"github.com/docker/docker/daemon/network"
    21  	derr "github.com/docker/docker/errors"
    22  	"github.com/docker/docker/pkg/directory"
    23  	"github.com/docker/docker/pkg/nat"
    24  	"github.com/docker/docker/pkg/stringid"
    25  	"github.com/docker/docker/pkg/system"
    26  	"github.com/docker/docker/pkg/ulimit"
    27  	"github.com/docker/docker/runconfig"
    28  	"github.com/docker/docker/utils"
    29  	"github.com/docker/docker/volume"
    30  	"github.com/docker/docker/volume/store"
    31  	"github.com/docker/libnetwork"
    32  	"github.com/docker/libnetwork/netlabel"
    33  	"github.com/docker/libnetwork/options"
    34  	"github.com/docker/libnetwork/types"
    35  	"github.com/opencontainers/runc/libcontainer/configs"
    36  	"github.com/opencontainers/runc/libcontainer/devices"
    37  	"github.com/opencontainers/runc/libcontainer/label"
    38  )
    39  
    40  // DefaultPathEnv is unix style list of directories to search for
    41  // executables. Each directory is separated from the next by a colon
    42  // ':' character .
    43  const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    44  
    45  // Container holds the fields specific to unixen implementations. See
    46  // CommonContainer for standard fields common to all containers.
    47  type Container struct {
    48  	CommonContainer
    49  
    50  	// Fields below here are platform specific.
    51  	activeLinks     map[string]*links.Link
    52  	AppArmorProfile string
    53  	HostnamePath    string
    54  	HostsPath       string
    55  	MountPoints     map[string]*mountPoint
    56  	ResolvConfPath  string
    57  
    58  	Volumes   map[string]string // Deprecated since 1.7, kept for backwards compatibility
    59  	VolumesRW map[string]bool   // Deprecated since 1.7, kept for backwards compatibility
    60  }
    61  
    62  func killProcessDirectly(container *Container) error {
    63  	if _, err := container.WaitStop(10 * time.Second); err != nil {
    64  		// Ensure that we don't kill ourselves
    65  		if pid := container.getPID(); pid != 0 {
    66  			logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID))
    67  			if err := syscall.Kill(pid, 9); err != nil {
    68  				if err != syscall.ESRCH {
    69  					return err
    70  				}
    71  				logrus.Debugf("Cannot kill process (pid=%d) with signal 9: no such process.", pid)
    72  			}
    73  		}
    74  	}
    75  	return nil
    76  }
    77  
    78  func (container *Container) setupLinkedContainers() ([]string, error) {
    79  	var (
    80  		env    []string
    81  		daemon = container.daemon
    82  	)
    83  	children, err := daemon.children(container.Name)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	if len(children) > 0 {
    89  		for linkAlias, child := range children {
    90  			if !child.IsRunning() {
    91  				return nil, derr.ErrorCodeLinkNotRunning.WithArgs(child.Name, linkAlias)
    92  			}
    93  
    94  			link := links.NewLink(
    95  				container.NetworkSettings.IPAddress,
    96  				child.NetworkSettings.IPAddress,
    97  				linkAlias,
    98  				child.Config.Env,
    99  				child.Config.ExposedPorts,
   100  			)
   101  
   102  			for _, envVar := range link.ToEnv() {
   103  				env = append(env, envVar)
   104  			}
   105  		}
   106  	}
   107  	return env, nil
   108  }
   109  
   110  func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
   111  	// if a domain name was specified, append it to the hostname (see #7851)
   112  	fullHostname := container.Config.Hostname
   113  	if container.Config.Domainname != "" {
   114  		fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
   115  	}
   116  	// Setup environment
   117  	env := []string{
   118  		"PATH=" + DefaultPathEnv,
   119  		"HOSTNAME=" + fullHostname,
   120  		// Note: we don't set HOME here because it'll get autoset intelligently
   121  		// based on the value of USER inside dockerinit, but only if it isn't
   122  		// set already (ie, that can be overridden by setting HOME via -e or ENV
   123  		// in a Dockerfile).
   124  	}
   125  	if container.Config.Tty {
   126  		env = append(env, "TERM=xterm")
   127  	}
   128  	env = append(env, linkedEnv...)
   129  	// because the env on the container can override certain default values
   130  	// we need to replace the 'env' keys where they match and append anything
   131  	// else.
   132  	env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
   133  
   134  	return env
   135  }
   136  
   137  func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) {
   138  	device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
   139  	// if there was no error, return the device
   140  	if err == nil {
   141  		device.Path = deviceMapping.PathInContainer
   142  		return append(devs, device), nil
   143  	}
   144  
   145  	// if the device is not a device node
   146  	// try to see if it's a directory holding many devices
   147  	if err == devices.ErrNotADevice {
   148  
   149  		// check if it is a directory
   150  		if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
   151  
   152  			// mount the internal devices recursively
   153  			filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
   154  				childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
   155  				if e != nil {
   156  					// ignore the device
   157  					return nil
   158  				}
   159  
   160  				// add the device to userSpecified devices
   161  				childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
   162  				devs = append(devs, childDevice)
   163  
   164  				return nil
   165  			})
   166  		}
   167  	}
   168  
   169  	if len(devs) > 0 {
   170  		return devs, nil
   171  	}
   172  
   173  	return devs, derr.ErrorCodeDeviceInfo.WithArgs(deviceMapping.PathOnHost, err)
   174  }
   175  
   176  func populateCommand(c *Container, env []string) error {
   177  	var en *execdriver.Network
   178  	if !c.Config.NetworkDisabled {
   179  		en = &execdriver.Network{}
   180  		if !c.daemon.execDriver.SupportsHooks() || c.hostConfig.NetworkMode.IsHost() {
   181  			en.NamespacePath = c.NetworkSettings.SandboxKey
   182  		}
   183  
   184  		parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
   185  		if parts[0] == "container" {
   186  			nc, err := c.getNetworkedContainer()
   187  			if err != nil {
   188  				return err
   189  			}
   190  			en.ContainerID = nc.ID
   191  		}
   192  	}
   193  
   194  	ipc := &execdriver.Ipc{}
   195  
   196  	if c.hostConfig.IpcMode.IsContainer() {
   197  		ic, err := c.getIpcContainer()
   198  		if err != nil {
   199  			return err
   200  		}
   201  		ipc.ContainerID = ic.ID
   202  	} else {
   203  		ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
   204  	}
   205  
   206  	pid := &execdriver.Pid{}
   207  	pid.HostPid = c.hostConfig.PidMode.IsHost()
   208  
   209  	uts := &execdriver.UTS{
   210  		HostUTS: c.hostConfig.UTSMode.IsHost(),
   211  	}
   212  
   213  	// Build lists of devices allowed and created within the container.
   214  	var userSpecifiedDevices []*configs.Device
   215  	for _, deviceMapping := range c.hostConfig.Devices {
   216  		devs, err := getDevicesFromPath(deviceMapping)
   217  		if err != nil {
   218  			return err
   219  		}
   220  
   221  		userSpecifiedDevices = append(userSpecifiedDevices, devs...)
   222  	}
   223  
   224  	allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
   225  
   226  	autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
   227  
   228  	// TODO: this can be removed after lxc-conf is fully deprecated
   229  	lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
   230  	if err != nil {
   231  		return err
   232  	}
   233  
   234  	var rlimits []*ulimit.Rlimit
   235  	ulimits := c.hostConfig.Ulimits
   236  
   237  	// Merge ulimits with daemon defaults
   238  	ulIdx := make(map[string]*ulimit.Ulimit)
   239  	for _, ul := range ulimits {
   240  		ulIdx[ul.Name] = ul
   241  	}
   242  	for name, ul := range c.daemon.configStore.Ulimits {
   243  		if _, exists := ulIdx[name]; !exists {
   244  			ulimits = append(ulimits, ul)
   245  		}
   246  	}
   247  
   248  	for _, limit := range ulimits {
   249  		rl, err := limit.GetRlimit()
   250  		if err != nil {
   251  			return err
   252  		}
   253  		rlimits = append(rlimits, rl)
   254  	}
   255  
   256  	resources := &execdriver.Resources{
   257  		Memory:           c.hostConfig.Memory,
   258  		MemorySwap:       c.hostConfig.MemorySwap,
   259  		KernelMemory:     c.hostConfig.KernelMemory,
   260  		CPUShares:        c.hostConfig.CPUShares,
   261  		CpusetCpus:       c.hostConfig.CpusetCpus,
   262  		CpusetMems:       c.hostConfig.CpusetMems,
   263  		CPUPeriod:        c.hostConfig.CPUPeriod,
   264  		CPUQuota:         c.hostConfig.CPUQuota,
   265  		BlkioWeight:      c.hostConfig.BlkioWeight,
   266  		Rlimits:          rlimits,
   267  		OomKillDisable:   c.hostConfig.OomKillDisable,
   268  		MemorySwappiness: -1,
   269  	}
   270  
   271  	if c.hostConfig.MemorySwappiness != nil {
   272  		resources.MemorySwappiness = *c.hostConfig.MemorySwappiness
   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  		ReadonlyRootfs:     c.hostConfig.ReadonlyRootfs,
   290  		InitPath:           "/.dockerinit",
   291  		WorkingDir:         c.Config.WorkingDir,
   292  		Network:            en,
   293  		Ipc:                ipc,
   294  		Pid:                pid,
   295  		UTS:                uts,
   296  		Resources:          resources,
   297  		AllowedDevices:     allowedDevices,
   298  		AutoCreatedDevices: autoCreatedDevices,
   299  		CapAdd:             c.hostConfig.CapAdd.Slice(),
   300  		CapDrop:            c.hostConfig.CapDrop.Slice(),
   301  		GroupAdd:           c.hostConfig.GroupAdd,
   302  		ProcessConfig:      processConfig,
   303  		ProcessLabel:       c.getProcessLabel(),
   304  		MountLabel:         c.getMountLabel(),
   305  		LxcConfig:          lxcConfig,
   306  		AppArmorProfile:    c.AppArmorProfile,
   307  		CgroupParent:       c.hostConfig.CgroupParent,
   308  	}
   309  
   310  	return nil
   311  }
   312  
   313  func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
   314  	if len(userDevices) == 0 {
   315  		return defaultDevices
   316  	}
   317  
   318  	paths := map[string]*configs.Device{}
   319  	for _, d := range userDevices {
   320  		paths[d.Path] = d
   321  	}
   322  
   323  	var devs []*configs.Device
   324  	for _, d := range defaultDevices {
   325  		if _, defined := paths[d.Path]; !defined {
   326  			devs = append(devs, d)
   327  		}
   328  	}
   329  	return append(devs, userDevices...)
   330  }
   331  
   332  // GetSize returns the real size & virtual size of the container.
   333  func (container *Container) getSize() (int64, int64) {
   334  	var (
   335  		sizeRw, sizeRootfs int64
   336  		err                error
   337  		driver             = container.daemon.driver
   338  	)
   339  
   340  	if err := container.Mount(); err != nil {
   341  		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
   342  		return sizeRw, sizeRootfs
   343  	}
   344  	defer container.Unmount()
   345  
   346  	initID := fmt.Sprintf("%s-init", container.ID)
   347  	sizeRw, err = driver.DiffSize(container.ID, initID)
   348  	if err != nil {
   349  		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
   350  		// FIXME: GetSize should return an error. Not changing it now in case
   351  		// there is a side-effect.
   352  		sizeRw = -1
   353  	}
   354  
   355  	if _, err = os.Stat(container.basefs); err == nil {
   356  		if sizeRootfs, err = directory.Size(container.basefs); err != nil {
   357  			sizeRootfs = -1
   358  		}
   359  	}
   360  	return sizeRw, sizeRootfs
   361  }
   362  
   363  // Attempt to set the network mounts given a provided destination and
   364  // the path to use for it; return true if the given destination was a
   365  // network mount file
   366  func (container *Container) trySetNetworkMount(destination string, path string) bool {
   367  	if destination == "/etc/resolv.conf" {
   368  		container.ResolvConfPath = path
   369  		return true
   370  	}
   371  	if destination == "/etc/hostname" {
   372  		container.HostnamePath = path
   373  		return true
   374  	}
   375  	if destination == "/etc/hosts" {
   376  		container.HostsPath = path
   377  		return true
   378  	}
   379  
   380  	return false
   381  }
   382  
   383  func (container *Container) buildHostnameFile() error {
   384  	hostnamePath, err := container.getRootResourcePath("hostname")
   385  	if err != nil {
   386  		return err
   387  	}
   388  	container.HostnamePath = hostnamePath
   389  
   390  	if container.Config.Domainname != "" {
   391  		return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
   392  	}
   393  	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
   394  }
   395  
   396  func (container *Container) buildSandboxOptions() ([]libnetwork.SandboxOption, error) {
   397  	var (
   398  		sboxOptions []libnetwork.SandboxOption
   399  		err         error
   400  		dns         []string
   401  		dnsSearch   []string
   402  		dnsOptions  []string
   403  	)
   404  
   405  	sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
   406  		libnetwork.OptionDomainname(container.Config.Domainname))
   407  
   408  	if container.hostConfig.NetworkMode.IsHost() {
   409  		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
   410  		sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
   411  		sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
   412  	} else if container.daemon.execDriver.SupportsHooks() {
   413  		// OptionUseExternalKey is mandatory for userns support.
   414  		// But optional for non-userns support
   415  		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
   416  	}
   417  
   418  	container.HostsPath, err = container.getRootResourcePath("hosts")
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
   423  
   424  	container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf")
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  	sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
   429  
   430  	if len(container.hostConfig.DNS) > 0 {
   431  		dns = container.hostConfig.DNS
   432  	} else if len(container.daemon.configStore.DNS) > 0 {
   433  		dns = container.daemon.configStore.DNS
   434  	}
   435  
   436  	for _, d := range dns {
   437  		sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
   438  	}
   439  
   440  	if len(container.hostConfig.DNSSearch) > 0 {
   441  		dnsSearch = container.hostConfig.DNSSearch
   442  	} else if len(container.daemon.configStore.DNSSearch) > 0 {
   443  		dnsSearch = container.daemon.configStore.DNSSearch
   444  	}
   445  
   446  	for _, ds := range dnsSearch {
   447  		sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
   448  	}
   449  
   450  	if len(container.hostConfig.DNSOptions) > 0 {
   451  		dnsOptions = container.hostConfig.DNSOptions
   452  	} else if len(container.daemon.configStore.DNSOptions) > 0 {
   453  		dnsOptions = container.daemon.configStore.DNSOptions
   454  	}
   455  
   456  	for _, ds := range dnsOptions {
   457  		sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
   458  	}
   459  
   460  	if container.NetworkSettings.SecondaryIPAddresses != nil {
   461  		name := container.Config.Hostname
   462  		if container.Config.Domainname != "" {
   463  			name = name + "." + container.Config.Domainname
   464  		}
   465  
   466  		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
   467  			sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
   468  		}
   469  	}
   470  
   471  	var childEndpoints, parentEndpoints []string
   472  
   473  	children, err := container.daemon.children(container.Name)
   474  	if err != nil {
   475  		return nil, err
   476  	}
   477  
   478  	for linkAlias, child := range children {
   479  		_, alias := path.Split(linkAlias)
   480  		// allow access to the linked container via the alias, real name, and container hostname
   481  		aliasList := alias + " " + child.Config.Hostname
   482  		// only add the name if alias isn't equal to the name
   483  		if alias != child.Name[1:] {
   484  			aliasList = aliasList + " " + child.Name[1:]
   485  		}
   486  		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
   487  		if child.NetworkSettings.EndpointID != "" {
   488  			childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID)
   489  		}
   490  	}
   491  
   492  	for _, extraHost := range container.hostConfig.ExtraHosts {
   493  		// allow IPv6 addresses in extra hosts; only split on first ":"
   494  		parts := strings.SplitN(extraHost, ":", 2)
   495  		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
   496  	}
   497  
   498  	refs := container.daemon.containerGraph().RefPaths(container.ID)
   499  	for _, ref := range refs {
   500  		if ref.ParentID == "0" {
   501  			continue
   502  		}
   503  
   504  		c, err := container.daemon.Get(ref.ParentID)
   505  		if err != nil {
   506  			logrus.Error(err)
   507  		}
   508  
   509  		if c != nil && !container.daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
   510  			logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
   511  			sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, container.NetworkSettings.IPAddress))
   512  			if c.NetworkSettings.EndpointID != "" {
   513  				parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID)
   514  			}
   515  		}
   516  	}
   517  
   518  	linkOptions := options.Generic{
   519  		netlabel.GenericData: options.Generic{
   520  			"ParentEndpoints": parentEndpoints,
   521  			"ChildEndpoints":  childEndpoints,
   522  		},
   523  	}
   524  
   525  	sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
   526  
   527  	return sboxOptions, nil
   528  }
   529  
   530  func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
   531  	if ep == nil {
   532  		return nil, derr.ErrorCodeEmptyEndpoint
   533  	}
   534  
   535  	if networkSettings == nil {
   536  		return nil, derr.ErrorCodeEmptyNetwork
   537  	}
   538  
   539  	driverInfo, err := ep.DriverInfo()
   540  	if err != nil {
   541  		return nil, err
   542  	}
   543  
   544  	if driverInfo == nil {
   545  		// It is not an error for epInfo to be nil
   546  		return networkSettings, nil
   547  	}
   548  
   549  	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
   550  		networkSettings.MacAddress = mac.(net.HardwareAddr).String()
   551  	}
   552  
   553  	networkSettings.Ports = nat.PortMap{}
   554  
   555  	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
   556  		if exposedPorts, ok := expData.([]types.TransportPort); ok {
   557  			for _, tp := range exposedPorts {
   558  				natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
   559  				if err != nil {
   560  					return nil, derr.ErrorCodeParsingPort.WithArgs(tp.Port, err)
   561  				}
   562  				networkSettings.Ports[natPort] = nil
   563  			}
   564  		}
   565  	}
   566  
   567  	mapData, ok := driverInfo[netlabel.PortMap]
   568  	if !ok {
   569  		return networkSettings, nil
   570  	}
   571  
   572  	if portMapping, ok := mapData.([]types.PortBinding); ok {
   573  		for _, pp := range portMapping {
   574  			natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
   575  			if err != nil {
   576  				return nil, err
   577  			}
   578  			natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
   579  			networkSettings.Ports[natPort] = append(networkSettings.Ports[natPort], natBndg)
   580  		}
   581  	}
   582  
   583  	return networkSettings, nil
   584  }
   585  
   586  func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
   587  	if ep == nil {
   588  		return nil, derr.ErrorCodeEmptyEndpoint
   589  	}
   590  
   591  	if networkSettings == nil {
   592  		return nil, derr.ErrorCodeEmptyNetwork
   593  	}
   594  
   595  	epInfo := ep.Info()
   596  	if epInfo == nil {
   597  		// It is not an error to get an empty endpoint info
   598  		return networkSettings, nil
   599  	}
   600  
   601  	iface := epInfo.Iface()
   602  	if iface == nil {
   603  		return networkSettings, nil
   604  	}
   605  
   606  	ones, _ := iface.Address().Mask.Size()
   607  	networkSettings.IPAddress = iface.Address().IP.String()
   608  	networkSettings.IPPrefixLen = ones
   609  
   610  	if iface.AddressIPv6().IP.To16() != nil {
   611  		onesv6, _ := iface.AddressIPv6().Mask.Size()
   612  		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
   613  		networkSettings.GlobalIPv6PrefixLen = onesv6
   614  	}
   615  
   616  	return networkSettings, nil
   617  }
   618  
   619  func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
   620  	epInfo := ep.Info()
   621  	if epInfo == nil {
   622  		// It is not an error to get an empty endpoint info
   623  		return nil
   624  	}
   625  
   626  	container.NetworkSettings.Gateway = epInfo.Gateway().String()
   627  	if epInfo.GatewayIPv6().To16() != nil {
   628  		container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
   629  	}
   630  
   631  	return nil
   632  }
   633  
   634  func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
   635  	networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}
   636  
   637  	networkSettings, err := container.buildPortMapInfo(ep, networkSettings)
   638  	if err != nil {
   639  		return err
   640  	}
   641  
   642  	networkSettings, err = container.buildEndpointInfo(ep, networkSettings)
   643  	if err != nil {
   644  		return err
   645  	}
   646  
   647  	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
   648  		networkSettings.Bridge = container.daemon.configStore.Bridge.Iface
   649  	}
   650  
   651  	container.NetworkSettings = networkSettings
   652  	return nil
   653  }
   654  
   655  func (container *Container) updateSandboxNetworkSettings(sb libnetwork.Sandbox) error {
   656  	container.NetworkSettings.SandboxID = sb.ID()
   657  	container.NetworkSettings.SandboxKey = sb.Key()
   658  	return nil
   659  }
   660  
   661  // UpdateNetwork is used to update the container's network (e.g. when linked containers
   662  // get removed/unlinked).
   663  func (container *Container) updateNetwork() error {
   664  	ctrl := container.daemon.netController
   665  	sid := container.NetworkSettings.SandboxID
   666  
   667  	sb, err := ctrl.SandboxByID(sid)
   668  	if err != nil {
   669  		return derr.ErrorCodeNoSandbox.WithArgs(sid, err)
   670  	}
   671  
   672  	options, err := container.buildSandboxOptions()
   673  	if err != nil {
   674  		return derr.ErrorCodeNetworkUpdate.WithArgs(err)
   675  	}
   676  
   677  	if err := sb.Refresh(options...); err != nil {
   678  		return derr.ErrorCodeNetworkRefresh.WithArgs(sid, err)
   679  	}
   680  
   681  	return nil
   682  }
   683  
   684  func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointOption, error) {
   685  	var (
   686  		portSpecs     = make(nat.PortSet)
   687  		bindings      = make(nat.PortMap)
   688  		pbList        []types.PortBinding
   689  		exposeList    []types.TransportPort
   690  		createOptions []libnetwork.EndpointOption
   691  	)
   692  
   693  	if container.Config.ExposedPorts != nil {
   694  		portSpecs = container.Config.ExposedPorts
   695  	}
   696  
   697  	if container.hostConfig.PortBindings != nil {
   698  		for p, b := range container.hostConfig.PortBindings {
   699  			bindings[p] = []nat.PortBinding{}
   700  			for _, bb := range b {
   701  				bindings[p] = append(bindings[p], nat.PortBinding{
   702  					HostIP:   bb.HostIP,
   703  					HostPort: bb.HostPort,
   704  				})
   705  			}
   706  		}
   707  	}
   708  
   709  	ports := make([]nat.Port, len(portSpecs))
   710  	var i int
   711  	for p := range portSpecs {
   712  		ports[i] = p
   713  		i++
   714  	}
   715  	nat.SortPortMap(ports, bindings)
   716  	for _, port := range ports {
   717  		expose := types.TransportPort{}
   718  		expose.Proto = types.ParseProtocol(port.Proto())
   719  		expose.Port = uint16(port.Int())
   720  		exposeList = append(exposeList, expose)
   721  
   722  		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
   723  		binding := bindings[port]
   724  		for i := 0; i < len(binding); i++ {
   725  			pbCopy := pb.GetCopy()
   726  			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
   727  			var portStart, portEnd int
   728  			if err == nil {
   729  				portStart, portEnd, err = newP.Range()
   730  			}
   731  			if err != nil {
   732  				return nil, derr.ErrorCodeHostPort.WithArgs(binding[i].HostPort, err)
   733  			}
   734  			pbCopy.HostPort = uint16(portStart)
   735  			pbCopy.HostPortEnd = uint16(portEnd)
   736  			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
   737  			pbList = append(pbList, pbCopy)
   738  		}
   739  
   740  		if container.hostConfig.PublishAllPorts && len(binding) == 0 {
   741  			pbList = append(pbList, pb)
   742  		}
   743  	}
   744  
   745  	createOptions = append(createOptions,
   746  		libnetwork.CreateOptionPortMapping(pbList),
   747  		libnetwork.CreateOptionExposedPorts(exposeList))
   748  
   749  	if container.Config.MacAddress != "" {
   750  		mac, err := net.ParseMAC(container.Config.MacAddress)
   751  		if err != nil {
   752  			return nil, err
   753  		}
   754  
   755  		genericOption := options.Generic{
   756  			netlabel.MacAddress: mac,
   757  		}
   758  
   759  		createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
   760  	}
   761  
   762  	return createOptions, nil
   763  }
   764  
   765  func parseService(controller libnetwork.NetworkController, service string) (string, string, string) {
   766  	dn := controller.Config().Daemon.DefaultNetwork
   767  	dd := controller.Config().Daemon.DefaultDriver
   768  
   769  	snd := strings.Split(service, ".")
   770  	if len(snd) > 2 {
   771  		return strings.Join(snd[:len(snd)-2], "."), snd[len(snd)-2], snd[len(snd)-1]
   772  	}
   773  	if len(snd) > 1 {
   774  		return snd[0], snd[1], dd
   775  	}
   776  	return snd[0], dn, dd
   777  }
   778  
   779  func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
   780  	createOptions := []libnetwork.NetworkOption{}
   781  	genericOption := options.Generic{}
   782  
   783  	// Bridge driver is special due to legacy reasons
   784  	if runconfig.NetworkMode(driver).IsBridge() {
   785  		genericOption[netlabel.GenericData] = map[string]interface{}{
   786  			"BridgeName":            dnet,
   787  			"AllowNonDefaultBridge": "true",
   788  		}
   789  		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
   790  		createOptions = append(createOptions, networkOption)
   791  	}
   792  
   793  	return controller.NewNetwork(driver, dnet, createOptions...)
   794  }
   795  
   796  func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
   797  	switch primaryNetworkType {
   798  	case "bridge", "none", "host", "container":
   799  		return false
   800  	}
   801  
   802  	if container.daemon.configStore.DisableBridge {
   803  		return false
   804  	}
   805  
   806  	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
   807  		return true
   808  	}
   809  	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
   810  		return true
   811  	}
   812  	return false
   813  }
   814  
   815  func (container *Container) allocateNetwork() error {
   816  	mode := container.hostConfig.NetworkMode
   817  	controller := container.daemon.netController
   818  	if container.Config.NetworkDisabled || mode.IsContainer() {
   819  		return nil
   820  	}
   821  
   822  	networkDriver := string(mode)
   823  	service := container.Config.PublishService
   824  	networkName := mode.NetworkName()
   825  	if mode.IsDefault() {
   826  		if service != "" {
   827  			service, networkName, networkDriver = parseService(controller, service)
   828  		} else {
   829  			networkName = controller.Config().Daemon.DefaultNetwork
   830  			networkDriver = controller.Config().Daemon.DefaultDriver
   831  		}
   832  	} else if service != "" {
   833  		return derr.ErrorCodeNetworkConflict
   834  	}
   835  
   836  	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.configStore.DisableBridge {
   837  		container.Config.NetworkDisabled = true
   838  		return nil
   839  	}
   840  
   841  	if service == "" {
   842  		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
   843  		// For backward compatibility, replacing "." with "-", instead of failing
   844  		service = strings.Replace(container.Name, ".", "-", -1)
   845  		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
   846  		service = strings.Replace(service, "/", "", -1)
   847  	}
   848  
   849  	if container.secondaryNetworkRequired(networkDriver) {
   850  		// Configure Bridge as secondary network for port binding purposes
   851  		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
   852  			return err
   853  		}
   854  	}
   855  
   856  	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
   857  		return err
   858  	}
   859  
   860  	return container.writeHostConfig()
   861  }
   862  
   863  func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
   864  	controller := container.daemon.netController
   865  
   866  	n, err := controller.NetworkByName(networkName)
   867  	if err != nil {
   868  		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
   869  			return err
   870  		}
   871  
   872  		if n, err = createNetwork(controller, networkName, networkDriver); err != nil {
   873  			return err
   874  		}
   875  	}
   876  
   877  	ep, err := n.EndpointByName(service)
   878  	if err != nil {
   879  		if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
   880  			return err
   881  		}
   882  
   883  		createOptions, err := container.buildCreateEndpointOptions()
   884  		if err != nil {
   885  			return err
   886  		}
   887  
   888  		ep, err = n.CreateEndpoint(service, createOptions...)
   889  		if err != nil {
   890  			return err
   891  		}
   892  	}
   893  
   894  	if err := container.updateEndpointNetworkSettings(n, ep); err != nil {
   895  		return err
   896  	}
   897  
   898  	var sb libnetwork.Sandbox
   899  	controller.WalkSandboxes(func(s libnetwork.Sandbox) bool {
   900  		if s.ContainerID() == container.ID {
   901  			sb = s
   902  			return true
   903  		}
   904  		return false
   905  	})
   906  	if sb == nil {
   907  		options, err := container.buildSandboxOptions()
   908  		if err != nil {
   909  			return err
   910  		}
   911  		sb, err = controller.NewSandbox(container.ID, options...)
   912  		if err != nil {
   913  			return err
   914  		}
   915  	}
   916  
   917  	container.updateSandboxNetworkSettings(sb)
   918  
   919  	if err := ep.Join(sb); err != nil {
   920  		return err
   921  	}
   922  
   923  	if err := container.updateJoinInfo(ep); err != nil {
   924  		return derr.ErrorCodeJoinInfo.WithArgs(err)
   925  	}
   926  
   927  	return nil
   928  }
   929  
   930  func (container *Container) initializeNetworking() error {
   931  	var err error
   932  
   933  	if container.hostConfig.NetworkMode.IsContainer() {
   934  		// we need to get the hosts files from the container to join
   935  		nc, err := container.getNetworkedContainer()
   936  		if err != nil {
   937  			return err
   938  		}
   939  		container.HostnamePath = nc.HostnamePath
   940  		container.HostsPath = nc.HostsPath
   941  		container.ResolvConfPath = nc.ResolvConfPath
   942  		container.Config.Hostname = nc.Config.Hostname
   943  		container.Config.Domainname = nc.Config.Domainname
   944  		return nil
   945  	}
   946  
   947  	if container.hostConfig.NetworkMode.IsHost() {
   948  		container.Config.Hostname, err = os.Hostname()
   949  		if err != nil {
   950  			return err
   951  		}
   952  
   953  		parts := strings.SplitN(container.Config.Hostname, ".", 2)
   954  		if len(parts) > 1 {
   955  			container.Config.Hostname = parts[0]
   956  			container.Config.Domainname = parts[1]
   957  		}
   958  
   959  	}
   960  
   961  	if err := container.allocateNetwork(); err != nil {
   962  		return err
   963  	}
   964  
   965  	return container.buildHostnameFile()
   966  }
   967  
   968  // called from the libcontainer pre-start hook to set the network
   969  // namespace configuration linkage to the libnetwork "sandbox" entity
   970  func (container *Container) setNetworkNamespaceKey(pid int) error {
   971  	path := fmt.Sprintf("/proc/%d/ns/net", pid)
   972  	var sandbox libnetwork.Sandbox
   973  	search := libnetwork.SandboxContainerWalker(&sandbox, container.ID)
   974  	container.daemon.netController.WalkSandboxes(search)
   975  	if sandbox == nil {
   976  		return fmt.Errorf("no sandbox present for %s", container.ID)
   977  	}
   978  
   979  	return sandbox.SetKey(path)
   980  }
   981  
   982  func (container *Container) getIpcContainer() (*Container, error) {
   983  	containerID := container.hostConfig.IpcMode.Container()
   984  	c, err := container.daemon.Get(containerID)
   985  	if err != nil {
   986  		return nil, err
   987  	}
   988  	if !c.IsRunning() {
   989  		return nil, derr.ErrorCodeIPCRunning
   990  	}
   991  	return c, nil
   992  }
   993  
   994  func (container *Container) setupWorkingDirectory() error {
   995  	if container.Config.WorkingDir != "" {
   996  		container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
   997  
   998  		pth, err := container.GetResourcePath(container.Config.WorkingDir)
   999  		if err != nil {
  1000  			return err
  1001  		}
  1002  
  1003  		pthInfo, err := os.Stat(pth)
  1004  		if err != nil {
  1005  			if !os.IsNotExist(err) {
  1006  				return err
  1007  			}
  1008  
  1009  			if err := system.MkdirAll(pth, 0755); err != nil {
  1010  				return err
  1011  			}
  1012  		}
  1013  		if pthInfo != nil && !pthInfo.IsDir() {
  1014  			return derr.ErrorCodeNotADir.WithArgs(container.Config.WorkingDir)
  1015  		}
  1016  	}
  1017  	return nil
  1018  }
  1019  
  1020  func (container *Container) getNetworkedContainer() (*Container, error) {
  1021  	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
  1022  	switch parts[0] {
  1023  	case "container":
  1024  		if len(parts) != 2 {
  1025  			return nil, derr.ErrorCodeParseContainer
  1026  		}
  1027  		nc, err := container.daemon.Get(parts[1])
  1028  		if err != nil {
  1029  			return nil, err
  1030  		}
  1031  		if container == nc {
  1032  			return nil, derr.ErrorCodeJoinSelf
  1033  		}
  1034  		if !nc.IsRunning() {
  1035  			return nil, derr.ErrorCodeJoinRunning.WithArgs(parts[1])
  1036  		}
  1037  		return nc, nil
  1038  	default:
  1039  		return nil, derr.ErrorCodeModeNotContainer
  1040  	}
  1041  }
  1042  
  1043  func (container *Container) releaseNetwork() {
  1044  	if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
  1045  		return
  1046  	}
  1047  
  1048  	sid := container.NetworkSettings.SandboxID
  1049  	eid := container.NetworkSettings.EndpointID
  1050  	nid := container.NetworkSettings.NetworkID
  1051  
  1052  	container.NetworkSettings = &network.Settings{}
  1053  
  1054  	if sid == "" || nid == "" || eid == "" {
  1055  		return
  1056  	}
  1057  
  1058  	sb, err := container.daemon.netController.SandboxByID(sid)
  1059  	if err != nil {
  1060  		logrus.Errorf("error locating sandbox id %s: %v", sid, err)
  1061  		return
  1062  	}
  1063  
  1064  	n, err := container.daemon.netController.NetworkByID(nid)
  1065  	if err != nil {
  1066  		logrus.Errorf("error locating network id %s: %v", nid, err)
  1067  		return
  1068  	}
  1069  
  1070  	ep, err := n.EndpointByID(eid)
  1071  	if err != nil {
  1072  		logrus.Errorf("error locating endpoint id %s: %v", eid, err)
  1073  		return
  1074  	}
  1075  
  1076  	if err := sb.Delete(); err != nil {
  1077  		logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
  1078  		return
  1079  	}
  1080  
  1081  	// In addition to leaving all endpoints, delete implicitly created endpoint
  1082  	if container.Config.PublishService == "" {
  1083  		if err := ep.Delete(); err != nil {
  1084  			logrus.Errorf("deleting endpoint failed: %v", err)
  1085  		}
  1086  	}
  1087  }
  1088  
  1089  func (container *Container) unmountVolumes(forceSyscall bool) error {
  1090  	var volumeMounts []mountPoint
  1091  
  1092  	for _, mntPoint := range container.MountPoints {
  1093  		dest, err := container.GetResourcePath(mntPoint.Destination)
  1094  		if err != nil {
  1095  			return err
  1096  		}
  1097  
  1098  		volumeMounts = append(volumeMounts, mountPoint{Destination: dest, Volume: mntPoint.Volume})
  1099  	}
  1100  
  1101  	for _, mnt := range container.networkMounts() {
  1102  		dest, err := container.GetResourcePath(mnt.Destination)
  1103  		if err != nil {
  1104  			return err
  1105  		}
  1106  
  1107  		volumeMounts = append(volumeMounts, mountPoint{Destination: dest})
  1108  	}
  1109  
  1110  	for _, volumeMount := range volumeMounts {
  1111  		if forceSyscall {
  1112  			syscall.Unmount(volumeMount.Destination, 0)
  1113  		}
  1114  
  1115  		if volumeMount.Volume != nil {
  1116  			if err := volumeMount.Volume.Unmount(); err != nil {
  1117  				return err
  1118  			}
  1119  		}
  1120  	}
  1121  
  1122  	return nil
  1123  }
  1124  
  1125  func (container *Container) networkMounts() []execdriver.Mount {
  1126  	var mounts []execdriver.Mount
  1127  	shared := container.hostConfig.NetworkMode.IsContainer()
  1128  	if container.ResolvConfPath != "" {
  1129  		label.Relabel(container.ResolvConfPath, container.MountLabel, shared)
  1130  		writable := !container.hostConfig.ReadonlyRootfs
  1131  		if m, exists := container.MountPoints["/etc/resolv.conf"]; exists {
  1132  			writable = m.RW
  1133  		}
  1134  		mounts = append(mounts, execdriver.Mount{
  1135  			Source:      container.ResolvConfPath,
  1136  			Destination: "/etc/resolv.conf",
  1137  			Writable:    writable,
  1138  			Private:     true,
  1139  		})
  1140  	}
  1141  	if container.HostnamePath != "" {
  1142  		label.Relabel(container.HostnamePath, container.MountLabel, shared)
  1143  		writable := !container.hostConfig.ReadonlyRootfs
  1144  		if m, exists := container.MountPoints["/etc/hostname"]; exists {
  1145  			writable = m.RW
  1146  		}
  1147  		mounts = append(mounts, execdriver.Mount{
  1148  			Source:      container.HostnamePath,
  1149  			Destination: "/etc/hostname",
  1150  			Writable:    writable,
  1151  			Private:     true,
  1152  		})
  1153  	}
  1154  	if container.HostsPath != "" {
  1155  		label.Relabel(container.HostsPath, container.MountLabel, shared)
  1156  		writable := !container.hostConfig.ReadonlyRootfs
  1157  		if m, exists := container.MountPoints["/etc/hosts"]; exists {
  1158  			writable = m.RW
  1159  		}
  1160  		mounts = append(mounts, execdriver.Mount{
  1161  			Source:      container.HostsPath,
  1162  			Destination: "/etc/hosts",
  1163  			Writable:    writable,
  1164  			Private:     true,
  1165  		})
  1166  	}
  1167  	return mounts
  1168  }
  1169  
  1170  func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
  1171  	container.MountPoints[destination] = &mountPoint{
  1172  		Name:        name,
  1173  		Source:      source,
  1174  		Destination: destination,
  1175  		RW:          rw,
  1176  	}
  1177  }
  1178  
  1179  func (container *Container) addLocalMountPoint(name, destination string, rw bool) {
  1180  	container.MountPoints[destination] = &mountPoint{
  1181  		Name:        name,
  1182  		Driver:      volume.DefaultDriverName,
  1183  		Destination: destination,
  1184  		RW:          rw,
  1185  	}
  1186  }
  1187  
  1188  func (container *Container) addMountPointWithVolume(destination string, vol volume.Volume, rw bool) {
  1189  	container.MountPoints[destination] = &mountPoint{
  1190  		Name:        vol.Name(),
  1191  		Driver:      vol.DriverName(),
  1192  		Destination: destination,
  1193  		RW:          rw,
  1194  		Volume:      vol,
  1195  	}
  1196  }
  1197  
  1198  func (container *Container) isDestinationMounted(destination string) bool {
  1199  	return container.MountPoints[destination] != nil
  1200  }
  1201  
  1202  func (container *Container) prepareMountPoints() error {
  1203  	for _, config := range container.MountPoints {
  1204  		if len(config.Driver) > 0 {
  1205  			v, err := container.daemon.createVolume(config.Name, config.Driver, nil)
  1206  			if err != nil {
  1207  				return err
  1208  			}
  1209  			config.Volume = v
  1210  		}
  1211  	}
  1212  	return nil
  1213  }
  1214  
  1215  func (container *Container) removeMountPoints(rm bool) error {
  1216  	var rmErrors []string
  1217  	for _, m := range container.MountPoints {
  1218  		if m.Volume == nil {
  1219  			continue
  1220  		}
  1221  		container.daemon.volumes.Decrement(m.Volume)
  1222  		if rm {
  1223  			err := container.daemon.volumes.Remove(m.Volume)
  1224  			// ErrVolumeInUse is ignored because having this
  1225  			// volume being referenced by othe container is
  1226  			// not an error, but an implementation detail.
  1227  			// This prevents docker from logging "ERROR: Volume in use"
  1228  			// where there is another container using the volume.
  1229  			if err != nil && err != store.ErrVolumeInUse {
  1230  				rmErrors = append(rmErrors, err.Error())
  1231  			}
  1232  		}
  1233  	}
  1234  	if len(rmErrors) > 0 {
  1235  		return derr.ErrorCodeRemovingVolume.WithArgs(strings.Join(rmErrors, "\n"))
  1236  	}
  1237  	return nil
  1238  }