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