Add daemon option `--default-shm-size`
| ... | ... |
@@ -106,7 +106,7 @@ type containerOptions struct {
|
| 106 | 106 |
stopSignal string |
| 107 | 107 |
stopTimeout int |
| 108 | 108 |
isolation string |
| 109 |
- shmSize string |
|
| 109 |
+ shmSize opts.MemBytes |
|
| 110 | 110 |
noHealthcheck bool |
| 111 | 111 |
healthCmd string |
| 112 | 112 |
healthInterval time.Duration |
| ... | ... |
@@ -270,7 +270,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
| 270 | 270 |
flags.StringVar(&copts.ipcMode, "ipc", "", "IPC namespace to use") |
| 271 | 271 |
flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology") |
| 272 | 272 |
flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use") |
| 273 |
- flags.StringVar(&copts.shmSize, "shm-size", "", "Size of /dev/shm, default value is 64MB") |
|
| 273 |
+ flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm") |
|
| 274 | 274 |
flags.StringVar(&copts.utsMode, "uts", "", "UTS namespace to use") |
| 275 | 275 |
flags.StringVar(&copts.runtime, "runtime", "", "Runtime to use for this container") |
| 276 | 276 |
|
| ... | ... |
@@ -349,14 +349,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*container.Config, *c |
| 349 | 349 |
return nil, nil, nil, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
|
| 350 | 350 |
} |
| 351 | 351 |
|
| 352 |
- var shmSize int64 |
|
| 353 |
- if copts.shmSize != "" {
|
|
| 354 |
- shmSize, err = units.RAMInBytes(copts.shmSize) |
|
| 355 |
- if err != nil {
|
|
| 356 |
- return nil, nil, nil, err |
|
| 357 |
- } |
|
| 358 |
- } |
|
| 359 |
- |
|
| 360 | 352 |
// TODO FIXME units.RAMInBytes should have a uint64 version |
| 361 | 353 |
var maxIOBandwidth int64 |
| 362 | 354 |
if copts.ioMaxBandwidth != "" {
|
| ... | ... |
@@ -629,7 +621,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*container.Config, *c |
| 629 | 629 |
LogConfig: container.LogConfig{Type: copts.loggingDriver, Config: loggingOpts},
|
| 630 | 630 |
VolumeDriver: copts.volumeDriver, |
| 631 | 631 |
Isolation: container.Isolation(copts.isolation), |
| 632 |
- ShmSize: shmSize, |
|
| 632 |
+ ShmSize: copts.shmSize.Value(), |
|
| 633 | 633 |
Resources: resources, |
| 634 | 634 |
Tmpfs: tmpfs, |
| 635 | 635 |
Sysctls: copts.sysctls.GetAll(), |
| ... | ... |
@@ -411,8 +411,9 @@ func TestParseModes(t *testing.T) {
|
| 411 | 411 |
t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode)
|
| 412 | 412 |
} |
| 413 | 413 |
// shm-size ko |
| 414 |
- if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != "invalid size: 'a128m'" {
|
|
| 415 |
- t.Fatalf("Expected an error with message 'invalid size: a128m', got %v", err)
|
|
| 414 |
+ expectedErr := `invalid argument "a128m" for --shm-size=a128m: invalid size: 'a128m'` |
|
| 415 |
+ if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != expectedErr {
|
|
| 416 |
+ t.Fatalf("Expected an error with message '%v', got %v", expectedErr, err)
|
|
| 416 | 417 |
} |
| 417 | 418 |
// shm-size ok |
| 418 | 419 |
_, hostconfig, _, err = parseRun([]string{"--shm-size=128m", "img", "cmd"})
|
| ... | ... |
@@ -41,7 +41,7 @@ type buildOptions struct {
|
| 41 | 41 |
ulimits *opts.UlimitOpt |
| 42 | 42 |
memory string |
| 43 | 43 |
memorySwap string |
| 44 |
- shmSize string |
|
| 44 |
+ shmSize opts.MemBytes |
|
| 45 | 45 |
cpuShares int64 |
| 46 | 46 |
cpuPeriod int64 |
| 47 | 47 |
cpuQuota int64 |
| ... | ... |
@@ -89,7 +89,7 @@ func NewBuildCommand(dockerCli *command.DockerCli) *cobra.Command {
|
| 89 | 89 |
flags.StringVarP(&options.dockerfileName, "file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')") |
| 90 | 90 |
flags.StringVarP(&options.memory, "memory", "m", "", "Memory limit") |
| 91 | 91 |
flags.StringVar(&options.memorySwap, "memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") |
| 92 |
- flags.StringVar(&options.shmSize, "shm-size", "", "Size of /dev/shm, default value is 64MB") |
|
| 92 |
+ flags.Var(&options.shmSize, "shm-size", "Size of /dev/shm") |
|
| 93 | 93 |
flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") |
| 94 | 94 |
flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit the CPU CFS (Completely Fair Scheduler) period") |
| 95 | 95 |
flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota") |
| ... | ... |
@@ -274,14 +274,6 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
|
| 274 | 274 |
} |
| 275 | 275 |
} |
| 276 | 276 |
|
| 277 |
- var shmSize int64 |
|
| 278 |
- if options.shmSize != "" {
|
|
| 279 |
- shmSize, err = units.RAMInBytes(options.shmSize) |
|
| 280 |
- if err != nil {
|
|
| 281 |
- return err |
|
| 282 |
- } |
|
| 283 |
- } |
|
| 284 |
- |
|
| 285 | 277 |
authConfigs, _ := dockerCli.GetAllCredentials() |
| 286 | 278 |
buildOptions := types.ImageBuildOptions{
|
| 287 | 279 |
Memory: memory, |
| ... | ... |
@@ -300,7 +292,7 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
|
| 300 | 300 |
CPUPeriod: options.cpuPeriod, |
| 301 | 301 |
CgroupParent: options.cgroupParent, |
| 302 | 302 |
Dockerfile: relDockerfile, |
| 303 |
- ShmSize: shmSize, |
|
| 303 |
+ ShmSize: options.shmSize.Value(), |
|
| 304 | 304 |
Ulimits: options.ulimits.GetList(), |
| 305 | 305 |
BuildArgs: runconfigopts.ConvertKVStringsToMapWithNil(options.buildArgs.GetAll()), |
| 306 | 306 |
AuthConfigs: authConfigs, |
| ... | ... |
@@ -11,7 +11,6 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/opts" |
| 12 | 12 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
| 13 | 13 |
"github.com/docker/go-connections/nat" |
| 14 |
- units "github.com/docker/go-units" |
|
| 15 | 14 |
"github.com/spf13/cobra" |
| 16 | 15 |
) |
| 17 | 16 |
|
| ... | ... |
@@ -19,26 +18,6 @@ type int64Value interface {
|
| 19 | 19 |
Value() int64 |
| 20 | 20 |
} |
| 21 | 21 |
|
| 22 |
-type memBytes int64 |
|
| 23 |
- |
|
| 24 |
-func (m *memBytes) String() string {
|
|
| 25 |
- return units.BytesSize(float64(m.Value())) |
|
| 26 |
-} |
|
| 27 |
- |
|
| 28 |
-func (m *memBytes) Set(value string) error {
|
|
| 29 |
- val, err := units.RAMInBytes(value) |
|
| 30 |
- *m = memBytes(val) |
|
| 31 |
- return err |
|
| 32 |
-} |
|
| 33 |
- |
|
| 34 |
-func (m *memBytes) Type() string {
|
|
| 35 |
- return "bytes" |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (m *memBytes) Value() int64 {
|
|
| 39 |
- return int64(*m) |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 | 22 |
// PositiveDurationOpt is an option type for time.Duration that uses a pointer. |
| 43 | 23 |
// It bahave similarly to DurationOpt but only allows positive duration values. |
| 44 | 24 |
type PositiveDurationOpt struct {
|
| ... | ... |
@@ -149,9 +128,9 @@ type updateOptions struct {
|
| 149 | 149 |
|
| 150 | 150 |
type resourceOptions struct {
|
| 151 | 151 |
limitCPU opts.NanoCPUs |
| 152 |
- limitMemBytes memBytes |
|
| 152 |
+ limitMemBytes opts.MemBytes |
|
| 153 | 153 |
resCPU opts.NanoCPUs |
| 154 |
- resMemBytes memBytes |
|
| 154 |
+ resMemBytes opts.MemBytes |
|
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
func (r *resourceOptions) ToResourceRequirements() *swarm.ResourceRequirements {
|
| ... | ... |
@@ -11,12 +11,12 @@ import ( |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 | 13 |
func TestMemBytesString(t *testing.T) {
|
| 14 |
- var mem memBytes = 1048576 |
|
| 14 |
+ var mem opts.MemBytes = 1048576 |
|
| 15 | 15 |
assert.Equal(t, mem.String(), "1 MiB") |
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 | 18 |
func TestMemBytesSetAndValue(t *testing.T) {
|
| 19 |
- var mem memBytes |
|
| 19 |
+ var mem opts.MemBytes |
|
| 20 | 20 |
assert.NilError(t, mem.Set("5kb"))
|
| 21 | 21 |
assert.Equal(t, mem.Value(), int64(5120)) |
| 22 | 22 |
} |
| ... | ... |
@@ -22,9 +22,7 @@ import ( |
| 22 | 22 |
) |
| 23 | 23 |
|
| 24 | 24 |
const ( |
| 25 |
- // DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container |
|
| 26 |
- DefaultSHMSize int64 = 67108864 |
|
| 27 |
- containerSecretMountPath = "/run/secrets" |
|
| 25 |
+ containerSecretMountPath = "/run/secrets" |
|
| 28 | 26 |
) |
| 29 | 27 |
|
| 30 | 28 |
// Container holds the fields specific to unixen implementations. |
| ... | ... |
@@ -14,6 +14,7 @@ var ( |
| 14 | 14 |
defaultPidFile = "/var/run/docker.pid" |
| 15 | 15 |
defaultGraph = "/var/lib/docker" |
| 16 | 16 |
defaultExecRoot = "/var/run/docker" |
| 17 |
+ defaultShmSize = int64(67108864) |
|
| 17 | 18 |
) |
| 18 | 19 |
|
| 19 | 20 |
// Config defines the configuration of a docker daemon. |
| ... | ... |
@@ -36,6 +37,7 @@ type Config struct {
|
| 36 | 36 |
Init bool `json:"init,omitempty"` |
| 37 | 37 |
InitPath string `json:"init-path,omitempty"` |
| 38 | 38 |
SeccompProfile string `json:"seccomp-profile,omitempty"` |
| 39 |
+ ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` |
|
| 39 | 40 |
} |
| 40 | 41 |
|
| 41 | 42 |
// bridgeConfig stores all the bridge driver specific |
| ... | ... |
@@ -66,6 +68,9 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
|
| 66 | 66 |
|
| 67 | 67 |
config.Ulimits = make(map[string]*units.Ulimit) |
| 68 | 68 |
|
| 69 |
+ // Set default value for `--default-shm-size` |
|
| 70 |
+ config.ShmSize = opts.MemBytes(defaultShmSize) |
|
| 71 |
+ |
|
| 69 | 72 |
// Then platform-specific install flags |
| 70 | 73 |
flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support") |
| 71 | 74 |
flags.Var(opts.NewUlimitOpt(&config.Ulimits), "default-ulimit", "Default ulimits for containers") |
| ... | ... |
@@ -89,6 +94,7 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
|
| 89 | 89 |
flags.Int64Var(&config.CPURealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") |
| 90 | 90 |
flags.Int64Var(&config.CPURealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") |
| 91 | 91 |
flags.StringVar(&config.SeccompProfile, "seccomp-profile", "", "Path to seccomp profile") |
| 92 |
+ flags.Var(&config.ShmSize, "default-shm-size", "Default shm size for containers") |
|
| 92 | 93 |
|
| 93 | 94 |
config.attachExperimentalFlags(flags) |
| 94 | 95 |
} |
| ... | ... |
@@ -4,7 +4,12 @@ package daemon |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"io/ioutil" |
| 7 |
+ "runtime" |
|
| 8 |
+ |
|
| 7 | 9 |
"testing" |
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/pkg/testutil/assert" |
|
| 12 |
+ "github.com/spf13/pflag" |
|
| 8 | 13 |
) |
| 9 | 14 |
|
| 10 | 15 |
func TestDaemonConfigurationMerge(t *testing.T) {
|
| ... | ... |
@@ -78,3 +83,52 @@ func TestDaemonConfigurationMerge(t *testing.T) {
|
| 78 | 78 |
} |
| 79 | 79 |
} |
| 80 | 80 |
} |
| 81 |
+ |
|
| 82 |
+func TestDaemonParseShmSize(t *testing.T) {
|
|
| 83 |
+ if runtime.GOOS == "solaris" {
|
|
| 84 |
+ t.Skip("ShmSize not supported on Solaris\n")
|
|
| 85 |
+ } |
|
| 86 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 87 |
+ |
|
| 88 |
+ config := &Config{}
|
|
| 89 |
+ config.InstallFlags(flags) |
|
| 90 |
+ // By default `--default-shm-size=64M` |
|
| 91 |
+ expectedValue := 64 * 1024 * 1024 |
|
| 92 |
+ if config.ShmSize.Value() != int64(expectedValue) {
|
|
| 93 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value())
|
|
| 94 |
+ } |
|
| 95 |
+ assert.NilError(t, flags.Set("default-shm-size", "128M"))
|
|
| 96 |
+ expectedValue = 128 * 1024 * 1024 |
|
| 97 |
+ if config.ShmSize.Value() != int64(expectedValue) {
|
|
| 98 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value())
|
|
| 99 |
+ } |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 102 |
+func TestDaemonConfigurationMergeShmSize(t *testing.T) {
|
|
| 103 |
+ if runtime.GOOS == "solaris" {
|
|
| 104 |
+ t.Skip("ShmSize not supported on Solaris\n")
|
|
| 105 |
+ } |
|
| 106 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 107 |
+ if err != nil {
|
|
| 108 |
+ t.Fatal(err) |
|
| 109 |
+ } |
|
| 110 |
+ |
|
| 111 |
+ configFile := f.Name() |
|
| 112 |
+ |
|
| 113 |
+ f.Write([]byte(` |
|
| 114 |
+ {
|
|
| 115 |
+ "default-shm-size": "1g" |
|
| 116 |
+ }`)) |
|
| 117 |
+ |
|
| 118 |
+ f.Close() |
|
| 119 |
+ |
|
| 120 |
+ c := &Config{}
|
|
| 121 |
+ cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ t.Fatal(err) |
|
| 124 |
+ } |
|
| 125 |
+ expectedValue := 1 * 1024 * 1024 * 1024 |
|
| 126 |
+ if cc.ShmSize.Value() != int64(expectedValue) {
|
|
| 127 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, cc.ShmSize.Value())
|
|
| 128 |
+ } |
|
| 129 |
+} |
| ... | ... |
@@ -117,7 +117,7 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
| 117 | 117 |
return err |
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 |
- shmSize := container.DefaultSHMSize |
|
| 120 |
+ shmSize := int64(daemon.configStore.ShmSize) |
|
| 121 | 121 |
if c.HostConfig.ShmSize != 0 {
|
| 122 | 122 |
shmSize = c.HostConfig.ShmSize |
| 123 | 123 |
} |
| ... | ... |
@@ -256,7 +256,10 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf |
| 256 | 256 |
hostConfig.MemorySwap = hostConfig.Memory * 2 |
| 257 | 257 |
} |
| 258 | 258 |
if hostConfig.ShmSize == 0 {
|
| 259 |
- hostConfig.ShmSize = container.DefaultSHMSize |
|
| 259 |
+ hostConfig.ShmSize = defaultShmSize |
|
| 260 |
+ if daemon.configStore != nil {
|
|
| 261 |
+ hostConfig.ShmSize = int64(daemon.configStore.ShmSize) |
|
| 262 |
+ } |
|
| 260 | 263 |
} |
| 261 | 264 |
var err error |
| 262 | 265 |
opts, err := daemon.generateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode, hostConfig.Privileged) |
| ... | ... |
@@ -576,6 +579,10 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
| 576 | 576 |
daemon.configStore.DefaultRuntime = config.DefaultRuntime |
| 577 | 577 |
} |
| 578 | 578 |
|
| 579 |
+ if config.IsValueSet("default-shm-size") {
|
|
| 580 |
+ daemon.configStore.ShmSize = config.ShmSize |
|
| 581 |
+ } |
|
| 582 |
+ |
|
| 579 | 583 |
// Update attributes |
| 580 | 584 |
var runtimeList bytes.Buffer |
| 581 | 585 |
for name, rt := range daemon.configStore.Runtimes {
|
| ... | ... |
@@ -586,8 +593,9 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
| 586 | 586 |
} |
| 587 | 587 |
|
| 588 | 588 |
return map[string]string{
|
| 589 |
- "runtimes": runtimeList.String(), |
|
| 590 |
- "default-runtime": daemon.configStore.DefaultRuntime, |
|
| 589 |
+ "runtimes": runtimeList.String(), |
|
| 590 |
+ "default-runtime": daemon.configStore.DefaultRuntime, |
|
| 591 |
+ "default-shm-size": fmt.Sprintf("%d", daemon.configStore.ShmSize),
|
|
| 591 | 592 |
} |
| 592 | 593 |
} |
| 593 | 594 |
|
| ... | ... |
@@ -49,7 +49,7 @@ Options: |
| 49 | 49 |
-q, --quiet Suppress the build output and print image ID on success |
| 50 | 50 |
--rm Remove intermediate containers after a successful build (default true) |
| 51 | 51 |
--security-opt value Security Options (default []) |
| 52 |
- --shm-size string Size of /dev/shm, default value is 64MB. |
|
| 52 |
+ --shm-size bytes Size of /dev/shm |
|
| 53 | 53 |
The format is `<number><unit>`. `number` must be greater than `0`. |
| 54 | 54 |
Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), |
| 55 | 55 |
or `g` (gigabytes). If you omit the unit, the system uses bytes. |
| ... | ... |
@@ -107,7 +107,7 @@ Options: |
| 107 | 107 |
--rm Automatically remove the container when it exits |
| 108 | 108 |
--runtime string Runtime to use for this container |
| 109 | 109 |
--security-opt value Security Options (default []) |
| 110 |
- --shm-size string Size of /dev/shm, default value is 64MB. |
|
| 110 |
+ --shm-size bytes Size of /dev/shm |
|
| 111 | 111 |
The format is `<number><unit>`. `number` must be greater than `0`. |
| 112 | 112 |
Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), |
| 113 | 113 |
or `g` (gigabytes). If you omit the unit, the system uses bytes. |
| ... | ... |
@@ -37,6 +37,7 @@ Options: |
| 37 | 37 |
--default-gateway value Container default gateway IPv4 address |
| 38 | 38 |
--default-gateway-v6 value Container default gateway IPv6 address |
| 39 | 39 |
--default-runtime string Default OCI runtime for containers (default "runc") |
| 40 |
+ --default-shm-size bytes Set the default shm size for containers (default 64 MiB) |
|
| 40 | 41 |
--default-ulimit value Default ulimits for containers (default []) |
| 41 | 42 |
--disable-legacy-registry Disable contacting legacy registries |
| 42 | 43 |
--dns value DNS server to use (default []) |
| ... | ... |
@@ -1161,6 +1162,7 @@ This is a full example of the allowed configuration options on Linux: |
| 1161 | 1161 |
"cluster-advertise": "", |
| 1162 | 1162 |
"max-concurrent-downloads": 3, |
| 1163 | 1163 |
"max-concurrent-uploads": 5, |
| 1164 |
+ "default-shm-size": "64M", |
|
| 1164 | 1165 |
"shutdown-timeout": 15, |
| 1165 | 1166 |
"debug": true, |
| 1166 | 1167 |
"hosts": [], |
| ... | ... |
@@ -117,7 +117,7 @@ Options: |
| 117 | 117 |
--rm Automatically remove the container when it exits |
| 118 | 118 |
--runtime string Runtime to use for this container |
| 119 | 119 |
--security-opt value Security Options (default []) |
| 120 |
- --shm-size string Size of /dev/shm, default value is 64MB. |
|
| 120 |
+ --shm-size bytes Size of /dev/shm |
|
| 121 | 121 |
The format is `<number><unit>`. `number` must be greater than `0`. |
| 122 | 122 |
Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), |
| 123 | 123 |
or `g` (gigabytes). If you omit the unit, the system uses bytes. |
| ... | ... |
@@ -39,7 +39,7 @@ Options: |
| 39 | 39 |
--hostname string Container hostname |
| 40 | 40 |
-l, --label list Service labels (default []) |
| 41 | 41 |
--limit-cpu decimal Limit CPUs (default 0.000) |
| 42 |
- --limit-memory bytes Limit Memory (default 0 B) |
|
| 42 |
+ --limit-memory bytes Limit Memory |
|
| 43 | 43 |
--log-driver string Logging driver for service |
| 44 | 44 |
--log-opt list Logging driver options (default []) |
| 45 | 45 |
--mode string Service mode (replicated or global) (default "replicated") |
| ... | ... |
@@ -51,7 +51,7 @@ Options: |
| 51 | 51 |
--read-only Mount the container's root filesystem as read only |
| 52 | 52 |
--replicas uint Number of tasks |
| 53 | 53 |
--reserve-cpu decimal Reserve CPUs (default 0.000) |
| 54 |
- --reserve-memory bytes Reserve Memory (default 0 B) |
|
| 54 |
+ --reserve-memory bytes Reserve Memory |
|
| 55 | 55 |
--restart-condition string Restart when condition is met (none, on-failure, or any) |
| 56 | 56 |
--restart-delay duration Delay between restart attempts (ns|us|ms|s|m|h) |
| 57 | 57 |
--restart-max-attempts uint Maximum number of restarts before giving up |
| ... | ... |
@@ -50,7 +50,7 @@ Options: |
| 50 | 50 |
--label-add list Add or update a service label (default []) |
| 51 | 51 |
--label-rm list Remove a label by its key (default []) |
| 52 | 52 |
--limit-cpu decimal Limit CPUs (default 0.000) |
| 53 |
- --limit-memory bytes Limit Memory (default 0 B) |
|
| 53 |
+ --limit-memory bytes Limit Memory |
|
| 54 | 54 |
--log-driver string Logging driver for service |
| 55 | 55 |
--log-opt list Logging driver options (default []) |
| 56 | 56 |
--mount-add mount Add or update a mount on a service |
| ... | ... |
@@ -61,7 +61,7 @@ Options: |
| 61 | 61 |
--read-only Mount the container's root filesystem as read only |
| 62 | 62 |
--replicas uint Number of tasks |
| 63 | 63 |
--reserve-cpu decimal Reserve CPUs (default 0.000) |
| 64 |
- --reserve-memory bytes Reserve Memory (default 0 B) |
|
| 64 |
+ --reserve-memory bytes Reserve Memory |
|
| 65 | 65 |
--restart-condition string Restart when condition is met (none, on-failure, or any) |
| 66 | 66 |
--restart-delay duration Delay between restart attempts (ns|us|ms|s|m|h) |
| 67 | 67 |
--restart-max-attempts uint Maximum number of restarts before giving up |
| ... | ... |
@@ -2879,3 +2879,60 @@ func (s *DockerDaemonSuite) TestRestartPolicyWithLiveRestore(c *check.C) {
|
| 2879 | 2879 |
out, err = s.d.Cmd("stop", id)
|
| 2880 | 2880 |
c.Assert(err, check.IsNil, check.Commentf("output: %s", out))
|
| 2881 | 2881 |
} |
| 2882 |
+ |
|
| 2883 |
+func (s *DockerDaemonSuite) TestShmSize(c *check.C) {
|
|
| 2884 |
+ testRequires(c, DaemonIsLinux) |
|
| 2885 |
+ |
|
| 2886 |
+ size := 67108864 * 2 |
|
| 2887 |
+ pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
|
|
| 2888 |
+ |
|
| 2889 |
+ s.d.StartWithBusybox(c, "--default-shm-size", fmt.Sprintf("%v", size))
|
|
| 2890 |
+ |
|
| 2891 |
+ name := "shm1" |
|
| 2892 |
+ out, err := s.d.Cmd("run", "--name", name, "busybox", "mount")
|
|
| 2893 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2894 |
+ c.Assert(pattern.MatchString(out), checker.True) |
|
| 2895 |
+ out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name)
|
|
| 2896 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2897 |
+ c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size))
|
|
| 2898 |
+} |
|
| 2899 |
+ |
|
| 2900 |
+func (s *DockerDaemonSuite) TestShmSizeReload(c *check.C) {
|
|
| 2901 |
+ testRequires(c, DaemonIsLinux) |
|
| 2902 |
+ |
|
| 2903 |
+ configPath, err := ioutil.TempDir("", "test-daemon-shm-size-reload-config")
|
|
| 2904 |
+ c.Assert(err, checker.IsNil, check.Commentf("could not create temp file for config reload"))
|
|
| 2905 |
+ defer os.RemoveAll(configPath) // clean up |
|
| 2906 |
+ configFile := filepath.Join(configPath, "config.json") |
|
| 2907 |
+ |
|
| 2908 |
+ size := 67108864 * 2 |
|
| 2909 |
+ configData := []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024))
|
|
| 2910 |
+ c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload"))
|
|
| 2911 |
+ pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
|
|
| 2912 |
+ |
|
| 2913 |
+ s.d.StartWithBusybox(c, "--config-file", configFile) |
|
| 2914 |
+ |
|
| 2915 |
+ name := "shm1" |
|
| 2916 |
+ out, err := s.d.Cmd("run", "--name", name, "busybox", "mount")
|
|
| 2917 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2918 |
+ c.Assert(pattern.MatchString(out), checker.True) |
|
| 2919 |
+ out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name)
|
|
| 2920 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2921 |
+ c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size))
|
|
| 2922 |
+ |
|
| 2923 |
+ size = 67108864 * 3 |
|
| 2924 |
+ configData = []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024))
|
|
| 2925 |
+ c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload"))
|
|
| 2926 |
+ pattern = regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
|
|
| 2927 |
+ |
|
| 2928 |
+ err = s.d.ReloadConfig() |
|
| 2929 |
+ c.Assert(err, checker.IsNil, check.Commentf("error reloading daemon config"))
|
|
| 2930 |
+ |
|
| 2931 |
+ name = "shm2" |
|
| 2932 |
+ out, err = s.d.Cmd("run", "--name", name, "busybox", "mount")
|
|
| 2933 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2934 |
+ c.Assert(pattern.MatchString(out), checker.True) |
|
| 2935 |
+ out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name)
|
|
| 2936 |
+ c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
| 2937 |
+ c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size))
|
|
| 2938 |
+} |
| ... | ... |
@@ -427,7 +427,7 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) {
|
| 427 | 427 |
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c))
|
| 428 | 428 |
c.Assert(err, checker.IsNil) |
| 429 | 429 |
|
| 430 |
- c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, default-runtime=runc, insecure-registries=[], labels=[\"bar=foo\"], live-restore=false, max-concurrent-downloads=1, max-concurrent-uploads=5, name=%s, registry-mirrors=[], runtimes=runc:{docker-runc []}, shutdown-timeout=10)", daemonID, daemonName))
|
|
| 430 |
+ c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, default-runtime=runc, default-shm-size=67108864, insecure-registries=[], labels=[\"bar=foo\"], live-restore=false, max-concurrent-downloads=1, max-concurrent-uploads=5, name=%s, registry-mirrors=[], runtimes=runc:{docker-runc []}, shutdown-timeout=10)", daemonID, daemonName))
|
|
| 431 | 431 |
} |
| 432 | 432 |
|
| 433 | 433 |
func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(c *check.C) {
|
| ... | ... |
@@ -21,6 +21,7 @@ dockerd - Enable daemon mode |
| 21 | 21 |
[**--default-gateway**[=*DEFAULT-GATEWAY*]] |
| 22 | 22 |
[**--default-gateway-v6**[=*DEFAULT-GATEWAY-V6*]] |
| 23 | 23 |
[**--default-runtime**[=*runc*]] |
| 24 |
+[**--default-shm-size**[=*64MiB*]] |
|
| 24 | 25 |
[**--default-ulimit**[=*[]*]] |
| 25 | 26 |
[**--disable-legacy-registry**] |
| 26 | 27 |
[**--dns**[=*[]*]] |
| ... | ... |
@@ -164,6 +165,9 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru |
| 164 | 164 |
**--default-runtime**="runc" |
| 165 | 165 |
Set default runtime if there're more than one specified by `--add-runtime`. |
| 166 | 166 |
|
| 167 |
+**--default-shm-size**=*64MiB* |
|
| 168 |
+ Set the daemon-wide default shm size for containers. Default is `64MiB`. |
|
| 169 |
+ |
|
| 167 | 170 |
**--default-ulimit**=[] |
| 168 | 171 |
Default ulimits for containers. |
| 169 | 172 |
|
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/api/types/filters" |
| 12 |
+ units "github.com/docker/go-units" |
|
| 12 | 13 |
) |
| 13 | 14 |
|
| 14 | 15 |
var ( |
| ... | ... |
@@ -402,3 +403,44 @@ func ValidateLink(val string) (string, error) {
|
| 402 | 402 |
_, _, err := ParseLink(val) |
| 403 | 403 |
return val, err |
| 404 | 404 |
} |
| 405 |
+ |
|
| 406 |
+// MemBytes is a type for human readable memory bytes (like 128M, 2g, etc) |
|
| 407 |
+type MemBytes int64 |
|
| 408 |
+ |
|
| 409 |
+// String returns the string format of the human readable memory bytes |
|
| 410 |
+func (m *MemBytes) String() string {
|
|
| 411 |
+ // NOTE: In spf13/pflag/flag.go, "0" is considered as "zero value" while "0 B" is not. |
|
| 412 |
+ // We return "0" in case value is 0 here so that the default value is hidden. |
|
| 413 |
+ // (Sometimes "default 0 B" is actually misleading) |
|
| 414 |
+ if m.Value() != 0 {
|
|
| 415 |
+ return units.BytesSize(float64(m.Value())) |
|
| 416 |
+ } |
|
| 417 |
+ return "0" |
|
| 418 |
+} |
|
| 419 |
+ |
|
| 420 |
+// Set sets the value of the MemBytes by passing a string |
|
| 421 |
+func (m *MemBytes) Set(value string) error {
|
|
| 422 |
+ val, err := units.RAMInBytes(value) |
|
| 423 |
+ *m = MemBytes(val) |
|
| 424 |
+ return err |
|
| 425 |
+} |
|
| 426 |
+ |
|
| 427 |
+// Type returns the type |
|
| 428 |
+func (m *MemBytes) Type() string {
|
|
| 429 |
+ return "bytes" |
|
| 430 |
+} |
|
| 431 |
+ |
|
| 432 |
+// Value returns the value in int64 |
|
| 433 |
+func (m *MemBytes) Value() int64 {
|
|
| 434 |
+ return int64(*m) |
|
| 435 |
+} |
|
| 436 |
+ |
|
| 437 |
+// UnmarshalJSON is the customized unmarshaler for MemBytes |
|
| 438 |
+func (m *MemBytes) UnmarshalJSON(s []byte) error {
|
|
| 439 |
+ if len(s) <= 2 || s[0] != '"' || s[len(s)-1] != '"' {
|
|
| 440 |
+ return fmt.Errorf("invalid size: %q", s)
|
|
| 441 |
+ } |
|
| 442 |
+ val, err := units.RAMInBytes(string(s[1 : len(s)-1])) |
|
| 443 |
+ *m = MemBytes(val) |
|
| 444 |
+ return err |
|
| 445 |
+} |