github.com/dougm/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 }