github.com/clintkitson/docker@v1.9.1/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 {{end}} 95 {{if gt .Resources.MemorySwap 0}} 96 lxc.cgroup.memory.memsw.limit_in_bytes = {{.Resources.MemorySwap}} 97 {{end}} 98 {{if gt .Resources.MemoryReservation 0}} 99 lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}} 100 {{end}} 101 {{if gt .Resources.KernelMemory 0}} 102 lxc.cgroup.memory.kmem.limit_in_bytes = {{.Resources.KernelMemory}} 103 {{end}} 104 {{if .Resources.CPUShares}} 105 lxc.cgroup.cpu.shares = {{.Resources.CPUShares}} 106 {{end}} 107 {{if .Resources.CPUPeriod}} 108 lxc.cgroup.cpu.cfs_period_us = {{.Resources.CPUPeriod}} 109 {{end}} 110 {{if .Resources.CpusetCpus}} 111 lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}} 112 {{end}} 113 {{if .Resources.CpusetMems}} 114 lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}} 115 {{end}} 116 {{if .Resources.CPUQuota}} 117 lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CPUQuota}} 118 {{end}} 119 {{if .Resources.BlkioWeight}} 120 lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}} 121 {{end}} 122 {{if .Resources.OomKillDisable}} 123 lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}} 124 {{end}} 125 {{if gt .Resources.MemorySwappiness 0}} 126 lxc.cgroup.memory.swappiness = {{.Resources.MemorySwappiness}} 127 {{end}} 128 {{end}} 129 130 {{if .LxcConfig}} 131 {{range $value := .LxcConfig}} 132 lxc.{{$value}} 133 {{end}} 134 {{end}} 135 136 {{if .ProcessConfig.Env}} 137 lxc.utsname = {{getHostname .ProcessConfig.Env}} 138 {{end}} 139 140 {{if .ProcessConfig.Privileged}} 141 # No cap values are needed, as lxc is starting in privileged mode 142 {{else}} 143 {{ with keepCapabilities .CapAdd .CapDrop }} 144 {{range .}} 145 lxc.cap.keep = {{.}} 146 {{end}} 147 {{else}} 148 {{ with dropList .CapDrop }} 149 {{range .}} 150 lxc.cap.drop = {{.}} 151 {{end}} 152 {{end}} 153 {{end}} 154 {{end}} 155 ` 156 157 var lxcTemplateCompiled *template.Template 158 159 // Escape spaces in strings according to the fstab documentation, which is the 160 // format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". 161 func escapeFstabSpaces(field string) string { 162 return strings.Replace(field, " ", "\\040", -1) 163 } 164 165 func keepCapabilities(adds []string, drops []string) ([]string, error) { 166 container := nativeTemplate.New() 167 logrus.Debugf("adds %s drops %s\n", adds, drops) 168 caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) 169 if err != nil { 170 return nil, err 171 } 172 var newCaps []string 173 for _, cap := range caps { 174 logrus.Debugf("cap %s\n", cap) 175 realCap := execdriver.GetCapability(cap) 176 numCap := fmt.Sprintf("%d", realCap.Value) 177 newCaps = append(newCaps, numCap) 178 } 179 180 return newCaps, nil 181 } 182 183 func dropList(drops []string) ([]string, error) { 184 if stringutils.InSlice(drops, "all") { 185 var newCaps []string 186 for _, capName := range execdriver.GetAllCapabilities() { 187 cap := execdriver.GetCapability(capName) 188 logrus.Debugf("drop cap %s\n", cap.Key) 189 numCap := fmt.Sprintf("%d", cap.Value) 190 newCaps = append(newCaps, numCap) 191 } 192 return newCaps, nil 193 } 194 return []string{}, nil 195 } 196 197 func isDirectory(source string) string { 198 f, err := os.Stat(source) 199 logrus.Debugf("dir: %s\n", source) 200 if err != nil { 201 if os.IsNotExist(err) { 202 return "dir" 203 } 204 return "" 205 } 206 if f.IsDir() { 207 return "dir" 208 } 209 return "file" 210 } 211 212 func getLabel(c map[string][]string, name string) string { 213 label := c["label"] 214 for _, l := range label { 215 parts := strings.SplitN(l, "=", 2) 216 if strings.TrimSpace(parts[0]) == name { 217 return strings.TrimSpace(parts[1]) 218 } 219 } 220 return "" 221 } 222 223 func getHostname(env []string) string { 224 for _, kv := range env { 225 parts := strings.SplitN(kv, "=", 2) 226 if parts[0] == "HOSTNAME" && len(parts) == 2 { 227 return parts[1] 228 } 229 } 230 return "" 231 } 232 233 func init() { 234 var err error 235 funcMap := template.FuncMap{ 236 "escapeFstabSpaces": escapeFstabSpaces, 237 "formatMountLabel": label.FormatMountLabel, 238 "isDirectory": isDirectory, 239 "keepCapabilities": keepCapabilities, 240 "dropList": dropList, 241 "getHostname": getHostname, 242 } 243 lxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) 244 if err != nil { 245 panic(err) 246 } 247 }