github.com/titanous/docker@v1.4.1/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.createNetwork(container, c); err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	if c.ProcessConfig.Privileged {
    48  		if err := d.setPrivileged(container); err != nil {
    49  			return nil, err
    50  		}
    51  	} else {
    52  		if err := d.setCapabilities(container, c); err != nil {
    53  			return nil, err
    54  		}
    55  	}
    56  
    57  	if c.AppArmorProfile != "" {
    58  		container.AppArmorProfile = c.AppArmorProfile
    59  	}
    60  
    61  	if err := d.setupCgroups(container, c); err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	if err := d.setupMounts(container, c); err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	if err := d.setupLabels(container, c); err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	cmds := make(map[string]*exec.Cmd)
    74  	d.Lock()
    75  	for k, v := range d.activeContainers {
    76  		cmds[k] = v.cmd
    77  	}
    78  	d.Unlock()
    79  
    80  	return container, nil
    81  }
    82  
    83  func (d *driver) createNetwork(container *libcontainer.Config, c *execdriver.Command) error {
    84  	if c.Network.HostNetworking {
    85  		container.Namespaces["NEWNET"] = false
    86  		return nil
    87  	}
    88  
    89  	container.Networks = []*libcontainer.Network{
    90  		{
    91  			Mtu:     c.Network.Mtu,
    92  			Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
    93  			Gateway: "localhost",
    94  			Type:    "loopback",
    95  		},
    96  	}
    97  
    98  	if c.Network.Interface != nil {
    99  		vethNetwork := libcontainer.Network{
   100  			Mtu:        c.Network.Mtu,
   101  			Address:    fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
   102  			MacAddress: c.Network.Interface.MacAddress,
   103  			Gateway:    c.Network.Interface.Gateway,
   104  			Type:       "veth",
   105  			Bridge:     c.Network.Interface.Bridge,
   106  			VethPrefix: "veth",
   107  		}
   108  		container.Networks = append(container.Networks, &vethNetwork)
   109  	}
   110  
   111  	if c.Network.ContainerID != "" {
   112  		d.Lock()
   113  		active := d.activeContainers[c.Network.ContainerID]
   114  		d.Unlock()
   115  
   116  		if active == nil || active.cmd.Process == nil {
   117  			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
   118  		}
   119  		cmd := active.cmd
   120  
   121  		nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
   122  		container.Networks = append(container.Networks, &libcontainer.Network{
   123  			Type:   "netns",
   124  			NsPath: nspath,
   125  		})
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func (d *driver) createIpc(container *libcontainer.Config, c *execdriver.Command) error {
   132  	if c.Ipc.HostIpc {
   133  		container.Namespaces["NEWIPC"] = false
   134  		return nil
   135  	}
   136  
   137  	if c.Ipc.ContainerID != "" {
   138  		d.Lock()
   139  		active := d.activeContainers[c.Ipc.ContainerID]
   140  		d.Unlock()
   141  
   142  		if active == nil || active.cmd.Process == nil {
   143  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   144  		}
   145  		cmd := active.cmd
   146  
   147  		container.IpcNsPath = filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "ipc")
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
   154  	container.Capabilities = capabilities.GetAllCapabilities()
   155  	container.Cgroups.AllowAllDevices = true
   156  
   157  	hostDeviceNodes, err := devices.GetHostDeviceNodes()
   158  	if err != nil {
   159  		return err
   160  	}
   161  	container.MountConfig.DeviceNodes = hostDeviceNodes
   162  
   163  	container.RestrictSys = false
   164  
   165  	if apparmor.IsEnabled() {
   166  		container.AppArmorProfile = "unconfined"
   167  	}
   168  
   169  	return nil
   170  }
   171  
   172  func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) (err error) {
   173  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   174  	return err
   175  }
   176  
   177  func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {
   178  	if c.Resources != nil {
   179  		container.Cgroups.CpuShares = c.Resources.CpuShares
   180  		container.Cgroups.Memory = c.Resources.Memory
   181  		container.Cgroups.MemoryReservation = c.Resources.Memory
   182  		container.Cgroups.MemorySwap = c.Resources.MemorySwap
   183  		container.Cgroups.CpusetCpus = c.Resources.Cpuset
   184  	}
   185  
   186  	return nil
   187  }
   188  
   189  func (d *driver) setupMounts(container *libcontainer.Config, c *execdriver.Command) error {
   190  	for _, m := range c.Mounts {
   191  		container.MountConfig.Mounts = append(container.MountConfig.Mounts, &mount.Mount{
   192  			Type:        "bind",
   193  			Source:      m.Source,
   194  			Destination: m.Destination,
   195  			Writable:    m.Writable,
   196  			Private:     m.Private,
   197  			Slave:       m.Slave,
   198  		})
   199  	}
   200  
   201  	return nil
   202  }
   203  
   204  func (d *driver) setupLabels(container *libcontainer.Config, c *execdriver.Command) error {
   205  	container.ProcessLabel = c.ProcessLabel
   206  	container.MountConfig.MountLabel = c.MountLabel
   207  
   208  	return nil
   209  }