github.com/dougm/docker@v1.5.0/daemon/execdriver/lxc/lxc_template.go (about) 1 package lxc 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 "text/template" 8 9 log "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/daemon/execdriver" 11 nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" 12 "github.com/docker/docker/utils" 13 "github.com/docker/libcontainer/label" 14 "github.com/docker/libcontainer/security/capabilities" 15 ) 16 17 const LxcTemplate = ` 18 {{if .Network.Interface}} 19 # network configuration 20 lxc.network.type = veth 21 lxc.network.link = {{.Network.Interface.Bridge}} 22 lxc.network.name = eth0 23 lxc.network.mtu = {{.Network.Mtu}} 24 lxc.network.flags = up 25 {{else if .Network.HostNetworking}} 26 lxc.network.type = none 27 {{else}} 28 # network is disabled (-n=false) 29 lxc.network.type = empty 30 lxc.network.flags = up 31 lxc.network.mtu = {{.Network.Mtu}} 32 {{end}} 33 34 # root filesystem 35 {{$ROOTFS := .Rootfs}} 36 lxc.rootfs = {{$ROOTFS}} 37 38 # use a dedicated pts for the container (and limit the number of pseudo terminal 39 # available) 40 lxc.pts = 1024 41 42 # disable the main console 43 lxc.console = none 44 45 # no controlling tty at all 46 lxc.tty = 1 47 48 {{if .ProcessConfig.Privileged}} 49 lxc.cgroup.devices.allow = a 50 {{else}} 51 # no implicit access to devices 52 lxc.cgroup.devices.deny = a 53 #Allow the devices passed to us in the AllowedDevices list. 54 {{range $allowedDevice := .AllowedDevices}} 55 lxc.cgroup.devices.allow = {{$allowedDevice.GetCgroupAllowString}} 56 {{end}} 57 {{end}} 58 59 # standard mount point 60 # Use mnt.putold as per https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/986385 61 lxc.pivotdir = lxc_putold 62 63 # NOTICE: These mounts must be applied within the namespace 64 {{if .ProcessConfig.Privileged}} 65 # WARNING: mounting procfs and/or sysfs read-write is a known attack vector. 66 # See e.g. http://blog.zx2c4.com/749 and http://bit.ly/T9CkqJ 67 # We mount them read-write here, but later, dockerinit will call the Restrict() function to remount them read-only. 68 # We cannot mount them directly read-only, because that would prevent loading AppArmor profiles. 69 lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0 70 lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0 71 {{if .AppArmor}} 72 lxc.aa_profile = unconfined 73 {{end}} 74 {{else}} 75 # In non-privileged mode, lxc will automatically mount /proc and /sys in readonly mode 76 # for security. See: http://man7.org/linux/man-pages/man5/lxc.container.conf.5.html 77 lxc.mount.auto = proc sys 78 {{if .AppArmorProfile}} 79 lxc.aa_profile = {{.AppArmorProfile}} 80 {{end}} 81 {{end}} 82 83 {{if .ProcessConfig.Tty}} 84 lxc.mount.entry = {{.ProcessConfig.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw 0 0 85 {{end}} 86 87 lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMountLabel "newinstance,ptmxmode=0666,nosuid,noexec" ""}} 0 0 88 lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec" ""}} 0 0 89 90 {{range $value := .Mounts}} 91 {{$createVal := isDirectory $value.Source}} 92 {{if $value.Writable}} 93 lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw,create={{$createVal}} 0 0 94 {{else}} 95 lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro,create={{$createVal}} 0 0 96 {{end}} 97 {{end}} 98 99 # limits 100 {{if .Resources}} 101 {{if .Resources.Memory}} 102 lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}} 103 lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}} 104 {{with $memSwap := getMemorySwap .Resources}} 105 lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}} 106 {{end}} 107 {{end}} 108 {{if .Resources.CpuShares}} 109 lxc.cgroup.cpu.shares = {{.Resources.CpuShares}} 110 {{end}} 111 {{if .Resources.Cpuset}} 112 lxc.cgroup.cpuset.cpus = {{.Resources.Cpuset}} 113 {{end}} 114 {{end}} 115 116 {{if .LxcConfig}} 117 {{range $value := .LxcConfig}} 118 lxc.{{$value}} 119 {{end}} 120 {{end}} 121 122 {{if .Network.Interface}} 123 {{if .Network.Interface.IPAddress}} 124 lxc.network.ipv4 = {{.Network.Interface.IPAddress}}/{{.Network.Interface.IPPrefixLen}} 125 {{end}} 126 {{if .Network.Interface.Gateway}} 127 lxc.network.ipv4.gateway = {{.Network.Interface.Gateway}} 128 {{end}} 129 130 {{if .ProcessConfig.Env}} 131 lxc.utsname = {{getHostname .ProcessConfig.Env}} 132 {{end}} 133 134 {{if .ProcessConfig.Privileged}} 135 # No cap values are needed, as lxc is starting in privileged mode 136 {{else}} 137 {{ with keepCapabilities .CapAdd .CapDrop }} 138 {{range .}} 139 lxc.cap.keep = {{.}} 140 {{end}} 141 {{else}} 142 {{ with dropList .CapDrop }} 143 {{range .}} 144 lxc.cap.drop = {{.}} 145 {{end}} 146 {{end}} 147 {{end}} 148 {{end}} 149 {{end}} 150 ` 151 152 var LxcTemplateCompiled *template.Template 153 154 // Escape spaces in strings according to the fstab documentation, which is the 155 // format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". 156 func escapeFstabSpaces(field string) string { 157 return strings.Replace(field, " ", "\\040", -1) 158 } 159 160 func keepCapabilities(adds []string, drops []string) ([]string, error) { 161 container := nativeTemplate.New() 162 log.Debugf("adds %s drops %s\n", adds, drops) 163 caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) 164 if err != nil { 165 return nil, err 166 } 167 var newCaps []string 168 for _, cap := range caps { 169 log.Debugf("cap %s\n", cap) 170 realCap := capabilities.GetCapability(cap) 171 numCap := fmt.Sprintf("%d", realCap.Value) 172 newCaps = append(newCaps, numCap) 173 } 174 175 return newCaps, nil 176 } 177 178 func dropList(drops []string) ([]string, error) { 179 if utils.StringsContainsNoCase(drops, "all") { 180 var newCaps []string 181 for _, cap := range capabilities.GetAllCapabilities() { 182 log.Debugf("drop cap %s\n", cap) 183 realCap := capabilities.GetCapability(cap) 184 if realCap == nil { 185 return nil, fmt.Errorf("Invalid capability '%s'", cap) 186 } 187 numCap := fmt.Sprintf("%d", realCap.Value) 188 newCaps = append(newCaps, numCap) 189 } 190 return newCaps, nil 191 } 192 return []string{}, nil 193 } 194 195 func isDirectory(source string) string { 196 f, err := os.Stat(source) 197 if err != nil { 198 if os.IsNotExist(err) { 199 return "dir" 200 } 201 return "" 202 } 203 if f.IsDir() { 204 return "dir" 205 } 206 return "file" 207 } 208 209 func getMemorySwap(v *execdriver.Resources) int64 { 210 // By default, MemorySwap is set to twice the size of RAM. 211 // If you want to omit MemorySwap, set it to `-1'. 212 if v.MemorySwap < 0 { 213 return 0 214 } 215 return v.Memory * 2 216 } 217 218 func getLabel(c map[string][]string, name string) string { 219 label := c["label"] 220 for _, l := range label { 221 parts := strings.SplitN(l, "=", 2) 222 if strings.TrimSpace(parts[0]) == name { 223 return strings.TrimSpace(parts[1]) 224 } 225 } 226 return "" 227 } 228 229 func getHostname(env []string) string { 230 for _, kv := range env { 231 parts := strings.SplitN(kv, "=", 2) 232 if parts[0] == "HOSTNAME" && len(parts) == 2 { 233 return parts[1] 234 } 235 } 236 return "" 237 } 238 239 func init() { 240 var err error 241 funcMap := template.FuncMap{ 242 "getMemorySwap": getMemorySwap, 243 "escapeFstabSpaces": escapeFstabSpaces, 244 "formatMountLabel": label.FormatMountLabel, 245 "isDirectory": isDirectory, 246 "keepCapabilities": keepCapabilities, 247 "dropList": dropList, 248 "getHostname": getHostname, 249 } 250 LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) 251 if err != nil { 252 panic(err) 253 } 254 }