github.com/ralexstokes/docker@v1.6.2/daemon/execdriver/native/create.go (about) 1 // +build linux,cgo 2 3 package native 4 5 import ( 6 "errors" 7 "fmt" 8 "net" 9 "strings" 10 "syscall" 11 12 "github.com/docker/docker/daemon/execdriver" 13 "github.com/docker/libcontainer/apparmor" 14 "github.com/docker/libcontainer/configs" 15 "github.com/docker/libcontainer/devices" 16 "github.com/docker/libcontainer/utils" 17 ) 18 19 // createContainer populates and configures the container type with the 20 // data provided by the execdriver.Command 21 func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) { 22 container := execdriver.InitContainer(c) 23 24 if err := d.createIpc(container, c); err != nil { 25 return nil, err 26 } 27 28 if err := d.createPid(container, c); err != nil { 29 return nil, err 30 } 31 32 if err := d.createNetwork(container, c); err != nil { 33 return nil, err 34 } 35 36 if c.ProcessConfig.Privileged { 37 // clear readonly for /sys 38 for i := range container.Mounts { 39 if container.Mounts[i].Destination == "/sys" { 40 container.Mounts[i].Flags &= ^syscall.MS_RDONLY 41 } 42 } 43 container.ReadonlyPaths = nil 44 container.MaskPaths = nil 45 if err := d.setPrivileged(container); err != nil { 46 return nil, err 47 } 48 } else { 49 if err := d.setCapabilities(container, c); err != nil { 50 return nil, err 51 } 52 } 53 54 if c.AppArmorProfile != "" { 55 container.AppArmorProfile = c.AppArmorProfile 56 } 57 58 if err := execdriver.SetupCgroups(container, c); err != nil { 59 return nil, err 60 } 61 62 if err := d.setupMounts(container, c); err != nil { 63 return nil, err 64 } 65 66 if err := d.setupLabels(container, c); err != nil { 67 return nil, err 68 } 69 d.setupRlimits(container, c) 70 return container, nil 71 } 72 73 func generateIfaceName() (string, error) { 74 for i := 0; i < 10; i++ { 75 name, err := utils.GenerateRandomName("veth", 7) 76 if err != nil { 77 continue 78 } 79 if _, err := net.InterfaceByName(name); err != nil { 80 if strings.Contains(err.Error(), "no such") { 81 return name, nil 82 } 83 return "", err 84 } 85 } 86 return "", errors.New("Failed to find name for new interface") 87 } 88 89 func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error { 90 if c.Network.HostNetworking { 91 container.Namespaces.Remove(configs.NEWNET) 92 return nil 93 } 94 95 container.Networks = []*configs.Network{ 96 { 97 Type: "loopback", 98 }, 99 } 100 101 iName, err := generateIfaceName() 102 if err != nil { 103 return err 104 } 105 if c.Network.Interface != nil { 106 vethNetwork := configs.Network{ 107 Name: "eth0", 108 HostInterfaceName: iName, 109 Mtu: c.Network.Mtu, 110 Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen), 111 MacAddress: c.Network.Interface.MacAddress, 112 Gateway: c.Network.Interface.Gateway, 113 Type: "veth", 114 Bridge: c.Network.Interface.Bridge, 115 } 116 if c.Network.Interface.GlobalIPv6Address != "" { 117 vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen) 118 vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway 119 } 120 container.Networks = append(container.Networks, &vethNetwork) 121 } 122 123 if c.Network.ContainerID != "" { 124 d.Lock() 125 active := d.activeContainers[c.Network.ContainerID] 126 d.Unlock() 127 128 if active == nil { 129 return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID) 130 } 131 132 state, err := active.State() 133 if err != nil { 134 return err 135 } 136 137 container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET]) 138 } 139 140 return nil 141 } 142 143 func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error { 144 if c.Ipc.HostIpc { 145 container.Namespaces.Remove(configs.NEWIPC) 146 return nil 147 } 148 149 if c.Ipc.ContainerID != "" { 150 d.Lock() 151 active := d.activeContainers[c.Ipc.ContainerID] 152 d.Unlock() 153 154 if active == nil { 155 return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID) 156 } 157 158 state, err := active.State() 159 if err != nil { 160 return err 161 } 162 container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC]) 163 } 164 165 return nil 166 } 167 168 func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error { 169 if c.Pid.HostPid { 170 container.Namespaces.Remove(configs.NEWPID) 171 return nil 172 } 173 174 return nil 175 } 176 177 func (d *driver) setPrivileged(container *configs.Config) (err error) { 178 container.Capabilities = execdriver.GetAllCapabilities() 179 container.Cgroups.AllowAllDevices = true 180 181 hostDevices, err := devices.HostDevices() 182 if err != nil { 183 return err 184 } 185 container.Devices = hostDevices 186 187 if apparmor.IsEnabled() { 188 container.AppArmorProfile = "unconfined" 189 } 190 191 return nil 192 } 193 194 func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) { 195 container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop) 196 return err 197 } 198 199 func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) { 200 if c.Resources == nil { 201 return 202 } 203 204 for _, rlimit := range c.Resources.Rlimits { 205 container.Rlimits = append(container.Rlimits, configs.Rlimit{ 206 Type: rlimit.Type, 207 Hard: rlimit.Hard, 208 Soft: rlimit.Soft, 209 }) 210 } 211 } 212 213 func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error { 214 userMounts := make(map[string]struct{}) 215 for _, m := range c.Mounts { 216 userMounts[m.Destination] = struct{}{} 217 } 218 219 // Filter out mounts that are overriden by user supplied mounts 220 var defaultMounts []*configs.Mount 221 for _, m := range container.Mounts { 222 if _, ok := userMounts[m.Destination]; !ok { 223 defaultMounts = append(defaultMounts, m) 224 } 225 } 226 container.Mounts = defaultMounts 227 228 for _, m := range c.Mounts { 229 flags := syscall.MS_BIND | syscall.MS_REC 230 if !m.Writable { 231 flags |= syscall.MS_RDONLY 232 } 233 if m.Slave { 234 flags |= syscall.MS_SLAVE 235 } 236 container.Mounts = append(container.Mounts, &configs.Mount{ 237 Source: m.Source, 238 Destination: m.Destination, 239 Device: "bind", 240 Flags: flags, 241 }) 242 } 243 return nil 244 } 245 246 func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) error { 247 container.ProcessLabel = c.ProcessLabel 248 container.MountLabel = c.MountLabel 249 250 return nil 251 }