Browse code

Add support for memory reservation

Signed-off-by: qhuang <qhuang@10.0.2.15>

qhuang authored on 2015/09/23 15:02:45
Showing 18 changed files
... ...
@@ -1151,6 +1151,7 @@ _docker_run() {
1151 1151
 		--memory -m
1152 1152
 		--memory-swap
1153 1153
 		--memory-swappiness
1154
+		--memory-reservation
1154 1155
 		--name
1155 1156
 		--net
1156 1157
 		--pid
... ...
@@ -254,18 +254,19 @@ func populateCommand(c *Container, env []string) error {
254 254
 	}
255 255
 
256 256
 	resources := &execdriver.Resources{
257
-		Memory:           c.hostConfig.Memory,
258
-		MemorySwap:       c.hostConfig.MemorySwap,
259
-		KernelMemory:     c.hostConfig.KernelMemory,
260
-		CPUShares:        c.hostConfig.CPUShares,
261
-		CpusetCpus:       c.hostConfig.CpusetCpus,
262
-		CpusetMems:       c.hostConfig.CpusetMems,
263
-		CPUPeriod:        c.hostConfig.CPUPeriod,
264
-		CPUQuota:         c.hostConfig.CPUQuota,
265
-		BlkioWeight:      c.hostConfig.BlkioWeight,
266
-		Rlimits:          rlimits,
267
-		OomKillDisable:   c.hostConfig.OomKillDisable,
268
-		MemorySwappiness: -1,
257
+		Memory:            c.hostConfig.Memory,
258
+		MemorySwap:        c.hostConfig.MemorySwap,
259
+		MemoryReservation: c.hostConfig.MemoryReservation,
260
+		KernelMemory:      c.hostConfig.KernelMemory,
261
+		CPUShares:         c.hostConfig.CPUShares,
262
+		CpusetCpus:        c.hostConfig.CpusetCpus,
263
+		CpusetMems:        c.hostConfig.CpusetMems,
264
+		CPUPeriod:         c.hostConfig.CPUPeriod,
265
+		CPUQuota:          c.hostConfig.CPUQuota,
266
+		BlkioWeight:       c.hostConfig.BlkioWeight,
267
+		Rlimits:           rlimits,
268
+		OomKillDisable:    c.hostConfig.OomKillDisable,
269
+		MemorySwappiness:  -1,
269 270
 	}
270 271
 
271 272
 	if c.hostConfig.MemorySwappiness != nil {
... ...
@@ -110,6 +110,9 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a
110 110
 		// By default, MemorySwap is set to twice the size of Memory.
111 111
 		hostConfig.MemorySwap = hostConfig.Memory * 2
112 112
 	}
113
+	if hostConfig.MemoryReservation == 0 && hostConfig.Memory > 0 {
114
+		hostConfig.MemoryReservation = hostConfig.Memory
115
+	}
113 116
 }
114 117
 
115 118
 // verifyPlatformContainerSettings performs platform-specific validation of the
... ...
@@ -154,6 +157,14 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
154 154
 			return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
155 155
 		}
156 156
 	}
157
+	if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation {
158
+		warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.")
159
+		logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.")
160
+		hostConfig.MemoryReservation = 0
161
+	}
162
+	if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation {
163
+		return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
164
+	}
157 165
 	if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory {
158 166
 		warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
159 167
 		logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
... ...
@@ -141,18 +141,19 @@ type UTS struct {
141 141
 // Currently these are all for cgroup configs.
142 142
 // TODO Windows: Factor out ulimit.Rlimit
143 143
 type Resources struct {
144
-	Memory           int64            `json:"memory"`
145
-	MemorySwap       int64            `json:"memory_swap"`
146
-	KernelMemory     int64            `json:"kernel_memory"`
147
-	CPUShares        int64            `json:"cpu_shares"`
148
-	CpusetCpus       string           `json:"cpuset_cpus"`
149
-	CpusetMems       string           `json:"cpuset_mems"`
150
-	CPUPeriod        int64            `json:"cpu_period"`
151
-	CPUQuota         int64            `json:"cpu_quota"`
152
-	BlkioWeight      int64            `json:"blkio_weight"`
153
-	Rlimits          []*ulimit.Rlimit `json:"rlimits"`
154
-	OomKillDisable   bool             `json:"oom_kill_disable"`
155
-	MemorySwappiness int64            `json:"memory_swappiness"`
144
+	Memory            int64            `json:"memory"`
145
+	MemorySwap        int64            `json:"memory_swap"`
146
+	MemoryReservation int64            `json:"memory_reservation"`
147
+	KernelMemory      int64            `json:"kernel_memory"`
148
+	CPUShares         int64            `json:"cpu_shares"`
149
+	CpusetCpus        string           `json:"cpuset_cpus"`
150
+	CpusetMems        string           `json:"cpuset_mems"`
151
+	CPUPeriod         int64            `json:"cpu_period"`
152
+	CPUQuota          int64            `json:"cpu_quota"`
153
+	BlkioWeight       int64            `json:"blkio_weight"`
154
+	Rlimits           []*ulimit.Rlimit `json:"rlimits"`
155
+	OomKillDisable    bool             `json:"oom_kill_disable"`
156
+	MemorySwappiness  int64            `json:"memory_swappiness"`
156 157
 }
157 158
 
158 159
 // ResourceStats contains information about resource usage by a container.
... ...
@@ -64,7 +64,7 @@ func SetupCgroups(container *configs.Config, c *Command) error {
64 64
 	if c.Resources != nil {
65 65
 		container.Cgroups.CpuShares = c.Resources.CPUShares
66 66
 		container.Cgroups.Memory = c.Resources.Memory
67
-		container.Cgroups.MemoryReservation = c.Resources.Memory
67
+		container.Cgroups.MemoryReservation = c.Resources.MemoryReservation
68 68
 		container.Cgroups.MemorySwap = c.Resources.MemorySwap
69 69
 		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
70 70
 		container.Cgroups.CpusetMems = c.Resources.CpusetMems
... ...
@@ -91,11 +91,13 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
91 91
 {{if .Resources}}
92 92
 {{if .Resources.Memory}}
93 93
 lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
94
-lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}}
95 94
 {{with $memSwap := getMemorySwap .Resources}}
96 95
 lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
97 96
 {{end}}
98 97
 {{end}}
98
+{{if gt .Resources.MemoryReservation 0}}
99
+lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}}
100
+{{end}}
99 101
 {{if gt .Resources.KernelMemory 0}}
100 102
 lxc.cgroup.memory.kmem.limit_in_bytes = {{.Resources.KernelMemory}}
101 103
 {{end}}
... ...
@@ -173,6 +173,7 @@ Create a container
173 173
              "LxcConf": {"lxc.utsname":"docker"},
174 174
              "Memory": 0,
175 175
              "MemorySwap": 0,
176
+             "MemoryReservation": 0,
176 177
              "KernelMemory": 0,
177 178
              "CpuShares": 512,
178 179
              "CpuPeriod": 100000,
... ...
@@ -223,6 +224,7 @@ Json Parameters:
223 223
 -   **Memory** - Memory limit in bytes.
224 224
 -   **MemorySwap** - Total memory limit (memory + swap); set `-1` to disable swap
225 225
       You must use this with `memory` and make the swap value larger than `memory`.
226
+-   **MemoryReservation** - Memory soft limit in bytes.
226 227
 -   **KernelMemory** - Kernel memory limit in bytes.
227 228
 -   **CpuShares** - An integer value containing the container's CPU Shares
228 229
       (ie. the relative weight vs other containers).
... ...
@@ -398,6 +400,7 @@ Return low-level information on the container `id`
398 398
 			"LxcConf": [],
399 399
 			"Memory": 0,
400 400
 			"MemorySwap": 0,
401
+			"MemoryReservation": 0,
401 402
 			"KernelMemory": 0,
402 403
 			"OomKillDisable": false,
403 404
 			"NetworkMode": "bridge",
... ...
@@ -50,6 +50,7 @@ Creates a new container.
50 50
       --lxc-conf=[]                 Add custom lxc options
51 51
       -m, --memory=""               Memory limit
52 52
       --mac-address=""              Container MAC address (e.g. 92:d0:c6:0a:29:33)
53
+      --memory-reservation=""       Memory soft limit
53 54
       --memory-swap=""              Total memory (memory + swap), '-1' to disable swap
54 55
       --memory-swappiness=""        Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
55 56
       --name=""                     Assign a name to the container
... ...
@@ -50,6 +50,7 @@ weight=1
50 50
       --lxc-conf=[]                 Add custom lxc options
51 51
       -m, --memory=""               Memory limit
52 52
       --mac-address=""              Container MAC address (e.g. 92:d0:c6:0a:29:33)
53
+      --memory-reservation=""       Memory soft limit
53 54
       --memory-swap=""              Total memory (memory + swap), '-1' to disable swap
54 55
       --memory-swappiness=""        Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
55 56
       --name=""                     Assign a name to the container
... ...
@@ -544,6 +544,7 @@ container:
544 544
 |----------------------------|---------------------------------------------------------------------------------------------|
545 545
 | `-m`, `--memory="" `       | Memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)                        |
546 546
 | `--memory-swap=""`         | Total memory limit (memory + swap, format: `<number>[<unit>]`, where unit = b, k, m or g)   |
547
+| `--memory-reservation=""`  | Memory soft limit (format: `<number>[<unit>]`, where unit = b, k, m or g)                   |
547 548
 | `--kernel-memory=""`       | Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)                 |
548 549
 | `-c`, `--cpu-shares=0`     | CPU shares (relative weight)                                                                |
549 550
 | `--cpu-period=0`           | Limit the CPU CFS (Completely Fair Scheduler) period                                        |
... ...
@@ -629,6 +630,43 @@ would be 2*300M, so processes can use 300M swap memory as well.
629 629
 We set both memory and swap memory, so the processes in the container can use
630 630
 300M memory and 700M swap memory.
631 631
 
632
+Memory reservation is a kind of memory soft limit that allows for greater
633
+sharing of memory. Under normal circumstances, containers can use as much of
634
+the memory as needed and are constrained only by the hard limits set with the
635
+`-m`/`--memory` option. When memory reservation is set, Docker detects memory
636
+contention or low memory and forces containers to restrict their consumption to
637
+a reservation limit.
638
+
639
+Always set the memory reservation value below the hard limit, otherwise the hard
640
+limit takes precedence. A reservation of 0 is the same as setting no
641
+reservation. By default (without reservation set), memory reservation is the
642
+same as the hard memory limit.
643
+
644
+Memory reservation is a soft-limit feature and does not guarantee the limit
645
+won't be exceeded. Instead, the feature attempts to ensure that, when memory is
646
+heavily contended for, memory is allocated based on the reservation hints/setup. 
647
+
648
+The following example limits the memory (`-m`) to 500M and sets the memory
649
+reservation to 200M.
650
+
651
+```bash
652
+$ docker run -ti -m 500M --memory-reservation 200M ubuntu:14.04 /bin/bash
653
+```
654
+
655
+Under this configuration, when the container consumes memory more than 200M and
656
+less than 500M, the next system memory reclaim attempts to shrink container
657
+memory below 200M.
658
+
659
+The following example set memory reservation to 1G without a hard memory limit.
660
+
661
+```bash
662
+$ docker run -ti --memory-reservation 1G ubuntu:14.04 /bin/bash
663
+```
664
+
665
+The container can use as much memory as it needs. The memory reservation setting
666
+ensures the container doesn't consume too much memory for long time, because
667
+every memory reclaim shrinks the container's consumption to the reservation.
668
+
632 669
 By default, kernel kills processes in a container if an out-of-memory (OOM)
633 670
 error occurs. To change this behaviour, use the `--oom-kill-disable` option.
634 671
 Only disable the OOM killer on containers where you have also set the
... ...
@@ -323,6 +323,22 @@ func (s *DockerSuite) TestRunWithSwappinessInvalid(c *check.C) {
323 323
 	}
324 324
 }
325 325
 
326
+func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
327
+	testRequires(c, memoryReservationSupport)
328
+	dockerCmd(c, "run", "--memory-reservation", "200M", "busybox", "true")
329
+}
330
+
331
+func (s *DockerSuite) TestRunWithMemoryReservationInvalid(c *check.C) {
332
+	testRequires(c, memoryLimitSupport)
333
+	testRequires(c, memoryReservationSupport)
334
+	out, _, err := dockerCmdWithError("run", "-m", "500M", "--memory-reservation", "800M", "busybox", "true")
335
+	c.Assert(err, check.NotNil)
336
+	expected := "Minimum memory limit should be larger than memory reservation limit"
337
+	if !strings.Contains(strings.TrimSpace(out), expected) {
338
+		c.Fatalf("run container should fail with invalid memory reservation, output: %q", out)
339
+	}
340
+}
341
+
326 342
 func (s *DockerSuite) TestStopContainerSignal(c *check.C) {
327 343
 	out, _ := dockerCmd(c, "run", "--stop-signal", "SIGUSR1", "-d", "busybox", "/bin/sh", "-c", `trap 'echo "exit trapped"; exit 0' USR1; while true; do sleep 1; done`)
328 344
 	containerID := strings.TrimSpace(out)
... ...
@@ -45,6 +45,12 @@ var (
45 45
 		},
46 46
 		"Test requires an environment that supports cgroup memory limit.",
47 47
 	}
48
+	memoryReservationSupport = testRequirement{
49
+		func() bool {
50
+			return SysInfo.MemoryReservation
51
+		},
52
+		"Test requires an environment that supports cgroup memory reservation.",
53
+	}
48 54
 	swapMemorySupport = testRequirement{
49 55
 		func() bool {
50 56
 			return SysInfo.SwapLimit
... ...
@@ -40,6 +40,7 @@ docker-create - Create a new container
40 40
 [**--lxc-conf**[=*[]*]]
41 41
 [**-m**|**--memory**[=*MEMORY*]]
42 42
 [**--mac-address**[=*MAC-ADDRESS*]]
43
+[**--memory-reservation**[=*MEMORY-RESERVATION*]]
43 44
 [**--memory-swap**[=*MEMORY-SWAP*]]
44 45
 [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
45 46
 [**--name**[=*NAME*]]
... ...
@@ -196,6 +197,15 @@ system's page size (the value would be very large, that's millions of trillions)
196 196
 **--mac-address**=""
197 197
    Container MAC address (e.g. 92:d0:c6:0a:29:33)
198 198
 
199
+**--memory-reservation**=""
200
+   Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)
201
+
202
+   After setting memory reservation, when the system detects memory contention
203
+or low memory, containers are forced to restrict their consumption to their
204
+reservation. So you should always set the value below **--memory**, otherwise the
205
+hard limit will take precedence. By default, memory reservation will be the same
206
+as memory limit.
207
+
199 208
 **--memory-swap**=""
200 209
    Total memory limit (memory + swap)
201 210
 
... ...
@@ -41,6 +41,7 @@ docker-run - Run a command in a new container
41 41
 [**--lxc-conf**[=*[]*]]
42 42
 [**-m**|**--memory**[=*MEMORY*]]
43 43
 [**--mac-address**[=*MAC-ADDRESS*]]
44
+[**--memory-reservation**[=*MEMORY-RESERVATION*]]
44 45
 [**--memory-swap**[=*MEMORY-SWAP*]]
45 46
 [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
46 47
 [**--name**[=*NAME*]]
... ...
@@ -290,6 +291,15 @@ RAM. If a limit of 0 is specified (not using **-m**), the container's memory is
290 290
 not limited. The actual limit may be rounded up to a multiple of the operating
291 291
 system's page size (the value would be very large, that's millions of trillions).
292 292
 
293
+**--memory-reservation**=""
294
+   Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)
295
+
296
+   After setting memory reservation, when the system detects memory contention
297
+or low memory, containers are forced to restrict their consumption to their
298
+reservation. So you should always set the value below **--memory**, otherwise the
299
+hard limit will take precedence. By default, memory reservation will be the same
300
+as memory limit.
301
+
293 302
 **--memory-swap**=""
294 303
    Total memory limit (memory + swap)
295 304
 
... ...
@@ -31,6 +31,9 @@ type cgroupMemInfo struct {
31 31
 	// Whether swap limit is supported or not
32 32
 	SwapLimit bool
33 33
 
34
+	// Whether soft limit is supported or not
35
+	MemoryReservation bool
36
+
34 37
 	// Whether OOM killer disalbe is supported or not
35 38
 	OomKillDisable bool
36 39
 
... ...
@@ -49,6 +49,10 @@ func checkCgroupMem(quiet bool) cgroupMemInfo {
49 49
 	if !quiet && !swapLimit {
50 50
 		logrus.Warn("Your kernel does not support swap memory limit.")
51 51
 	}
52
+	memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
53
+	if !quiet && !memoryReservation {
54
+		logrus.Warn("Your kernel does not support memory reservation.")
55
+	}
52 56
 	oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
53 57
 	if !quiet && !oomKillDisable {
54 58
 		logrus.Warnf("Your kernel does not support oom control.")
... ...
@@ -63,11 +67,12 @@ func checkCgroupMem(quiet bool) cgroupMemInfo {
63 63
 	}
64 64
 
65 65
 	return cgroupMemInfo{
66
-		MemoryLimit:      true,
67
-		SwapLimit:        swapLimit,
68
-		OomKillDisable:   oomKillDisable,
69
-		MemorySwappiness: memorySwappiness,
70
-		KernelMemory:     kernelMemory,
66
+		MemoryLimit:       true,
67
+		SwapLimit:         swapLimit,
68
+		MemoryReservation: memoryReservation,
69
+		OomKillDisable:    oomKillDisable,
70
+		MemorySwappiness:  memorySwappiness,
71
+		KernelMemory:      kernelMemory,
71 72
 	}
72 73
 }
73 74
 
... ...
@@ -214,45 +214,46 @@ func NewLxcConfig(values []KeyValuePair) *LxcConfig {
214 214
 // Here, "non-portable" means "dependent of the host we are running on".
215 215
 // Portable information *should* appear in Config.
216 216
 type HostConfig struct {
217
-	Binds            []string              // List of volume bindings for this container
218
-	ContainerIDFile  string                // File (path) where the containerId is written
219
-	LxcConf          *LxcConfig            // Additional lxc configuration
220
-	Memory           int64                 // Memory limit (in bytes)
221
-	MemorySwap       int64                 // Total memory usage (memory + swap); set `-1` to disable swap
222
-	KernelMemory     int64                 // Kernel memory limit (in bytes)
223
-	CPUShares        int64                 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
224
-	CPUPeriod        int64                 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
225
-	CpusetCpus       string                // CpusetCpus 0-2, 0,1
226
-	CpusetMems       string                // CpusetMems 0-2, 0,1
227
-	CPUQuota         int64                 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
228
-	BlkioWeight      int64                 // Block IO weight (relative weight vs. other containers)
229
-	OomKillDisable   bool                  // Whether to disable OOM Killer or not
230
-	MemorySwappiness *int64                // Tuning container memory swappiness behaviour
231
-	Privileged       bool                  // Is the container in privileged mode
232
-	PortBindings     nat.PortMap           // Port mapping between the exposed port (container) and the host
233
-	Links            []string              // List of links (in the name:alias form)
234
-	PublishAllPorts  bool                  // Should docker publish all exposed port for the container
235
-	DNS              []string              `json:"Dns"`        // List of DNS server to lookup
236
-	DNSOptions       []string              `json:"DnsOptions"` // List of DNSOption to look for
237
-	DNSSearch        []string              `json:"DnsSearch"`  // List of DNSSearch to look for
238
-	ExtraHosts       []string              // List of extra hosts
239
-	VolumesFrom      []string              // List of volumes to take from other container
240
-	Devices          []DeviceMapping       // List of devices to map inside the container
241
-	NetworkMode      NetworkMode           // Network namespace to use for the container
242
-	IpcMode          IpcMode               // IPC namespace to use for the container
243
-	PidMode          PidMode               // PID namespace to use for the container
244
-	UTSMode          UTSMode               // UTS namespace to use for the container
245
-	CapAdd           *stringutils.StrSlice // List of kernel capabilities to add to the container
246
-	CapDrop          *stringutils.StrSlice // List of kernel capabilities to remove from the container
247
-	GroupAdd         []string              // List of additional groups that the container process will run as
248
-	RestartPolicy    RestartPolicy         // Restart policy to be used for the container
249
-	SecurityOpt      []string              // List of string values to customize labels for MLS systems, such as SELinux.
250
-	ReadonlyRootfs   bool                  // Is the container root filesystem in read-only
251
-	Ulimits          []*ulimit.Ulimit      // List of ulimits to be set in the container
252
-	LogConfig        LogConfig             // Configuration of the logs for this container
253
-	CgroupParent     string                // Parent cgroup.
254
-	ConsoleSize      [2]int                // Initial console size on Windows
255
-	VolumeDriver     string                // Name of the volume driver used to mount volumes
217
+	Binds             []string              // List of volume bindings for this container
218
+	ContainerIDFile   string                // File (path) where the containerId is written
219
+	LxcConf           *LxcConfig            // Additional lxc configuration
220
+	Memory            int64                 // Memory limit (in bytes)
221
+	MemoryReservation int64                 // Memory soft limit (in bytes)
222
+	MemorySwap        int64                 // Total memory usage (memory + swap); set `-1` to disable swap
223
+	KernelMemory      int64                 // Kernel memory limit (in bytes)
224
+	CPUShares         int64                 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
225
+	CPUPeriod         int64                 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
226
+	CpusetCpus        string                // CpusetCpus 0-2, 0,1
227
+	CpusetMems        string                // CpusetMems 0-2, 0,1
228
+	CPUQuota          int64                 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
229
+	BlkioWeight       int64                 // Block IO weight (relative weight vs. other containers)
230
+	OomKillDisable    bool                  // Whether to disable OOM Killer or not
231
+	MemorySwappiness  *int64                // Tuning container memory swappiness behaviour
232
+	Privileged        bool                  // Is the container in privileged mode
233
+	PortBindings      nat.PortMap           // Port mapping between the exposed port (container) and the host
234
+	Links             []string              // List of links (in the name:alias form)
235
+	PublishAllPorts   bool                  // Should docker publish all exposed port for the container
236
+	DNS               []string              `json:"Dns"`        // List of DNS server to lookup
237
+	DNSOptions        []string              `json:"DnsOptions"` // List of DNSOption to look for
238
+	DNSSearch         []string              `json:"DnsSearch"`  // List of DNSSearch to look for
239
+	ExtraHosts        []string              // List of extra hosts
240
+	VolumesFrom       []string              // List of volumes to take from other container
241
+	Devices           []DeviceMapping       // List of devices to map inside the container
242
+	NetworkMode       NetworkMode           // Network namespace to use for the container
243
+	IpcMode           IpcMode               // IPC namespace to use for the container
244
+	PidMode           PidMode               // PID namespace to use for the container
245
+	UTSMode           UTSMode               // UTS namespace to use for the container
246
+	CapAdd            *stringutils.StrSlice // List of kernel capabilities to add to the container
247
+	CapDrop           *stringutils.StrSlice // List of kernel capabilities to remove from the container
248
+	GroupAdd          []string              // List of additional groups that the container process will run as
249
+	RestartPolicy     RestartPolicy         // Restart policy to be used for the container
250
+	SecurityOpt       []string              // List of string values to customize labels for MLS systems, such as SELinux.
251
+	ReadonlyRootfs    bool                  // Is the container root filesystem in read-only
252
+	Ulimits           []*ulimit.Ulimit      // List of ulimits to be set in the container
253
+	LogConfig         LogConfig             // Configuration of the logs for this container
254
+	CgroupParent      string                // Parent cgroup.
255
+	ConsoleSize       [2]int                // Initial console size on Windows
256
+	VolumeDriver      string                // Name of the volume driver used to mount volumes
256 257
 }
257 258
 
258 259
 // DecodeHostConfig creates a HostConfig based on the specified Reader.
... ...
@@ -64,38 +64,39 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
64 64
 		flLabelsFile  = opts.NewListOpts(nil)
65 65
 		flLoggingOpts = opts.NewListOpts(nil)
66 66
 
67
-		flNetwork         = cmd.Bool([]string{"#n", "#-networking"}, true, "Enable networking for this container")
68
-		flPrivileged      = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
69
-		flPidMode         = cmd.String([]string{"-pid"}, "", "PID namespace to use")
70
-		flUTSMode         = cmd.String([]string{"-uts"}, "", "UTS namespace to use")
71
-		flPublishAll      = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports")
72
-		flStdin           = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
73
-		flTty             = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
74
-		flOomKillDisable  = cmd.Bool([]string{"-oom-kill-disable"}, false, "Disable OOM Killer")
75
-		flContainerIDFile = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
76
-		flEntrypoint      = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
77
-		flHostname        = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
78
-		flMemoryString    = cmd.String([]string{"m", "-memory"}, "", "Memory limit")
79
-		flMemorySwap      = cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
80
-		flKernelMemory    = cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
81
-		flUser            = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
82
-		flWorkingDir      = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
83
-		flCPUShares       = cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
84
-		flCPUPeriod       = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
85
-		flCPUQuota        = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
86
-		flCpusetCpus      = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
87
-		flCpusetMems      = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
88
-		flBlkioWeight     = cmd.Int64([]string{"-blkio-weight"}, 0, "Block IO (relative weight), between 10 and 1000")
89
-		flSwappiness      = cmd.Int64([]string{"-memory-swappiness"}, -1, "Tuning container memory swappiness (0 to 100)")
90
-		flNetMode         = cmd.String([]string{"-net"}, "default", "Set the Network mode for the container")
91
-		flMacAddress      = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
92
-		flIpcMode         = cmd.String([]string{"-ipc"}, "", "IPC namespace to use")
93
-		flRestartPolicy   = cmd.String([]string{"-restart"}, "no", "Restart policy to apply when a container exits")
94
-		flReadonlyRootfs  = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
95
-		flLoggingDriver   = cmd.String([]string{"-log-driver"}, "", "Logging driver for container")
96
-		flCgroupParent    = cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
97
-		flVolumeDriver    = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
98
-		flStopSignal      = cmd.String([]string{"-stop-signal"}, signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal))
67
+		flNetwork           = cmd.Bool([]string{"#n", "#-networking"}, true, "Enable networking for this container")
68
+		flPrivileged        = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
69
+		flPidMode           = cmd.String([]string{"-pid"}, "", "PID namespace to use")
70
+		flUTSMode           = cmd.String([]string{"-uts"}, "", "UTS namespace to use")
71
+		flPublishAll        = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports")
72
+		flStdin             = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
73
+		flTty               = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
74
+		flOomKillDisable    = cmd.Bool([]string{"-oom-kill-disable"}, false, "Disable OOM Killer")
75
+		flContainerIDFile   = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
76
+		flEntrypoint        = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
77
+		flHostname          = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
78
+		flMemoryString      = cmd.String([]string{"m", "-memory"}, "", "Memory limit")
79
+		flMemoryReservation = cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
80
+		flMemorySwap        = cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
81
+		flKernelMemory      = cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
82
+		flUser              = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
83
+		flWorkingDir        = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
84
+		flCPUShares         = cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
85
+		flCPUPeriod         = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
86
+		flCPUQuota          = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota")
87
+		flCpusetCpus        = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
88
+		flCpusetMems        = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
89
+		flBlkioWeight       = cmd.Int64([]string{"-blkio-weight"}, 0, "Block IO (relative weight), between 10 and 1000")
90
+		flSwappiness        = cmd.Int64([]string{"-memory-swappiness"}, -1, "Tuning container memory swappiness (0 to 100)")
91
+		flNetMode           = cmd.String([]string{"-net"}, "default", "Set the Network mode for the container")
92
+		flMacAddress        = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
93
+		flIpcMode           = cmd.String([]string{"-ipc"}, "", "IPC namespace to use")
94
+		flRestartPolicy     = cmd.String([]string{"-restart"}, "no", "Restart policy to apply when a container exits")
95
+		flReadonlyRootfs    = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
96
+		flLoggingDriver     = cmd.String([]string{"-log-driver"}, "", "Logging driver for container")
97
+		flCgroupParent      = cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
98
+		flVolumeDriver      = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
99
+		flStopSignal        = cmd.String([]string{"-stop-signal"}, signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal))
99 100
 	)
100 101
 
101 102
 	cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
... ...
@@ -160,6 +161,14 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
160 160
 		}
161 161
 	}
162 162
 
163
+	var MemoryReservation int64
164
+	if *flMemoryReservation != "" {
165
+		MemoryReservation, err = units.RAMInBytes(*flMemoryReservation)
166
+		if err != nil {
167
+			return nil, nil, cmd, err
168
+		}
169
+	}
170
+
163 171
 	var memorySwap int64
164 172
 	if *flMemorySwap != "" {
165 173
 		if *flMemorySwap == "-1" {
... ...
@@ -329,44 +338,45 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
329 329
 	}
330 330
 
331 331
 	hostConfig := &HostConfig{
332
-		Binds:            binds,
333
-		ContainerIDFile:  *flContainerIDFile,
334
-		LxcConf:          lxcConf,
335
-		Memory:           flMemory,
336
-		MemorySwap:       memorySwap,
337
-		KernelMemory:     KernelMemory,
338
-		CPUShares:        *flCPUShares,
339
-		CPUPeriod:        *flCPUPeriod,
340
-		CpusetCpus:       *flCpusetCpus,
341
-		CpusetMems:       *flCpusetMems,
342
-		CPUQuota:         *flCPUQuota,
343
-		BlkioWeight:      *flBlkioWeight,
344
-		OomKillDisable:   *flOomKillDisable,
345
-		MemorySwappiness: flSwappiness,
346
-		Privileged:       *flPrivileged,
347
-		PortBindings:     portBindings,
348
-		Links:            flLinks.GetAll(),
349
-		PublishAllPorts:  *flPublishAll,
350
-		DNS:              flDNS.GetAll(),
351
-		DNSSearch:        flDNSSearch.GetAll(),
352
-		DNSOptions:       flDNSOptions.GetAll(),
353
-		ExtraHosts:       flExtraHosts.GetAll(),
354
-		VolumesFrom:      flVolumesFrom.GetAll(),
355
-		NetworkMode:      NetworkMode(*flNetMode),
356
-		IpcMode:          ipcMode,
357
-		PidMode:          pidMode,
358
-		UTSMode:          utsMode,
359
-		Devices:          deviceMappings,
360
-		CapAdd:           stringutils.NewStrSlice(flCapAdd.GetAll()...),
361
-		CapDrop:          stringutils.NewStrSlice(flCapDrop.GetAll()...),
362
-		GroupAdd:         flGroupAdd.GetAll(),
363
-		RestartPolicy:    restartPolicy,
364
-		SecurityOpt:      flSecurityOpt.GetAll(),
365
-		ReadonlyRootfs:   *flReadonlyRootfs,
366
-		Ulimits:          flUlimits.GetList(),
367
-		LogConfig:        LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
368
-		CgroupParent:     *flCgroupParent,
369
-		VolumeDriver:     *flVolumeDriver,
332
+		Binds:             binds,
333
+		ContainerIDFile:   *flContainerIDFile,
334
+		LxcConf:           lxcConf,
335
+		Memory:            flMemory,
336
+		MemoryReservation: MemoryReservation,
337
+		MemorySwap:        memorySwap,
338
+		KernelMemory:      KernelMemory,
339
+		CPUShares:         *flCPUShares,
340
+		CPUPeriod:         *flCPUPeriod,
341
+		CpusetCpus:        *flCpusetCpus,
342
+		CpusetMems:        *flCpusetMems,
343
+		CPUQuota:          *flCPUQuota,
344
+		BlkioWeight:       *flBlkioWeight,
345
+		OomKillDisable:    *flOomKillDisable,
346
+		MemorySwappiness:  flSwappiness,
347
+		Privileged:        *flPrivileged,
348
+		PortBindings:      portBindings,
349
+		Links:             flLinks.GetAll(),
350
+		PublishAllPorts:   *flPublishAll,
351
+		DNS:               flDNS.GetAll(),
352
+		DNSSearch:         flDNSSearch.GetAll(),
353
+		DNSOptions:        flDNSOptions.GetAll(),
354
+		ExtraHosts:        flExtraHosts.GetAll(),
355
+		VolumesFrom:       flVolumesFrom.GetAll(),
356
+		NetworkMode:       NetworkMode(*flNetMode),
357
+		IpcMode:           ipcMode,
358
+		PidMode:           pidMode,
359
+		UTSMode:           utsMode,
360
+		Devices:           deviceMappings,
361
+		CapAdd:            stringutils.NewStrSlice(flCapAdd.GetAll()...),
362
+		CapDrop:           stringutils.NewStrSlice(flCapDrop.GetAll()...),
363
+		GroupAdd:          flGroupAdd.GetAll(),
364
+		RestartPolicy:     restartPolicy,
365
+		SecurityOpt:       flSecurityOpt.GetAll(),
366
+		ReadonlyRootfs:    *flReadonlyRootfs,
367
+		Ulimits:           flUlimits.GetList(),
368
+		LogConfig:         LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
369
+		CgroupParent:      *flCgroupParent,
370
+		VolumeDriver:      *flVolumeDriver,
370 371
 	}
371 372
 
372 373
 	applyExperimentalFlags(expFlags, config, hostConfig)