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