github.com/ld86/docker@v1.7.1-rc3/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 == nil { 93 return nil 94 } 95 if c.Network.ContainerID != "" { 96 d.Lock() 97 active := d.activeContainers[c.Network.ContainerID] 98 d.Unlock() 99 100 if active == nil { 101 return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID) 102 } 103 104 state, err := active.State() 105 if err != nil { 106 return err 107 } 108 109 container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET]) 110 return nil 111 } 112 113 if c.Network.NamespacePath == "" { 114 return fmt.Errorf("network namespace path is empty") 115 } 116 117 container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath) 118 return nil 119 } 120 121 func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error { 122 if c.Ipc.HostIpc { 123 container.Namespaces.Remove(configs.NEWIPC) 124 return nil 125 } 126 127 if c.Ipc.ContainerID != "" { 128 d.Lock() 129 active := d.activeContainers[c.Ipc.ContainerID] 130 d.Unlock() 131 132 if active == nil { 133 return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID) 134 } 135 136 state, err := active.State() 137 if err != nil { 138 return err 139 } 140 container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC]) 141 } 142 143 return nil 144 } 145 146 func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error { 147 if c.Pid.HostPid { 148 container.Namespaces.Remove(configs.NEWPID) 149 return nil 150 } 151 152 return nil 153 } 154 155 func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error { 156 if c.UTS.HostUTS { 157 container.Namespaces.Remove(configs.NEWUTS) 158 container.Hostname = "" 159 return nil 160 } 161 162 return nil 163 } 164 165 func (d *driver) setPrivileged(container *configs.Config) (err error) { 166 container.Capabilities = execdriver.GetAllCapabilities() 167 container.Cgroups.AllowAllDevices = true 168 169 hostDevices, err := devices.HostDevices() 170 if err != nil { 171 return err 172 } 173 container.Devices = hostDevices 174 175 if apparmor.IsEnabled() { 176 container.AppArmorProfile = "unconfined" 177 } 178 179 return nil 180 } 181 182 func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) { 183 container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop) 184 return err 185 } 186 187 func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) { 188 if c.Resources == nil { 189 return 190 } 191 192 for _, rlimit := range c.Resources.Rlimits { 193 container.Rlimits = append(container.Rlimits, configs.Rlimit{ 194 Type: rlimit.Type, 195 Hard: rlimit.Hard, 196 Soft: rlimit.Soft, 197 }) 198 } 199 } 200 201 func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error { 202 userMounts := make(map[string]struct{}) 203 for _, m := range c.Mounts { 204 userMounts[m.Destination] = struct{}{} 205 } 206 207 // Filter out mounts that are overriden by user supplied mounts 208 var defaultMounts []*configs.Mount 209 _, mountDev := userMounts["/dev"] 210 for _, m := range container.Mounts { 211 if _, ok := userMounts[m.Destination]; !ok { 212 if mountDev && strings.HasPrefix(m.Destination, "/dev/") { 213 continue 214 } 215 defaultMounts = append(defaultMounts, m) 216 } 217 } 218 container.Mounts = defaultMounts 219 220 for _, m := range c.Mounts { 221 flags := syscall.MS_BIND | syscall.MS_REC 222 if !m.Writable { 223 flags |= syscall.MS_RDONLY 224 } 225 if m.Slave { 226 flags |= syscall.MS_SLAVE 227 } 228 container.Mounts = append(container.Mounts, &configs.Mount{ 229 Source: m.Source, 230 Destination: m.Destination, 231 Device: "bind", 232 Flags: flags, 233 }) 234 } 235 return nil 236 } 237 238 func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) { 239 container.ProcessLabel = c.ProcessLabel 240 container.MountLabel = c.MountLabel 241 }