github.com/ralexstokes/docker@v1.6.2/daemon/execdriver/native/create.go (about)

     1  // +build linux,cgo
     2  
     3  package native
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"net"
     9  	"strings"
    10  	"syscall"
    11  
    12  	"github.com/docker/docker/daemon/execdriver"
    13  	"github.com/docker/libcontainer/apparmor"
    14  	"github.com/docker/libcontainer/configs"
    15  	"github.com/docker/libcontainer/devices"
    16  	"github.com/docker/libcontainer/utils"
    17  )
    18  
    19  // createContainer populates and configures the container type with the
    20  // data provided by the execdriver.Command
    21  func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
    22  	container := execdriver.InitContainer(c)
    23  
    24  	if err := d.createIpc(container, c); err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	if err := d.createPid(container, c); err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	if err := d.createNetwork(container, c); err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	if c.ProcessConfig.Privileged {
    37  		// clear readonly for /sys
    38  		for i := range container.Mounts {
    39  			if container.Mounts[i].Destination == "/sys" {
    40  				container.Mounts[i].Flags &= ^syscall.MS_RDONLY
    41  			}
    42  		}
    43  		container.ReadonlyPaths = nil
    44  		container.MaskPaths = nil
    45  		if err := d.setPrivileged(container); err != nil {
    46  			return nil, err
    47  		}
    48  	} else {
    49  		if err := d.setCapabilities(container, c); err != nil {
    50  			return nil, err
    51  		}
    52  	}
    53  
    54  	if c.AppArmorProfile != "" {
    55  		container.AppArmorProfile = c.AppArmorProfile
    56  	}
    57  
    58  	if err := execdriver.SetupCgroups(container, c); err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	if err := d.setupMounts(container, c); err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	if err := d.setupLabels(container, c); err != nil {
    67  		return nil, err
    68  	}
    69  	d.setupRlimits(container, c)
    70  	return container, nil
    71  }
    72  
    73  func generateIfaceName() (string, error) {
    74  	for i := 0; i < 10; i++ {
    75  		name, err := utils.GenerateRandomName("veth", 7)
    76  		if err != nil {
    77  			continue
    78  		}
    79  		if _, err := net.InterfaceByName(name); err != nil {
    80  			if strings.Contains(err.Error(), "no such") {
    81  				return name, nil
    82  			}
    83  			return "", err
    84  		}
    85  	}
    86  	return "", errors.New("Failed to find name for new interface")
    87  }
    88  
    89  func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
    90  	if c.Network.HostNetworking {
    91  		container.Namespaces.Remove(configs.NEWNET)
    92  		return nil
    93  	}
    94  
    95  	container.Networks = []*configs.Network{
    96  		{
    97  			Type: "loopback",
    98  		},
    99  	}
   100  
   101  	iName, err := generateIfaceName()
   102  	if err != nil {
   103  		return err
   104  	}
   105  	if c.Network.Interface != nil {
   106  		vethNetwork := configs.Network{
   107  			Name:              "eth0",
   108  			HostInterfaceName: iName,
   109  			Mtu:               c.Network.Mtu,
   110  			Address:           fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
   111  			MacAddress:        c.Network.Interface.MacAddress,
   112  			Gateway:           c.Network.Interface.Gateway,
   113  			Type:              "veth",
   114  			Bridge:            c.Network.Interface.Bridge,
   115  		}
   116  		if c.Network.Interface.GlobalIPv6Address != "" {
   117  			vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
   118  			vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
   119  		}
   120  		container.Networks = append(container.Networks, &vethNetwork)
   121  	}
   122  
   123  	if c.Network.ContainerID != "" {
   124  		d.Lock()
   125  		active := d.activeContainers[c.Network.ContainerID]
   126  		d.Unlock()
   127  
   128  		if active == nil {
   129  			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
   130  		}
   131  
   132  		state, err := active.State()
   133  		if err != nil {
   134  			return err
   135  		}
   136  
   137  		container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
   144  	if c.Ipc.HostIpc {
   145  		container.Namespaces.Remove(configs.NEWIPC)
   146  		return nil
   147  	}
   148  
   149  	if c.Ipc.ContainerID != "" {
   150  		d.Lock()
   151  		active := d.activeContainers[c.Ipc.ContainerID]
   152  		d.Unlock()
   153  
   154  		if active == nil {
   155  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   156  		}
   157  
   158  		state, err := active.State()
   159  		if err != nil {
   160  			return err
   161  		}
   162  		container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
   163  	}
   164  
   165  	return nil
   166  }
   167  
   168  func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
   169  	if c.Pid.HostPid {
   170  		container.Namespaces.Remove(configs.NEWPID)
   171  		return nil
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func (d *driver) setPrivileged(container *configs.Config) (err error) {
   178  	container.Capabilities = execdriver.GetAllCapabilities()
   179  	container.Cgroups.AllowAllDevices = true
   180  
   181  	hostDevices, err := devices.HostDevices()
   182  	if err != nil {
   183  		return err
   184  	}
   185  	container.Devices = hostDevices
   186  
   187  	if apparmor.IsEnabled() {
   188  		container.AppArmorProfile = "unconfined"
   189  	}
   190  
   191  	return nil
   192  }
   193  
   194  func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
   195  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   196  	return err
   197  }
   198  
   199  func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
   200  	if c.Resources == nil {
   201  		return
   202  	}
   203  
   204  	for _, rlimit := range c.Resources.Rlimits {
   205  		container.Rlimits = append(container.Rlimits, configs.Rlimit{
   206  			Type: rlimit.Type,
   207  			Hard: rlimit.Hard,
   208  			Soft: rlimit.Soft,
   209  		})
   210  	}
   211  }
   212  
   213  func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
   214  	userMounts := make(map[string]struct{})
   215  	for _, m := range c.Mounts {
   216  		userMounts[m.Destination] = struct{}{}
   217  	}
   218  
   219  	// Filter out mounts that are overriden by user supplied mounts
   220  	var defaultMounts []*configs.Mount
   221  	for _, m := range container.Mounts {
   222  		if _, ok := userMounts[m.Destination]; !ok {
   223  			defaultMounts = append(defaultMounts, m)
   224  		}
   225  	}
   226  	container.Mounts = defaultMounts
   227  
   228  	for _, m := range c.Mounts {
   229  		flags := syscall.MS_BIND | syscall.MS_REC
   230  		if !m.Writable {
   231  			flags |= syscall.MS_RDONLY
   232  		}
   233  		if m.Slave {
   234  			flags |= syscall.MS_SLAVE
   235  		}
   236  		container.Mounts = append(container.Mounts, &configs.Mount{
   237  			Source:      m.Source,
   238  			Destination: m.Destination,
   239  			Device:      "bind",
   240  			Flags:       flags,
   241  		})
   242  	}
   243  	return nil
   244  }
   245  
   246  func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) error {
   247  	container.ProcessLabel = c.ProcessLabel
   248  	container.MountLabel = c.MountLabel
   249  
   250  	return nil
   251  }