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