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