github.com/psychoss/docker@v1.9.0/daemon/daemon_unix.go (about)

     1  // +build linux freebsd
     2  
     3  package daemon
     4  
     5  import (
     6  	"fmt"
     7  	"net"
     8  	"os"
     9  	"path/filepath"
    10  	"strconv"
    11  	"strings"
    12  	"syscall"
    13  
    14  	"github.com/Sirupsen/logrus"
    15  	"github.com/docker/docker/autogen/dockerversion"
    16  	"github.com/docker/docker/daemon/graphdriver"
    17  	derr "github.com/docker/docker/errors"
    18  	"github.com/docker/docker/pkg/fileutils"
    19  	"github.com/docker/docker/pkg/idtools"
    20  	"github.com/docker/docker/pkg/parsers"
    21  	"github.com/docker/docker/pkg/parsers/kernel"
    22  	"github.com/docker/docker/pkg/sysinfo"
    23  	"github.com/docker/docker/runconfig"
    24  	"github.com/docker/docker/utils"
    25  	"github.com/docker/libnetwork"
    26  	nwconfig "github.com/docker/libnetwork/config"
    27  	"github.com/docker/libnetwork/drivers/bridge"
    28  	"github.com/docker/libnetwork/ipamutils"
    29  	"github.com/docker/libnetwork/netlabel"
    30  	"github.com/docker/libnetwork/options"
    31  	"github.com/docker/libnetwork/types"
    32  	"github.com/opencontainers/runc/libcontainer/label"
    33  	"github.com/vishvananda/netlink"
    34  )
    35  
    36  const (
    37  	// See https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269
    38  	linuxMinCPUShares = 2
    39  	linuxMaxCPUShares = 262144
    40  	platformSupported = true
    41  )
    42  
    43  func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
    44  	var (
    45  		labelOpts []string
    46  		err       error
    47  	)
    48  
    49  	for _, opt := range config.SecurityOpt {
    50  		con := strings.SplitN(opt, ":", 2)
    51  		if len(con) == 1 {
    52  			return fmt.Errorf("Invalid --security-opt: %q", opt)
    53  		}
    54  		switch con[0] {
    55  		case "label":
    56  			labelOpts = append(labelOpts, con[1])
    57  		case "apparmor":
    58  			container.AppArmorProfile = con[1]
    59  		default:
    60  			return fmt.Errorf("Invalid --security-opt: %q", opt)
    61  		}
    62  	}
    63  
    64  	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
    65  	return err
    66  }
    67  
    68  func checkKernelVersion(k, major, minor int) bool {
    69  	if v, err := kernel.GetKernelVersion(); err != nil {
    70  		logrus.Warnf("%s", err)
    71  	} else {
    72  		if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 {
    73  			return false
    74  		}
    75  	}
    76  	return true
    77  }
    78  
    79  func checkKernel() error {
    80  	// Check for unsupported kernel versions
    81  	// FIXME: it would be cleaner to not test for specific versions, but rather
    82  	// test for specific functionalities.
    83  	// Unfortunately we can't test for the feature "does not cause a kernel panic"
    84  	// without actually causing a kernel panic, so we need this workaround until
    85  	// the circumstances of pre-3.10 crashes are clearer.
    86  	// For details see https://github.com/docker/docker/issues/407
    87  	if !checkKernelVersion(3, 10, 0) {
    88  		v, _ := kernel.GetKernelVersion()
    89  		if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
    90  			logrus.Warnf("Your Linux kernel version %s can be unstable running docker. Please upgrade your kernel to 3.10.0.", v.String())
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  // adaptContainerSettings is called during container creation to modify any
    97  // settings necessary in the HostConfig structure.
    98  func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) {
    99  	if hostConfig == nil {
   100  		return
   101  	}
   102  
   103  	if adjustCPUShares && hostConfig.CPUShares > 0 {
   104  		// Handle unsupported CPUShares
   105  		if hostConfig.CPUShares < linuxMinCPUShares {
   106  			logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares)
   107  			hostConfig.CPUShares = linuxMinCPUShares
   108  		} else if hostConfig.CPUShares > linuxMaxCPUShares {
   109  			logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares)
   110  			hostConfig.CPUShares = linuxMaxCPUShares
   111  		}
   112  	}
   113  	if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 {
   114  		// By default, MemorySwap is set to twice the size of Memory.
   115  		hostConfig.MemorySwap = hostConfig.Memory * 2
   116  	}
   117  }
   118  
   119  // verifyPlatformContainerSettings performs platform-specific validation of the
   120  // hostconfig and config structures.
   121  func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
   122  	warnings := []string{}
   123  	sysInfo := sysinfo.New(true)
   124  
   125  	warnings, err := daemon.verifyExperimentalContainerSettings(hostConfig, config)
   126  	if err != nil {
   127  		return warnings, err
   128  	}
   129  
   130  	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
   131  		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
   132  	}
   133  
   134  	// memory subsystem checks and adjustments
   135  	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
   136  		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
   137  	}
   138  	if hostConfig.Memory > 0 && !sysInfo.MemoryLimit {
   139  		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
   140  		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
   141  		hostConfig.Memory = 0
   142  		hostConfig.MemorySwap = -1
   143  	}
   144  	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit {
   145  		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
   146  		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
   147  		hostConfig.MemorySwap = -1
   148  	}
   149  	if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory {
   150  		return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
   151  	}
   152  	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
   153  		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
   154  	}
   155  	if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
   156  		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
   157  		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
   158  		hostConfig.MemorySwappiness = nil
   159  	}
   160  	if hostConfig.MemorySwappiness != nil {
   161  		swappiness := *hostConfig.MemorySwappiness
   162  		if swappiness < -1 || swappiness > 100 {
   163  			return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
   164  		}
   165  	}
   166  	if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation {
   167  		warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.")
   168  		logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.")
   169  		hostConfig.MemoryReservation = 0
   170  	}
   171  	if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation {
   172  		return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
   173  	}
   174  	if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory {
   175  		warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
   176  		logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
   177  		hostConfig.KernelMemory = 0
   178  	}
   179  	if hostConfig.KernelMemory > 0 && !checkKernelVersion(4, 0, 0) {
   180  		warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.")
   181  		logrus.Warnf("You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.")
   182  	}
   183  	if hostConfig.CPUShares > 0 && !sysInfo.CPUShares {
   184  		warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.")
   185  		logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.")
   186  		hostConfig.CPUShares = 0
   187  	}
   188  	if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
   189  		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
   190  		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
   191  		hostConfig.CPUPeriod = 0
   192  	}
   193  	if hostConfig.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
   194  		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
   195  		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
   196  		hostConfig.CPUQuota = 0
   197  	}
   198  	if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset {
   199  		warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.")
   200  		logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.")
   201  		hostConfig.CpusetCpus = ""
   202  		hostConfig.CpusetMems = ""
   203  	}
   204  	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus)
   205  	if err != nil {
   206  		return warnings, derr.ErrorCodeInvalidCpusetCpus.WithArgs(hostConfig.CpusetCpus)
   207  	}
   208  	if !cpusAvailable {
   209  		return warnings, derr.ErrorCodeNotAvailableCpusetCpus.WithArgs(hostConfig.CpusetCpus, sysInfo.Cpus)
   210  	}
   211  	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems)
   212  	if err != nil {
   213  		return warnings, derr.ErrorCodeInvalidCpusetMems.WithArgs(hostConfig.CpusetMems)
   214  	}
   215  	if !memsAvailable {
   216  		return warnings, derr.ErrorCodeNotAvailableCpusetMems.WithArgs(hostConfig.CpusetMems, sysInfo.Mems)
   217  	}
   218  	if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight {
   219  		warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.")
   220  		logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.")
   221  		hostConfig.BlkioWeight = 0
   222  	}
   223  	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
   224  		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
   225  	}
   226  	if hostConfig.OomKillDisable && !sysInfo.OomKillDisable {
   227  		hostConfig.OomKillDisable = false
   228  		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
   229  	}
   230  
   231  	if sysInfo.IPv4ForwardingDisabled {
   232  		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
   233  		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
   234  	}
   235  	return warnings, nil
   236  }
   237  
   238  // checkConfigOptions checks for mutually incompatible config options
   239  func checkConfigOptions(config *Config) error {
   240  	// Check for mutually incompatible config options
   241  	if config.Bridge.Iface != "" && config.Bridge.IP != "" {
   242  		return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
   243  	}
   244  	if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication {
   245  		return fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
   246  	}
   247  	if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq {
   248  		config.Bridge.EnableIPMasq = false
   249  	}
   250  	return nil
   251  }
   252  
   253  // checkSystem validates platform-specific requirements
   254  func checkSystem() error {
   255  	if os.Geteuid() != 0 {
   256  		return fmt.Errorf("The Docker daemon needs to be run as root")
   257  	}
   258  	return checkKernel()
   259  }
   260  
   261  // configureKernelSecuritySupport configures and validate security support for the kernel
   262  func configureKernelSecuritySupport(config *Config, driverName string) error {
   263  	if config.EnableSelinuxSupport {
   264  		if selinuxEnabled() {
   265  			// As Docker on either btrfs or overlayFS and SELinux are incompatible at present, error on both being enabled
   266  			if driverName == "btrfs" || driverName == "overlay" {
   267  				return fmt.Errorf("SELinux is not supported with the %s graph driver", driverName)
   268  			}
   269  			logrus.Debug("SELinux enabled successfully")
   270  		} else {
   271  			logrus.Warn("Docker could not enable SELinux on the host system")
   272  		}
   273  	} else {
   274  		selinuxSetDisabled()
   275  	}
   276  	return nil
   277  }
   278  
   279  // MigrateIfDownlevel is a wrapper for AUFS migration for downlevel
   280  func migrateIfDownlevel(driver graphdriver.Driver, root string) error {
   281  	return migrateIfAufs(driver, root)
   282  }
   283  
   284  func configureSysInit(config *Config, rootUID, rootGID int) (string, error) {
   285  	localCopy := filepath.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION))
   286  	sysInitPath := utils.DockerInitPath(localCopy)
   287  	if sysInitPath == "" {
   288  		return "", fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/project/set-up-dev-env/ for official build instructions.")
   289  	}
   290  
   291  	if sysInitPath != localCopy {
   292  		// 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).
   293  		if err := idtools.MkdirAs(filepath.Dir(localCopy), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
   294  			return "", err
   295  		}
   296  		if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil {
   297  			return "", err
   298  		}
   299  		if err := os.Chmod(localCopy, 0700); err != nil {
   300  			return "", err
   301  		}
   302  		sysInitPath = localCopy
   303  	}
   304  	return sysInitPath, nil
   305  }
   306  
   307  func isBridgeNetworkDisabled(config *Config) bool {
   308  	return config.Bridge.Iface == disableNetworkBridge
   309  }
   310  
   311  func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
   312  	options := []nwconfig.Option{}
   313  	if dconfig == nil {
   314  		return options, nil
   315  	}
   316  
   317  	options = append(options, nwconfig.OptionDataDir(dconfig.Root))
   318  
   319  	if strings.TrimSpace(dconfig.DefaultNetwork) != "" {
   320  		dn := strings.Split(dconfig.DefaultNetwork, ":")
   321  		if len(dn) < 2 {
   322  			return nil, fmt.Errorf("default network daemon config must be of the form NETWORKDRIVER:NETWORKNAME")
   323  		}
   324  		options = append(options, nwconfig.OptionDefaultDriver(dn[0]))
   325  		options = append(options, nwconfig.OptionDefaultNetwork(strings.Join(dn[1:], ":")))
   326  	} else {
   327  		dd := runconfig.DefaultDaemonNetworkMode()
   328  		dn := runconfig.DefaultDaemonNetworkMode().NetworkName()
   329  		options = append(options, nwconfig.OptionDefaultDriver(string(dd)))
   330  		options = append(options, nwconfig.OptionDefaultNetwork(dn))
   331  	}
   332  
   333  	if strings.TrimSpace(dconfig.ClusterStore) != "" {
   334  		kv := strings.Split(dconfig.ClusterStore, "://")
   335  		if len(kv) < 2 {
   336  			return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL")
   337  		}
   338  		options = append(options, nwconfig.OptionKVProvider(kv[0]))
   339  		options = append(options, nwconfig.OptionKVProviderURL(strings.Join(kv[1:], "://")))
   340  	}
   341  	if len(dconfig.ClusterOpts) > 0 {
   342  		options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts))
   343  	}
   344  
   345  	if daemon.discoveryWatcher != nil {
   346  		options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher))
   347  	}
   348  
   349  	if dconfig.ClusterAdvertise != "" {
   350  		options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise))
   351  	}
   352  
   353  	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
   354  	options = append(options, driverOptions(dconfig)...)
   355  	return options, nil
   356  }
   357  
   358  func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
   359  	netOptions, err := daemon.networkOptions(config)
   360  	if err != nil {
   361  		return nil, err
   362  	}
   363  
   364  	controller, err := libnetwork.New(netOptions...)
   365  	if err != nil {
   366  		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
   367  	}
   368  
   369  	// Initialize default network on "null"
   370  	if _, err := controller.NewNetwork("null", "none", libnetwork.NetworkOptionPersist(false)); err != nil {
   371  		return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
   372  	}
   373  
   374  	// Initialize default network on "host"
   375  	if _, err := controller.NewNetwork("host", "host", libnetwork.NetworkOptionPersist(false)); err != nil {
   376  		return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
   377  	}
   378  
   379  	if !config.DisableBridge {
   380  		// Initialize default driver "bridge"
   381  		if err := initBridgeDriver(controller, config); err != nil {
   382  			return nil, err
   383  		}
   384  	}
   385  
   386  	return controller, nil
   387  }
   388  
   389  func driverOptions(config *Config) []nwconfig.Option {
   390  	bridgeConfig := options.Generic{
   391  		"EnableIPForwarding":  config.Bridge.EnableIPForward,
   392  		"EnableIPTables":      config.Bridge.EnableIPTables,
   393  		"EnableUserlandProxy": config.Bridge.EnableUserlandProxy}
   394  	bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig}
   395  
   396  	dOptions := []nwconfig.Option{}
   397  	dOptions = append(dOptions, nwconfig.OptionDriverConfig("bridge", bridgeOption))
   398  	return dOptions
   399  }
   400  
   401  func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
   402  	if n, err := controller.NetworkByName("bridge"); err == nil {
   403  		if err = n.Delete(); err != nil {
   404  			return fmt.Errorf("could not delete the default bridge network: %v", err)
   405  		}
   406  	}
   407  
   408  	bridgeName := bridge.DefaultBridgeName
   409  	if config.Bridge.Iface != "" {
   410  		bridgeName = config.Bridge.Iface
   411  	}
   412  	netOption := map[string]string{
   413  		bridge.BridgeName:         bridgeName,
   414  		bridge.DefaultBridge:      strconv.FormatBool(true),
   415  		netlabel.DriverMTU:        strconv.Itoa(config.Mtu),
   416  		bridge.EnableIPMasquerade: strconv.FormatBool(config.Bridge.EnableIPMasq),
   417  		bridge.EnableICC:          strconv.FormatBool(config.Bridge.InterContainerCommunication),
   418  	}
   419  
   420  	// --ip processing
   421  	if config.Bridge.DefaultIP != nil {
   422  		netOption[bridge.DefaultBindingIP] = config.Bridge.DefaultIP.String()
   423  	}
   424  
   425  	ipamV4Conf := libnetwork.IpamConf{}
   426  
   427  	ipamV4Conf.AuxAddresses = make(map[string]string)
   428  
   429  	if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil {
   430  		ipamV4Conf.PreferredPool = nw.String()
   431  		hip, _ := types.GetHostPartIP(nw.IP, nw.Mask)
   432  		if hip.IsGlobalUnicast() {
   433  			ipamV4Conf.Gateway = nw.IP.String()
   434  		}
   435  	}
   436  
   437  	if config.Bridge.IP != "" {
   438  		ipamV4Conf.PreferredPool = config.Bridge.IP
   439  		ip, _, err := net.ParseCIDR(config.Bridge.IP)
   440  		if err != nil {
   441  			return err
   442  		}
   443  		ipamV4Conf.Gateway = ip.String()
   444  	} else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" {
   445  		logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool)
   446  	}
   447  
   448  	if config.Bridge.FixedCIDR != "" {
   449  		_, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR)
   450  		if err != nil {
   451  			return err
   452  		}
   453  
   454  		ipamV4Conf.SubPool = fCIDR.String()
   455  	}
   456  
   457  	if config.Bridge.DefaultGatewayIPv4 != nil {
   458  		ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String()
   459  	}
   460  
   461  	var ipamV6Conf *libnetwork.IpamConf
   462  	if config.Bridge.FixedCIDRv6 != "" {
   463  		_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
   464  		if err != nil {
   465  			return err
   466  		}
   467  		if ipamV6Conf == nil {
   468  			ipamV6Conf = &libnetwork.IpamConf{}
   469  		}
   470  		ipamV6Conf.PreferredPool = fCIDRv6.String()
   471  	}
   472  
   473  	if config.Bridge.DefaultGatewayIPv6 != nil {
   474  		if ipamV6Conf == nil {
   475  			ipamV6Conf = &libnetwork.IpamConf{}
   476  		}
   477  		ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6.String()
   478  	}
   479  
   480  	v4Conf := []*libnetwork.IpamConf{&ipamV4Conf}
   481  	v6Conf := []*libnetwork.IpamConf{}
   482  	if ipamV6Conf != nil {
   483  		v6Conf = append(v6Conf, ipamV6Conf)
   484  	}
   485  	// Initialize default network on "bridge" with the same name
   486  	_, err := controller.NewNetwork("bridge", "bridge",
   487  		libnetwork.NetworkOptionGeneric(options.Generic{
   488  			netlabel.GenericData: netOption,
   489  			netlabel.EnableIPv6:  config.Bridge.EnableIPv6,
   490  		}),
   491  		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf))
   492  	if err != nil {
   493  		return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
   494  	}
   495  	return nil
   496  }
   497  
   498  // setupInitLayer populates a directory with mountpoints suitable
   499  // for bind-mounting dockerinit into the container. The mountpoint is simply an
   500  // empty file at /.dockerinit
   501  //
   502  // This extra layer is used by all containers as the top-most ro layer. It protects
   503  // the container from unwanted side-effects on the rw layer.
   504  func setupInitLayer(initLayer string, rootUID, rootGID int) error {
   505  	for pth, typ := range map[string]string{
   506  		"/dev/pts":         "dir",
   507  		"/dev/shm":         "dir",
   508  		"/proc":            "dir",
   509  		"/sys":             "dir",
   510  		"/.dockerinit":     "file",
   511  		"/.dockerenv":      "file",
   512  		"/etc/resolv.conf": "file",
   513  		"/etc/hosts":       "file",
   514  		"/etc/hostname":    "file",
   515  		"/dev/console":     "file",
   516  		"/etc/mtab":        "/proc/mounts",
   517  	} {
   518  		parts := strings.Split(pth, "/")
   519  		prev := "/"
   520  		for _, p := range parts[1:] {
   521  			prev = filepath.Join(prev, p)
   522  			syscall.Unlink(filepath.Join(initLayer, prev))
   523  		}
   524  
   525  		if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
   526  			if os.IsNotExist(err) {
   527  				if err := idtools.MkdirAllAs(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootUID, rootGID); err != nil {
   528  					return err
   529  				}
   530  				switch typ {
   531  				case "dir":
   532  					if err := idtools.MkdirAllAs(filepath.Join(initLayer, pth), 0755, rootUID, rootGID); err != nil {
   533  						return err
   534  					}
   535  				case "file":
   536  					f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755)
   537  					if err != nil {
   538  						return err
   539  					}
   540  					f.Close()
   541  					f.Chown(rootUID, rootGID)
   542  				default:
   543  					if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
   544  						return err
   545  					}
   546  				}
   547  			} else {
   548  				return err
   549  			}
   550  		}
   551  	}
   552  
   553  	// Layer is ready to use, if it wasn't before.
   554  	return nil
   555  }
   556  
   557  // registerLinks writes the links to a file.
   558  func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error {
   559  	if hostConfig == nil || hostConfig.Links == nil {
   560  		return nil
   561  	}
   562  
   563  	for _, l := range hostConfig.Links {
   564  		name, alias, err := parsers.ParseLink(l)
   565  		if err != nil {
   566  			return err
   567  		}
   568  		child, err := daemon.Get(name)
   569  		if err != nil {
   570  			//An error from daemon.Get() means this name could not be found
   571  			return fmt.Errorf("Could not get container for %s", name)
   572  		}
   573  		for child.hostConfig.NetworkMode.IsContainer() {
   574  			parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2)
   575  			child, err = daemon.Get(parts[1])
   576  			if err != nil {
   577  				return fmt.Errorf("Could not get container for %s", parts[1])
   578  			}
   579  		}
   580  		if child.hostConfig.NetworkMode.IsHost() {
   581  			return runconfig.ErrConflictHostNetworkAndLinks
   582  		}
   583  		if err := daemon.registerLink(container, child, alias); err != nil {
   584  			return err
   585  		}
   586  	}
   587  
   588  	// After we load all the links into the daemon
   589  	// set them to nil on the hostconfig
   590  	hostConfig.Links = nil
   591  	if err := container.writeHostConfig(); err != nil {
   592  		return err
   593  	}
   594  
   595  	return nil
   596  }
   597  
   598  func (daemon *Daemon) newBaseContainer(id string) Container {
   599  	return Container{
   600  		CommonContainer: CommonContainer{
   601  			ID:           id,
   602  			State:        NewState(),
   603  			execCommands: newExecStore(),
   604  			root:         daemon.containerRoot(id),
   605  		},
   606  		MountPoints: make(map[string]*mountPoint),
   607  		Volumes:     make(map[string]string),
   608  		VolumesRW:   make(map[string]bool),
   609  	}
   610  }
   611  
   612  // getDefaultRouteMtu returns the MTU for the default route's interface.
   613  func getDefaultRouteMtu() (int, error) {
   614  	routes, err := netlink.RouteList(nil, 0)
   615  	if err != nil {
   616  		return 0, err
   617  	}
   618  	for _, r := range routes {
   619  		// a nil Dst means that this is the default route.
   620  		if r.Dst == nil {
   621  			i, err := net.InterfaceByIndex(r.LinkIndex)
   622  			if err != nil {
   623  				continue
   624  			}
   625  			return i.MTU, nil
   626  		}
   627  	}
   628  	return 0, errNoDefaultRoute
   629  }