Signed-off-by: Antonio Murdaca <runcom@redhat.com>
Antonio Murdaca authored on 2015/11/26 21:14:09... | ... |
@@ -211,18 +211,6 @@ func (cli *DockerCli) CmdBuild(args ...string) error { |
211 | 211 |
} |
212 | 212 |
} |
213 | 213 |
|
214 |
- var shmSize int64 = 67108864 // initial SHM size is 64MB |
|
215 |
- if *flShmSize != "" { |
|
216 |
- parsedShmSize, err := units.RAMInBytes(*flShmSize) |
|
217 |
- if err != nil { |
|
218 |
- return err |
|
219 |
- } |
|
220 |
- if parsedShmSize <= 0 { |
|
221 |
- return fmt.Errorf("--shm-size: SHM size must be greater than 0 . You specified: %v ", parsedShmSize) |
|
222 |
- } |
|
223 |
- shmSize = parsedShmSize |
|
224 |
- } |
|
225 |
- |
|
226 | 214 |
// Send the build context |
227 | 215 |
v := url.Values{ |
228 | 216 |
"t": flTags.GetAll(), |
... | ... |
@@ -261,9 +249,16 @@ func (cli *DockerCli) CmdBuild(args ...string) error { |
261 | 261 |
v.Set("cpuperiod", strconv.FormatInt(*flCPUPeriod, 10)) |
262 | 262 |
v.Set("memory", strconv.FormatInt(memory, 10)) |
263 | 263 |
v.Set("memswap", strconv.FormatInt(memorySwap, 10)) |
264 |
- v.Set("shmsize", strconv.FormatInt(shmSize, 10)) |
|
265 | 264 |
v.Set("cgroupparent", *flCgroupParent) |
266 | 265 |
|
266 |
+ if *flShmSize != "" { |
|
267 |
+ parsedShmSize, err := units.RAMInBytes(*flShmSize) |
|
268 |
+ if err != nil { |
|
269 |
+ return err |
|
270 |
+ } |
|
271 |
+ v.Set("shmsize", strconv.FormatInt(parsedShmSize, 10)) |
|
272 |
+ } |
|
273 |
+ |
|
267 | 274 |
v.Set("dockerfile", relDockerfile) |
268 | 275 |
|
269 | 276 |
ulimitsVar := flUlimits.GetList() |
... | ... |
@@ -357,7 +357,11 @@ func (s *router) postBuild(ctx context.Context, w http.ResponseWriter, r *http.R |
357 | 357 |
buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm") |
358 | 358 |
buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap") |
359 | 359 |
buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory") |
360 |
- buildConfig.ShmSize = httputils.Int64ValueOrZero(r, "shmsize") |
|
360 |
+ shmSize, err := httputils.Int64ValueOrDefault(r, "shmsize", runconfig.DefaultSHMSize) |
|
361 |
+ if err != nil { |
|
362 |
+ return errf(err) |
|
363 |
+ } |
|
364 |
+ buildConfig.ShmSize = &shmSize |
|
361 | 365 |
buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares") |
362 | 366 |
buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod") |
363 | 367 |
buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota") |
... | ... |
@@ -1358,11 +1358,12 @@ func (daemon *Daemon) setupIpcDirs(container *Container) error { |
1358 | 1358 |
return err |
1359 | 1359 |
} |
1360 | 1360 |
|
1361 |
- // When ShmSize is 0 or less, the SHM size is set to 64MB. |
|
1362 |
- if container.hostConfig.ShmSize <= 0 { |
|
1363 |
- container.hostConfig.ShmSize = 67108864 |
|
1361 |
+ shmSize := runconfig.DefaultSHMSize |
|
1362 |
+ if container.hostConfig.ShmSize != nil { |
|
1363 |
+ shmSize = *container.hostConfig.ShmSize |
|
1364 | 1364 |
} |
1365 |
- shmproperty := "mode=1777,size=" + strconv.FormatInt(container.hostConfig.ShmSize, 10) |
|
1365 |
+ |
|
1366 |
+ shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10) |
|
1366 | 1367 |
if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, container.getMountLabel())); err != nil { |
1367 | 1368 |
return fmt.Errorf("mounting shm tmpfs: %s", err) |
1368 | 1369 |
} |
... | ... |
@@ -131,6 +131,10 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a |
131 | 131 |
// By default, MemorySwap is set to twice the size of Memory. |
132 | 132 |
hostConfig.MemorySwap = hostConfig.Memory * 2 |
133 | 133 |
} |
134 |
+ if hostConfig.ShmSize == nil { |
|
135 |
+ shmSize := runconfig.DefaultSHMSize |
|
136 |
+ hostConfig.ShmSize = &shmSize |
|
137 |
+ } |
|
134 | 138 |
} |
135 | 139 |
|
136 | 140 |
// verifyPlatformContainerSettings performs platform-specific validation of the |
... | ... |
@@ -144,6 +148,10 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC |
144 | 144 |
return warnings, err |
145 | 145 |
} |
146 | 146 |
|
147 |
+ if hostConfig.ShmSize != nil && *hostConfig.ShmSize <= 0 { |
|
148 |
+ return warnings, fmt.Errorf("SHM size must be greater then 0") |
|
149 |
+ } |
|
150 |
+ |
|
147 | 151 |
// memory subsystem checks and adjustments |
148 | 152 |
if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { |
149 | 153 |
return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") |
... | ... |
@@ -10,6 +10,7 @@ import ( |
10 | 10 |
"net/http/httputil" |
11 | 11 |
"net/url" |
12 | 12 |
"os" |
13 |
+ "regexp" |
|
13 | 14 |
"strconv" |
14 | 15 |
"strings" |
15 | 16 |
"time" |
... | ... |
@@ -1388,3 +1389,138 @@ func (s *DockerSuite) TestStartWithNilDNS(c *check.C) { |
1388 | 1388 |
c.Assert(err, checker.IsNil) |
1389 | 1389 |
c.Assert(dns, checker.Equals, "[]") |
1390 | 1390 |
} |
1391 |
+ |
|
1392 |
+func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) { |
|
1393 |
+ config := map[string]interface{}{ |
|
1394 |
+ "Image": "busybox", |
|
1395 |
+ "HostConfig": map[string]interface{}{"ShmSize": -1}, |
|
1396 |
+ } |
|
1397 |
+ |
|
1398 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1399 |
+ c.Assert(err, check.IsNil) |
|
1400 |
+ c.Assert(status, check.Equals, http.StatusInternalServerError) |
|
1401 |
+ c.Assert(string(body), checker.Contains, "SHM size must be greater then 0") |
|
1402 |
+} |
|
1403 |
+ |
|
1404 |
+func (s *DockerSuite) TestPostContainersCreateShmSizeZero(c *check.C) { |
|
1405 |
+ config := map[string]interface{}{ |
|
1406 |
+ "Image": "busybox", |
|
1407 |
+ "HostConfig": map[string]interface{}{"ShmSize": 0}, |
|
1408 |
+ } |
|
1409 |
+ |
|
1410 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1411 |
+ c.Assert(err, check.IsNil) |
|
1412 |
+ c.Assert(status, check.Equals, http.StatusInternalServerError) |
|
1413 |
+ c.Assert(string(body), checker.Contains, "SHM size must be greater then 0") |
|
1414 |
+} |
|
1415 |
+ |
|
1416 |
+func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.C) { |
|
1417 |
+ config := map[string]interface{}{ |
|
1418 |
+ "Image": "busybox", |
|
1419 |
+ "Cmd": "mount", |
|
1420 |
+ } |
|
1421 |
+ |
|
1422 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1423 |
+ c.Assert(err, check.IsNil) |
|
1424 |
+ c.Assert(status, check.Equals, http.StatusCreated) |
|
1425 |
+ |
|
1426 |
+ var container types.ContainerCreateResponse |
|
1427 |
+ c.Assert(json.Unmarshal(body, &container), check.IsNil) |
|
1428 |
+ |
|
1429 |
+ status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) |
|
1430 |
+ c.Assert(err, check.IsNil) |
|
1431 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
1432 |
+ |
|
1433 |
+ var containerJSON types.ContainerJSON |
|
1434 |
+ c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) |
|
1435 |
+ |
|
1436 |
+ c.Assert(containerJSON.HostConfig.ShmSize, check.IsNil) |
|
1437 |
+ |
|
1438 |
+ out, _ := dockerCmd(c, "start", "-i", containerJSON.ID) |
|
1439 |
+ shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) |
|
1440 |
+ if !shmRegexp.MatchString(out) { |
|
1441 |
+ c.Fatalf("Expected shm of 64MB in mount command, got %v", out) |
|
1442 |
+ } |
|
1443 |
+} |
|
1444 |
+ |
|
1445 |
+func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *check.C) { |
|
1446 |
+ config := map[string]interface{}{ |
|
1447 |
+ "Image": "busybox", |
|
1448 |
+ "HostConfig": map[string]interface{}{}, |
|
1449 |
+ "Cmd": "mount", |
|
1450 |
+ } |
|
1451 |
+ |
|
1452 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1453 |
+ c.Assert(err, check.IsNil) |
|
1454 |
+ c.Assert(status, check.Equals, http.StatusCreated) |
|
1455 |
+ |
|
1456 |
+ var container types.ContainerCreateResponse |
|
1457 |
+ c.Assert(json.Unmarshal(body, &container), check.IsNil) |
|
1458 |
+ |
|
1459 |
+ status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) |
|
1460 |
+ c.Assert(err, check.IsNil) |
|
1461 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
1462 |
+ |
|
1463 |
+ var containerJSON types.ContainerJSON |
|
1464 |
+ c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) |
|
1465 |
+ |
|
1466 |
+ c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, runconfig.DefaultSHMSize) |
|
1467 |
+ |
|
1468 |
+ out, _ := dockerCmd(c, "start", "-i", containerJSON.ID) |
|
1469 |
+ shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) |
|
1470 |
+ if !shmRegexp.MatchString(out) { |
|
1471 |
+ c.Fatalf("Expected shm of 64MB in mount command, got %v", out) |
|
1472 |
+ } |
|
1473 |
+} |
|
1474 |
+ |
|
1475 |
+func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *check.C) { |
|
1476 |
+ config := map[string]interface{}{ |
|
1477 |
+ "Image": "busybox", |
|
1478 |
+ "Cmd": "mount", |
|
1479 |
+ "HostConfig": map[string]interface{}{"ShmSize": 1073741824}, |
|
1480 |
+ } |
|
1481 |
+ |
|
1482 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1483 |
+ c.Assert(err, check.IsNil) |
|
1484 |
+ c.Assert(status, check.Equals, http.StatusCreated) |
|
1485 |
+ |
|
1486 |
+ var container types.ContainerCreateResponse |
|
1487 |
+ c.Assert(json.Unmarshal(body, &container), check.IsNil) |
|
1488 |
+ |
|
1489 |
+ status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) |
|
1490 |
+ c.Assert(err, check.IsNil) |
|
1491 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
1492 |
+ |
|
1493 |
+ var containerJSON types.ContainerJSON |
|
1494 |
+ c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) |
|
1495 |
+ |
|
1496 |
+ c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, int64(1073741824)) |
|
1497 |
+ |
|
1498 |
+ out, _ := dockerCmd(c, "start", "-i", containerJSON.ID) |
|
1499 |
+ shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`) |
|
1500 |
+ if !shmRegex.MatchString(out) { |
|
1501 |
+ c.Fatalf("Expected shm of 1GB in mount command, got %v", out) |
|
1502 |
+ } |
|
1503 |
+} |
|
1504 |
+ |
|
1505 |
+func (s *DockerSuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(c *check.C) { |
|
1506 |
+ config := map[string]interface{}{ |
|
1507 |
+ "Image": "busybox", |
|
1508 |
+ } |
|
1509 |
+ |
|
1510 |
+ status, body, err := sockRequest("POST", "/containers/create", config) |
|
1511 |
+ c.Assert(err, check.IsNil) |
|
1512 |
+ c.Assert(status, check.Equals, http.StatusCreated) |
|
1513 |
+ |
|
1514 |
+ var container types.ContainerCreateResponse |
|
1515 |
+ c.Assert(json.Unmarshal(body, &container), check.IsNil) |
|
1516 |
+ |
|
1517 |
+ status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) |
|
1518 |
+ c.Assert(err, check.IsNil) |
|
1519 |
+ c.Assert(status, check.Equals, http.StatusOK) |
|
1520 |
+ |
|
1521 |
+ var containerJSON types.ContainerJSON |
|
1522 |
+ c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) |
|
1523 |
+ |
|
1524 |
+ c.Assert(containerJSON.HostConfig.MemorySwappiness, check.IsNil) |
|
1525 |
+} |
... | ... |
@@ -9,6 +9,7 @@ import ( |
9 | 9 |
"os" |
10 | 10 |
"os/exec" |
11 | 11 |
"path/filepath" |
12 |
+ "regexp" |
|
12 | 13 |
"strconv" |
13 | 14 |
"strings" |
14 | 15 |
"time" |
... | ... |
@@ -409,3 +410,31 @@ func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) { |
409 | 409 |
expected = "The maximum allowed cpu-shares is" |
410 | 410 |
c.Assert(out, checker.Contains, expected) |
411 | 411 |
} |
412 |
+ |
|
413 |
+func (s *DockerSuite) TestRunWithDefaultShmSize(c *check.C) { |
|
414 |
+ testRequires(c, DaemonIsLinux) |
|
415 |
+ |
|
416 |
+ name := "shm-default" |
|
417 |
+ out, _ := dockerCmd(c, "run", "--name", name, "busybox", "mount") |
|
418 |
+ shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) |
|
419 |
+ if !shmRegex.MatchString(out) { |
|
420 |
+ c.Fatalf("Expected shm of 64MB in mount command, got %v", out) |
|
421 |
+ } |
|
422 |
+ shmSize, err := inspectField(name, "HostConfig.ShmSize") |
|
423 |
+ c.Assert(err, check.IsNil) |
|
424 |
+ c.Assert(shmSize, check.Equals, "67108864") |
|
425 |
+} |
|
426 |
+ |
|
427 |
+func (s *DockerSuite) TestRunWithShmSize(c *check.C) { |
|
428 |
+ testRequires(c, DaemonIsLinux) |
|
429 |
+ |
|
430 |
+ name := "shm" |
|
431 |
+ out, _ := dockerCmd(c, "run", "--name", name, "--shm-size=1G", "busybox", "mount") |
|
432 |
+ shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`) |
|
433 |
+ if !shmRegex.MatchString(out) { |
|
434 |
+ c.Fatalf("Expected shm of 1GB in mount command, got %v", out) |
|
435 |
+ } |
|
436 |
+ shmSize, err := inspectField(name, "HostConfig.ShmSize") |
|
437 |
+ c.Assert(err, check.IsNil) |
|
438 |
+ c.Assert(shmSize, check.Equals, "1073741824") |
|
439 |
+} |
... | ... |
@@ -218,7 +218,7 @@ type HostConfig struct { |
218 | 218 |
ReadonlyRootfs bool // Is the container root filesystem in read-only |
219 | 219 |
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. |
220 | 220 |
UTSMode UTSMode // UTS namespace to use for the container |
221 |
- ShmSize int64 // Total shm memory usage |
|
221 |
+ ShmSize *int64 // Total shm memory usage |
|
222 | 222 |
|
223 | 223 |
// Applicable to Windows |
224 | 224 |
ConsoleSize [2]int // Initial console size |
... | ... |
@@ -42,6 +42,9 @@ var ( |
42 | 42 |
ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: --expose and the network mode (--net)") |
43 | 43 |
) |
44 | 44 |
|
45 |
+// DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container |
|
46 |
+const DefaultSHMSize int64 = 67108864 |
|
47 |
+ |
|
45 | 48 |
// Parse parses the specified args for the specified command and generates a Config, |
46 | 49 |
// a HostConfig and returns them with the specified command. |
47 | 50 |
// If the specified args are not valid, it will return an error. |
... | ... |
@@ -201,16 +204,13 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
201 | 201 |
return nil, nil, cmd, fmt.Errorf("Invalid value: %d. Valid memory swappiness range is 0-100", swappiness) |
202 | 202 |
} |
203 | 203 |
|
204 |
- var parsedShm int64 = 67108864 // initial SHM size is 64MB |
|
204 |
+ var parsedShm *int64 |
|
205 | 205 |
if *flShmSize != "" { |
206 |
- var err error |
|
207 |
- parsedShm, err = units.RAMInBytes(*flShmSize) |
|
206 |
+ shmSize, err := units.RAMInBytes(*flShmSize) |
|
208 | 207 |
if err != nil { |
209 |
- return nil, nil, cmd, fmt.Errorf("--shm-size: invalid SHM size") |
|
210 |
- } |
|
211 |
- if parsedShm <= 0 { |
|
212 |
- return nil, nil, cmd, fmt.Errorf("--shm-size: SHM size must be greater than 0 . You specified: %v ", parsedShm) |
|
208 |
+ return nil, nil, cmd, err |
|
213 | 209 |
} |
210 |
+ parsedShm = &shmSize |
|
214 | 211 |
} |
215 | 212 |
|
216 | 213 |
var binds []string |
... | ... |
@@ -525,16 +525,16 @@ func TestParseModes(t *testing.T) { |
525 | 525 |
t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode) |
526 | 526 |
} |
527 | 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) |
|
528 |
+ if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != "invalid size: 'a128m'" { |
|
529 |
+ t.Fatalf("Expected an error with message 'invalid size: a128m', got %v", err) |
|
530 | 530 |
} |
531 | 531 |
// shm-size ok |
532 | 532 |
_, hostconfig, _, err = parseRun([]string{"--shm-size=128m", "img", "cmd"}) |
533 | 533 |
if err != nil { |
534 | 534 |
t.Fatal(err) |
535 | 535 |
} |
536 |
- if hostconfig.ShmSize != 134217728 { |
|
537 |
- t.Fatalf("Expected a valid ShmSize, got %v", hostconfig.ShmSize) |
|
536 |
+ if *hostconfig.ShmSize != 134217728 { |
|
537 |
+ t.Fatalf("Expected a valid ShmSize, got %d", *hostconfig.ShmSize) |
|
538 | 538 |
} |
539 | 539 |
} |
540 | 540 |
|