github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/daemon/execdriver/native/create.go (about) 1 // +build linux,cgo 2 3 package native 4 5 import ( 6 "errors" 7 "fmt" 8 "net" 9 "path/filepath" 10 "strings" 11 "syscall" 12 13 "github.com/docker/docker/daemon/execdriver" 14 "github.com/docker/docker/pkg/symlink" 15 "github.com/docker/libcontainer/apparmor" 16 "github.com/docker/libcontainer/configs" 17 "github.com/docker/libcontainer/devices" 18 "github.com/docker/libcontainer/utils" 19 ) 20 21 // createContainer populates and configures the container type with the 22 // data provided by the execdriver.Command 23 func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) { 24 container := execdriver.InitContainer(c) 25 26 if err := d.createIpc(container, c); err != nil { 27 return nil, err 28 } 29 30 if err := d.createPid(container, c); err != nil { 31 return nil, err 32 } 33 34 if err := d.createNetwork(container, c); err != nil { 35 return nil, err 36 } 37 38 if c.ProcessConfig.Privileged { 39 // clear readonly for /sys 40 for i := range container.Mounts { 41 if container.Mounts[i].Destination == "/sys" { 42 container.Mounts[i].Flags &= ^syscall.MS_RDONLY 43 } 44 } 45 container.ReadonlyPaths = nil 46 container.MaskPaths = nil 47 if err := d.setPrivileged(container); err != nil { 48 return nil, err 49 } 50 } else { 51 if err := d.setCapabilities(container, c); err != nil { 52 return nil, err 53 } 54 } 55 56 if c.AppArmorProfile != "" { 57 container.AppArmorProfile = c.AppArmorProfile 58 } 59 60 if err := execdriver.SetupCgroups(container, c); err != nil { 61 return nil, err 62 } 63 64 if err := d.setupMounts(container, c); err != nil { 65 return nil, err 66 } 67 68 if err := d.setupLabels(container, c); err != nil { 69 return nil, err 70 } 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 } 118 if c.Network.Interface.GlobalIPv6Address != "" { 119 vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen) 120 vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway 121 } 122 container.Networks = append(container.Networks, &vethNetwork) 123 } 124 125 if c.Network.ContainerID != "" { 126 d.Lock() 127 active := d.activeContainers[c.Network.ContainerID] 128 d.Unlock() 129 130 if active == nil { 131 return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID) 132 } 133 134 state, err := active.State() 135 if err != nil { 136 return err 137 } 138 139 container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET]) 140 } 141 142 return nil 143 } 144 145 func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error { 146 if c.Ipc.HostIpc { 147 container.Namespaces.Remove(configs.NEWIPC) 148 return nil 149 } 150 151 if c.Ipc.ContainerID != "" { 152 d.Lock() 153 active := d.activeContainers[c.Ipc.ContainerID] 154 d.Unlock() 155 156 if active == nil { 157 return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID) 158 } 159 160 state, err := active.State() 161 if err != nil { 162 return err 163 } 164 container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC]) 165 } 166 167 return nil 168 } 169 170 func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error { 171 if c.Pid.HostPid { 172 container.Namespaces.Remove(configs.NEWPID) 173 return nil 174 } 175 176 return nil 177 } 178 179 func (d *driver) setPrivileged(container *configs.Config) (err error) { 180 container.Capabilities = execdriver.GetAllCapabilities() 181 container.Cgroups.AllowAllDevices = true 182 183 hostDevices, err := devices.HostDevices() 184 if err != nil { 185 return err 186 } 187 container.Devices = hostDevices 188 189 if apparmor.IsEnabled() { 190 container.AppArmorProfile = "unconfined" 191 } 192 193 return nil 194 } 195 196 func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) { 197 container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop) 198 return err 199 } 200 201 func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) { 202 if c.Resources == nil { 203 return 204 } 205 206 for _, rlimit := range c.Resources.Rlimits { 207 container.Rlimits = append(container.Rlimits, configs.Rlimit{ 208 Type: rlimit.Type, 209 Hard: rlimit.Hard, 210 Soft: rlimit.Soft, 211 }) 212 } 213 } 214 215 func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error { 216 userMounts := make(map[string]struct{}) 217 for _, m := range c.Mounts { 218 userMounts[m.Destination] = struct{}{} 219 } 220 221 // Filter out mounts that are overriden by user supplied mounts 222 var defaultMounts []*configs.Mount 223 _, mountDev := userMounts["/dev"] 224 for _, m := range container.Mounts { 225 if _, ok := userMounts[m.Destination]; !ok { 226 if mountDev && strings.HasPrefix(m.Destination, "/dev/") { 227 continue 228 } 229 defaultMounts = append(defaultMounts, m) 230 } 231 } 232 container.Mounts = defaultMounts 233 234 for _, m := range c.Mounts { 235 dest, err := symlink.FollowSymlinkInScope(filepath.Join(c.Rootfs, m.Destination), c.Rootfs) 236 if err != nil { 237 return err 238 } 239 flags := syscall.MS_BIND | syscall.MS_REC 240 if !m.Writable { 241 flags |= syscall.MS_RDONLY 242 } 243 if m.Slave { 244 flags |= syscall.MS_SLAVE 245 } 246 247 container.Mounts = append(container.Mounts, &configs.Mount{ 248 Source: m.Source, 249 Destination: dest, 250 Device: "bind", 251 Flags: flags, 252 }) 253 } 254 return nil 255 } 256 257 func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) error { 258 container.ProcessLabel = c.ProcessLabel 259 container.MountLabel = c.MountLabel 260 261 return nil 262 }