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