github.com/sbward/docker@v1.4.2-0.20150114010528-c9dab702bed3/daemon/execdriver/native/create.go (about)

     1  // +build linux,cgo
     2  
     3  package native
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  
    11  	"github.com/docker/docker/daemon/execdriver"
    12  	"github.com/docker/docker/daemon/execdriver/native/template"
    13  	"github.com/docker/libcontainer"
    14  	"github.com/docker/libcontainer/apparmor"
    15  	"github.com/docker/libcontainer/devices"
    16  	"github.com/docker/libcontainer/mount"
    17  	"github.com/docker/libcontainer/security/capabilities"
    18  )
    19  
    20  // createContainer populates and configures the container type with the
    21  // data provided by the execdriver.Command
    22  func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, error) {
    23  	container := template.New()
    24  
    25  	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
    26  	container.Tty = c.ProcessConfig.Tty
    27  	container.User = c.ProcessConfig.User
    28  	container.WorkingDir = c.WorkingDir
    29  	container.Env = c.ProcessConfig.Env
    30  	container.Cgroups.Name = c.ID
    31  	container.Cgroups.AllowedDevices = c.AllowedDevices
    32  	container.MountConfig.DeviceNodes = c.AutoCreatedDevices
    33  	container.RootFs = c.Rootfs
    34  
    35  	// check to see if we are running in ramdisk to disable pivot root
    36  	container.MountConfig.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
    37  	container.RestrictSys = true
    38  
    39  	if err := d.createIpc(container, c); err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	if err := d.createPid(container, c); err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	if err := d.createNetwork(container, c); err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	if c.ProcessConfig.Privileged {
    52  		if err := d.setPrivileged(container); err != nil {
    53  			return nil, err
    54  		}
    55  	} else {
    56  		if err := d.setCapabilities(container, c); err != nil {
    57  			return nil, err
    58  		}
    59  	}
    60  
    61  	if c.AppArmorProfile != "" {
    62  		container.AppArmorProfile = c.AppArmorProfile
    63  	}
    64  
    65  	if err := d.setupCgroups(container, c); err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	if err := d.setupMounts(container, c); err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	if err := d.setupLabels(container, c); err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	cmds := make(map[string]*exec.Cmd)
    78  	d.Lock()
    79  	for k, v := range d.activeContainers {
    80  		cmds[k] = v.cmd
    81  	}
    82  	d.Unlock()
    83  
    84  	return container, nil
    85  }
    86  
    87  func (d *driver) createNetwork(container *libcontainer.Config, c *execdriver.Command) error {
    88  	if c.Network.HostNetworking {
    89  		container.Namespaces.Remove(libcontainer.NEWNET)
    90  		return nil
    91  	}
    92  
    93  	container.Networks = []*libcontainer.Network{
    94  		{
    95  			Mtu:     c.Network.Mtu,
    96  			Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
    97  			Gateway: "localhost",
    98  			Type:    "loopback",
    99  		},
   100  	}
   101  
   102  	if c.Network.Interface != nil {
   103  		vethNetwork := libcontainer.Network{
   104  			Mtu:        c.Network.Mtu,
   105  			Address:    fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
   106  			MacAddress: c.Network.Interface.MacAddress,
   107  			Gateway:    c.Network.Interface.Gateway,
   108  			Type:       "veth",
   109  			Bridge:     c.Network.Interface.Bridge,
   110  			VethPrefix: "veth",
   111  		}
   112  		if c.Network.Interface.GlobalIPv6Address != "" {
   113  			vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
   114  			vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
   115  		}
   116  		container.Networks = append(container.Networks, &vethNetwork)
   117  	}
   118  
   119  	if c.Network.ContainerID != "" {
   120  		d.Lock()
   121  		active := d.activeContainers[c.Network.ContainerID]
   122  		d.Unlock()
   123  
   124  		if active == nil || active.cmd.Process == nil {
   125  			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
   126  		}
   127  		cmd := active.cmd
   128  
   129  		nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
   130  		container.Namespaces.Add(libcontainer.NEWNET, nspath)
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  func (d *driver) createIpc(container *libcontainer.Config, c *execdriver.Command) error {
   137  	if c.Ipc.HostIpc {
   138  		container.Namespaces.Remove(libcontainer.NEWIPC)
   139  		return nil
   140  	}
   141  
   142  	if c.Ipc.ContainerID != "" {
   143  		d.Lock()
   144  		active := d.activeContainers[c.Ipc.ContainerID]
   145  		d.Unlock()
   146  
   147  		if active == nil || active.cmd.Process == nil {
   148  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   149  		}
   150  		cmd := active.cmd
   151  
   152  		container.Namespaces.Add(libcontainer.NEWIPC, filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "ipc"))
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  func (d *driver) createPid(container *libcontainer.Config, c *execdriver.Command) error {
   159  	if c.Pid.HostPid {
   160  		container.Namespaces.Remove(libcontainer.NEWPID)
   161  		return nil
   162  	}
   163  
   164  	return nil
   165  }
   166  
   167  func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
   168  	container.Capabilities = capabilities.GetAllCapabilities()
   169  	container.Cgroups.AllowAllDevices = true
   170  
   171  	hostDeviceNodes, err := devices.GetHostDeviceNodes()
   172  	if err != nil {
   173  		return err
   174  	}
   175  	container.MountConfig.DeviceNodes = hostDeviceNodes
   176  
   177  	container.RestrictSys = false
   178  
   179  	if apparmor.IsEnabled() {
   180  		container.AppArmorProfile = "unconfined"
   181  	}
   182  
   183  	return nil
   184  }
   185  
   186  func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) (err error) {
   187  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   188  	return err
   189  }
   190  
   191  func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {
   192  	if c.Resources != nil {
   193  		container.Cgroups.CpuShares = c.Resources.CpuShares
   194  		container.Cgroups.Memory = c.Resources.Memory
   195  		container.Cgroups.MemoryReservation = c.Resources.Memory
   196  		container.Cgroups.MemorySwap = c.Resources.MemorySwap
   197  		container.Cgroups.CpusetCpus = c.Resources.Cpuset
   198  	}
   199  
   200  	return nil
   201  }
   202  
   203  func (d *driver) setupMounts(container *libcontainer.Config, c *execdriver.Command) error {
   204  	for _, m := range c.Mounts {
   205  		container.MountConfig.Mounts = append(container.MountConfig.Mounts, &mount.Mount{
   206  			Type:        "bind",
   207  			Source:      m.Source,
   208  			Destination: m.Destination,
   209  			Writable:    m.Writable,
   210  			Private:     m.Private,
   211  			Slave:       m.Slave,
   212  		})
   213  	}
   214  
   215  	return nil
   216  }
   217  
   218  func (d *driver) setupLabels(container *libcontainer.Config, c *execdriver.Command) error {
   219  	container.ProcessLabel = c.ProcessLabel
   220  	container.MountConfig.MountLabel = c.MountLabel
   221  
   222  	return nil
   223  }