Browse code

Addition of "--shm-size" to which size of /dev/shm is changed.

- Optional "--shm-size=" was added to the sub-command(run, create,and build).
- The size of /dev/shm in the container can be changed
when container is made.
- Being able to specify is a numerical value that applies number,
b, k, m, and g.
- The default value is 64MB, when this option is not set.
- It deals with both native and lxc drivers.

Signed-off-by: NIWA Hideyuki <niwa.hiedyuki@jp.fujitsu.com>

NIWA Hideyuki authored on 2015/09/09 15:30:56
Showing 16 changed files
... ...
@@ -59,6 +59,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
59 59
 	dockerfileName := cmd.String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
60 60
 	flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
61 61
 	flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
62
+	flShmSize := cmd.String([]string{"-shm-size"}, "", "Size of /dev/shm, default value is 64MB")
62 63
 	flCPUShares := cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
63 64
 	flCPUPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
64 65
 	flCPUQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
... ...
@@ -210,6 +211,18 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
210 210
 		}
211 211
 	}
212 212
 
213
+	var shmSize int64 = 67108864 // initial SHM size is 64MB
214
+	if *flShmSize != "" {
215
+		parsedShmSize, err := units.RAMInBytes(*flShmSize)
216
+		if err != nil {
217
+			return err
218
+		}
219
+		if parsedShmSize <= 0 {
220
+			return fmt.Errorf("--shm-size: SHM size must be greater than 0 . You specified: %v ", parsedShmSize)
221
+		}
222
+		shmSize = parsedShmSize
223
+	}
224
+
213 225
 	// Send the build context
214 226
 	v := url.Values{
215 227
 		"t": flTags.GetAll(),
... ...
@@ -248,6 +261,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
248 248
 	v.Set("cpuperiod", strconv.FormatInt(*flCPUPeriod, 10))
249 249
 	v.Set("memory", strconv.FormatInt(memory, 10))
250 250
 	v.Set("memswap", strconv.FormatInt(memorySwap, 10))
251
+	v.Set("shmsize", strconv.FormatInt(shmSize, 10))
251 252
 	v.Set("cgroupparent", *flCgroupParent)
252 253
 
253 254
 	v.Set("dockerfile", relDockerfile)
... ...
@@ -323,6 +323,7 @@ func (s *router) postBuild(ctx context.Context, w http.ResponseWriter, r *http.R
323 323
 	buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm")
324 324
 	buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
325 325
 	buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory")
326
+	buildConfig.ShmSize = httputils.Int64ValueOrZero(r, "shmsize")
326 327
 	buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
327 328
 	buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
328 329
 	buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
... ...
@@ -60,6 +60,7 @@ type Config struct {
60 60
 
61 61
 	Memory       int64
62 62
 	MemorySwap   int64
63
+	ShmSize      int64
63 64
 	CPUShares    int64
64 65
 	CPUPeriod    int64
65 66
 	CPUQuota     int64
... ...
@@ -508,6 +508,7 @@ func (b *Builder) create() (*daemon.Container, error) {
508 508
 		CgroupParent: b.CgroupParent,
509 509
 		Memory:       b.Memory,
510 510
 		MemorySwap:   b.MemorySwap,
511
+		ShmSize:      b.ShmSize,
511 512
 		Ulimits:      b.Ulimits,
512 513
 		Isolation:    b.Isolation,
513 514
 	}
... ...
@@ -1357,7 +1357,12 @@ func (daemon *Daemon) setupIpcDirs(container *Container) error {
1357 1357
 			return err
1358 1358
 		}
1359 1359
 
1360
-		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("mode=1777,size=65536k", container.getMountLabel())); err != nil {
1360
+		// When ShmSize is 0 or less, the SHM size is set to 64MB.
1361
+		if container.hostConfig.ShmSize <= 0 {
1362
+			container.hostConfig.ShmSize = 67108864
1363
+		}
1364
+		shmproperty := "mode=1777,size=" + strconv.FormatInt(container.hostConfig.ShmSize, 10)
1365
+		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, container.getMountLabel())); err != nil {
1361 1366
 			return fmt.Errorf("mounting shm tmpfs: %s", err)
1362 1367
 		}
1363 1368
 		if err := os.Chown(shmPath, rootUID, rootGID); err != nil {
... ...
@@ -208,7 +208,8 @@ Create a container
208 208
              "LogConfig": { "Type": "json-file", "Config": {} },
209 209
              "SecurityOpt": [""],
210 210
              "CgroupParent": "",
211
-             "VolumeDriver": ""
211
+             "VolumeDriver": "",
212
+             "ShmSize": 67108864
212 213
           }
213 214
       }
214 215
 
... ...
@@ -318,6 +319,7 @@ Json Parameters:
318 318
           `json-file` logging driver.
319 319
     -   **CgroupParent** - Path to `cgroups` under which the container's `cgroup` is created. If the path is not absolute, the path is considered to be relative to the `cgroups` path of the init process. Cgroups are created if they do not already exist.
320 320
     -   **VolumeDriver** - Driver that this container users to mount volumes.
321
+    -   **ShmSize** - Size of `/dev/shm` in bytes. The size must be greater than 0.  If omitted the system uses 64MB.
321 322
 
322 323
 Query Parameters:
323 324
 
... ...
@@ -430,7 +432,8 @@ Return low-level information on the container `id`
430 430
 			"SecurityOpt": null,
431 431
 			"VolumesFrom": null,
432 432
 			"Ulimits": [{}],
433
-			"VolumeDriver": ""
433
+			"VolumeDriver": "",
434
+			"ShmSize": 67108864
434 435
 		},
435 436
 		"HostnamePath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname",
436 437
 		"HostsPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts",
... ...
@@ -1435,6 +1438,7 @@ Query Parameters:
1435 1435
         context for command(s) run via the Dockerfile's `RUN` instruction or for
1436 1436
         variable expansion in other Dockerfile instructions. This is not meant for
1437 1437
         passing secret values. [Read more about the buildargs instruction](../../reference/builder.md#arg)
1438
+-   **shmsize** - Size of `/dev/shm` in bytes. The size must be greater than 0.  If omitted the system uses 64MB.
1438 1439
 
1439 1440
     Request Headers:
1440 1441
 
... ...
@@ -31,6 +31,7 @@ parent = "smn_cli"
31 31
       --pull=false                    Always attempt to pull a newer version of the image
32 32
       -q, --quiet=false               Suppress the verbose output generated by the containers
33 33
       --rm=true                       Remove intermediate containers after a successful build
34
+      --shm-size=[]                   Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
34 35
       -t, --tag=[]                    Name and optionally a tag in the 'name:tag' format
35 36
       --ulimit=[]                     Ulimit options
36 37
 
... ...
@@ -65,6 +65,7 @@ Creates a new container.
65 65
       --restart="no"                Restart policy (no, on-failure[:max-retry], always, unless-stopped)
66 66
       --security-opt=[]             Security options
67 67
       --stop-signal="SIGTERM"       Signal to stop a container
68
+      --shm-size=[]                 Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
68 69
       -t, --tty=false               Allocate a pseudo-TTY
69 70
       -u, --user=""                 Username or UID
70 71
       --ulimit=[]                   Ulimit options
... ...
@@ -68,6 +68,7 @@ parent = "smn_cli"
68 68
       --read-only=false             Mount the container's root filesystem as read only
69 69
       --restart="no"                Restart policy (no, on-failure[:max-retry], always, unless-stopped)
70 70
       --rm=false                    Automatically remove the container when it exits
71
+      --shm-size=[]                 Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
71 72
       --security-opt=[]             Security Options
72 73
       --sig-proxy=true              Proxy received signals to the process
73 74
       --stop-signal="SIGTERM"       Signal to stop a container
... ...
@@ -626,6 +626,10 @@ container:
626 626
 | `--blkio-weight-device=""` | Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)                                                |
627 627
 | `--oom-kill-disable=false` | Whether to disable OOM Killer for the container or not.                                     |
628 628
 | `--memory-swappiness=""  ` | Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.        |
629
+| `--shm-size=""  `          | Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.      |
630
+|                            | Unit  is  optional   and   can  be  `b` (bytes),  `k` (kilobytes),   `m` (megabytes),   or  |
631
+|                            | `g` (gigabytes).  If  you  omit  the  unit,  the system  uses bytes.  If you omit the size  |
632
+|                            | entirely, the system uses `64m`.                                                            |
629 633
 
630 634
 ### User memory constraints
631 635
 
... ...
@@ -19,6 +19,7 @@ docker-build - Build a new image from the source code at PATH
19 19
 [**-t**|**--tag**[=*[]*]]
20 20
 [**-m**|**--memory**[=*MEMORY*]]
21 21
 [**--memory-swap**[=*MEMORY-SWAP*]]
22
+[**--shm-size**[=*SHM-SIZE*]]
22 23
 [**--cpu-period**[=*0*]]
23 24
 [**--cpu-quota**[=*0*]]
24 25
 [**--cpuset-cpus**[=*CPUSET-CPUS*]]
... ...
@@ -90,6 +91,11 @@ set as the **URL**, the repository is cloned locally and then sent as the contex
90 90
 **--memory-swap**=*MEMORY-SWAP*
91 91
   Total memory (memory + swap), '-1' to disable swap.
92 92
 
93
+**--shm-size**=*SHM-SIZE*
94
+  Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
95
+  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes.
96
+  If you omit the size entirely, the system uses `64m`.
97
+
93 98
 **--cpu-shares**=*0*
94 99
   CPU shares (relative weight).
95 100
 
... ...
@@ -54,6 +54,7 @@ docker-create - Create a new container
54 54
 [**--restart**[=*RESTART*]]
55 55
 [**--security-opt**[=*[]*]]
56 56
 [**--stop-signal**[=*SIGNAL*]]
57
+[**--shm-size**[=*[]*]]
57 58
 [**-t**|**--tty**[=*false*]]
58 59
 [**-u**|**--user**[=*USER*]]
59 60
 [**--ulimit**[=*[]*]]
... ...
@@ -252,6 +253,11 @@ This value should always larger than **-m**, so you should always use this with
252 252
 **--restart**="*no*"
253 253
    Restart policy to apply when a container exits (no, on-failure[:max-retry], always, unless-stopped).
254 254
 
255
+**--shm-size**=""
256
+   Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.
257
+   Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes.
258
+   If you omit the size entirely, the system uses `64m`.
259
+
255 260
 **--security-opt**=[]
256 261
    Security Options
257 262
 
... ...
@@ -56,6 +56,7 @@ docker-run - Run a command in a new container
56 56
 [**--rm**[=*false*]]
57 57
 [**--security-opt**[=*[]*]]
58 58
 [**--stop-signal**[=*SIGNAL*]]
59
+[**--shm-size**[=*[]*]]
59 60
 [**--sig-proxy**[=*true*]]
60 61
 [**-t**|**--tty**[=*false*]]
61 62
 [**-u**|**--user**[=*USER*]]
... ...
@@ -410,6 +411,11 @@ its root filesystem mounted as read only prohibiting any writes.
410 410
 **--stop-signal**=*SIGTERM*
411 411
   Signal to stop a container. Default is SIGTERM.
412 412
 
413
+**--shm-size**=""
414
+   Size of `/dev/shm`. The format is `<number><unit>`.
415
+   `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m`(megabytes), or `g` (gigabytes).
416
+   If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
417
+
413 418
 **--sig-proxy**=*true*|*false*
414 419
    Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied. The default is *true*.
415 420
 
... ...
@@ -211,6 +211,7 @@ type HostConfig struct {
211 211
 	SecurityOpt       []string              // List of string values to customize labels for MLS systems, such as SELinux.
212 212
 	Ulimits           []*ulimit.Ulimit      // List of ulimits to be set in the container
213 213
 	UTSMode           UTSMode               // UTS namespace to use for the container
214
+	ShmSize           int64                 // Total shm memory usage
214 215
 
215 216
 	// Applicable to Windows
216 217
 	ConsoleSize [2]int         // Initial console size
... ...
@@ -105,6 +105,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
105 105
 		flVolumeDriver      = cmd.String([]string{"-volume-driver"}, "", "Optional volume driver for the container")
106 106
 		flStopSignal        = cmd.String([]string{"-stop-signal"}, signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal))
107 107
 		flIsolation         = cmd.String([]string{"-isolation"}, "", "Container isolation level")
108
+		flShmSize           = cmd.String([]string{"-shm-size"}, "", "Size of /dev/shm, default value is 64MB")
108 109
 	)
109 110
 
110 111
 	cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
... ...
@@ -200,6 +201,18 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
200 200
 		return nil, nil, cmd, fmt.Errorf("Invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
201 201
 	}
202 202
 
203
+	var parsedShm int64 = 67108864 // initial SHM size is 64MB
204
+	if *flShmSize != "" {
205
+		var err error
206
+		parsedShm, err = units.RAMInBytes(*flShmSize)
207
+		if err != nil {
208
+			return nil, nil, cmd, fmt.Errorf("--shm-size: invalid SHM size")
209
+		}
210
+		if parsedShm <= 0 {
211
+			return nil, nil, cmd, fmt.Errorf("--shm-size: SHM size must be greater than 0 . You specified: %v ", parsedShm)
212
+		}
213
+	}
214
+
203 215
 	var binds []string
204 216
 	// add any bind targets to the list of container volumes
205 217
 	for bind := range flVolumes.GetMap() {
... ...
@@ -381,6 +394,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
381 381
 		CgroupParent:   *flCgroupParent,
382 382
 		VolumeDriver:   *flVolumeDriver,
383 383
 		Isolation:      IsolationLevel(*flIsolation),
384
+		ShmSize:        parsedShm,
384 385
 	}
385 386
 
386 387
 	// When allocating stdin in attached mode, close stdin at client disconnect
... ...
@@ -524,6 +524,18 @@ func TestParseModes(t *testing.T) {
524 524
 	if !hostconfig.UTSMode.Valid() {
525 525
 		t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode)
526 526
 	}
527
+	// shm-size ko
528
+	if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != "--shm-size: invalid SHM size" {
529
+		t.Fatalf("Expected an error with message '--shm-size: invalid SHM size', got %v", err)
530
+	}
531
+	// shm-size ok
532
+	_, hostconfig, _, err = parseRun([]string{"--shm-size=128m", "img", "cmd"})
533
+	if err != nil {
534
+		t.Fatal(err)
535
+	}
536
+	if hostconfig.ShmSize != 134217728 {
537
+		t.Fatalf("Expected a valid ShmSize, got %v", hostconfig.ShmSize)
538
+	}
527 539
 }
528 540
 
529 541
 func TestParseRestartPolicy(t *testing.T) {