github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/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.Remove(libcontainer.NEWNET)
    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.Namespaces.Add(libcontainer.NEWNET, nspath)
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func (d *driver) createIpc(container *libcontainer.Config, c *execdriver.Command) error {
   129  	if c.Ipc.HostIpc {
   130  		container.Namespaces.Remove(libcontainer.NEWIPC)
   131  		return nil
   132  	}
   133  
   134  	if c.Ipc.ContainerID != "" {
   135  		d.Lock()
   136  		active := d.activeContainers[c.Ipc.ContainerID]
   137  		d.Unlock()
   138  
   139  		if active == nil || active.cmd.Process == nil {
   140  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   141  		}
   142  		cmd := active.cmd
   143  
   144  		container.Namespaces.Add(libcontainer.NEWIPC, filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "ipc"))
   145  	}
   146  
   147  	return nil
   148  }
   149  
   150  func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
   151  	container.Capabilities = capabilities.GetAllCapabilities()
   152  	container.Cgroups.AllowAllDevices = true
   153  
   154  	hostDeviceNodes, err := devices.GetHostDeviceNodes()
   155  	if err != nil {
   156  		return err
   157  	}
   158  	container.MountConfig.DeviceNodes = hostDeviceNodes
   159  
   160  	container.RestrictSys = false
   161  
   162  	if apparmor.IsEnabled() {
   163  		container.AppArmorProfile = "unconfined"
   164  	}
   165  
   166  	return nil
   167  }
   168  
   169  func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) (err error) {
   170  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   171  	return err
   172  }
   173  
   174  func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {
   175  	if c.Resources != nil {
   176  		container.Cgroups.CpuShares = c.Resources.CpuShares
   177  		container.Cgroups.Memory = c.Resources.Memory
   178  		container.Cgroups.MemoryReservation = c.Resources.Memory
   179  		container.Cgroups.MemorySwap = c.Resources.MemorySwap
   180  		container.Cgroups.CpusetCpus = c.Resources.Cpuset
   181  	}
   182  
   183  	return nil
   184  }
   185  
   186  func (d *driver) setupMounts(container *libcontainer.Config, c *execdriver.Command) error {
   187  	for _, m := range c.Mounts {
   188  		container.MountConfig.Mounts = append(container.MountConfig.Mounts, &mount.Mount{
   189  			Type:        "bind",
   190  			Source:      m.Source,
   191  			Destination: m.Destination,
   192  			Writable:    m.Writable,
   193  			Private:     m.Private,
   194  			Slave:       m.Slave,
   195  		})
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  func (d *driver) setupLabels(container *libcontainer.Config, c *execdriver.Command) error {
   202  	container.ProcessLabel = c.ProcessLabel
   203  	container.MountConfig.MountLabel = c.MountLabel
   204  
   205  	return nil
   206  }