diff --git a/cli/command/container/opts.go b/cli/command/container/opts.go index ff961aa3a4..560236a2c2 100644 --- a/cli/command/container/opts.go +++ b/cli/command/container/opts.go @@ -106,7 +106,7 @@ type containerOptions struct { stopSignal string stopTimeout int isolation string - shmSize string + shmSize opts.MemBytes noHealthcheck bool healthCmd string healthInterval time.Duration @@ -270,7 +270,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions { flags.StringVar(&copts.ipcMode, "ipc", "", "IPC namespace to use") flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology") flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use") - flags.StringVar(&copts.shmSize, "shm-size", "", "Size of /dev/shm, default value is 64MB") + flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm") flags.StringVar(&copts.utsMode, "uts", "", "UTS namespace to use") flags.StringVar(&copts.runtime, "runtime", "", "Runtime to use for this container") @@ -349,14 +349,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*container.Config, *c return nil, nil, nil, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness) } - var shmSize int64 - if copts.shmSize != "" { - shmSize, err = units.RAMInBytes(copts.shmSize) - if err != nil { - return nil, nil, nil, err - } - } - // TODO FIXME units.RAMInBytes should have a uint64 version var maxIOBandwidth int64 if copts.ioMaxBandwidth != "" { @@ -629,7 +621,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*container.Config, *c LogConfig: container.LogConfig{Type: copts.loggingDriver, Config: loggingOpts}, VolumeDriver: copts.volumeDriver, Isolation: container.Isolation(copts.isolation), - ShmSize: shmSize, + ShmSize: copts.shmSize.Value(), Resources: resources, Tmpfs: tmpfs, Sysctls: copts.sysctls.GetAll(), diff --git a/cli/command/container/opts_test.go b/cli/command/container/opts_test.go index ce3bb21b41..d0655069e9 100644 --- a/cli/command/container/opts_test.go +++ b/cli/command/container/opts_test.go @@ -411,8 +411,9 @@ func TestParseModes(t *testing.T) { t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode) } // shm-size ko - if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != "invalid size: 'a128m'" { - t.Fatalf("Expected an error with message 'invalid size: a128m', got %v", err) + expectedErr := `invalid argument "a128m" for --shm-size=a128m: invalid size: 'a128m'` + if _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}); err == nil || err.Error() != expectedErr { + t.Fatalf("Expected an error with message '%v', got %v", expectedErr, err) } // shm-size ok _, hostconfig, _, err = parseRun([]string{"--shm-size=128m", "img", "cmd"}) diff --git a/cli/command/image/build.go b/cli/command/image/build.go index ac2089e7bf..34e0a39500 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -41,7 +41,7 @@ type buildOptions struct { ulimits *opts.UlimitOpt memory string memorySwap string - shmSize string + shmSize opts.MemBytes cpuShares int64 cpuPeriod int64 cpuQuota int64 @@ -89,7 +89,7 @@ func NewBuildCommand(dockerCli *command.DockerCli) *cobra.Command { flags.StringVarP(&options.dockerfileName, "file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')") flags.StringVarP(&options.memory, "memory", "m", "", "Memory limit") flags.StringVar(&options.memorySwap, "memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") - flags.StringVar(&options.shmSize, "shm-size", "", "Size of /dev/shm, default value is 64MB") + flags.Var(&options.shmSize, "shm-size", "Size of /dev/shm") flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit the CPU CFS (Completely Fair Scheduler) period") 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 { } } - var shmSize int64 - if options.shmSize != "" { - shmSize, err = units.RAMInBytes(options.shmSize) - if err != nil { - return err - } - } - authConfigs, _ := dockerCli.GetAllCredentials() buildOptions := types.ImageBuildOptions{ Memory: memory, @@ -300,7 +292,7 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error { CPUPeriod: options.cpuPeriod, CgroupParent: options.cgroupParent, Dockerfile: relDockerfile, - ShmSize: shmSize, + ShmSize: options.shmSize.Value(), Ulimits: options.ulimits.GetList(), BuildArgs: runconfigopts.ConvertKVStringsToMapWithNil(options.buildArgs.GetAll()), AuthConfigs: authConfigs, diff --git a/cli/command/service/opts.go b/cli/command/service/opts.go index dcd52ac7a3..332d37e732 100644 --- a/cli/command/service/opts.go +++ b/cli/command/service/opts.go @@ -11,7 +11,6 @@ import ( "github.com/docker/docker/opts" runconfigopts "github.com/docker/docker/runconfig/opts" "github.com/docker/go-connections/nat" - units "github.com/docker/go-units" "github.com/spf13/cobra" ) @@ -19,26 +18,6 @@ type int64Value interface { Value() int64 } -type memBytes int64 - -func (m *memBytes) String() string { - return units.BytesSize(float64(m.Value())) -} - -func (m *memBytes) Set(value string) error { - val, err := units.RAMInBytes(value) - *m = memBytes(val) - return err -} - -func (m *memBytes) Type() string { - return "bytes" -} - -func (m *memBytes) Value() int64 { - return int64(*m) -} - // PositiveDurationOpt is an option type for time.Duration that uses a pointer. // It bahave similarly to DurationOpt but only allows positive duration values. type PositiveDurationOpt struct { @@ -149,9 +128,9 @@ type updateOptions struct { type resourceOptions struct { limitCPU opts.NanoCPUs - limitMemBytes memBytes + limitMemBytes opts.MemBytes resCPU opts.NanoCPUs - resMemBytes memBytes + resMemBytes opts.MemBytes } func (r *resourceOptions) ToResourceRequirements() *swarm.ResourceRequirements { diff --git a/cli/command/service/opts_test.go b/cli/command/service/opts_test.go index 78b956ad67..4031d6f251 100644 --- a/cli/command/service/opts_test.go +++ b/cli/command/service/opts_test.go @@ -11,12 +11,12 @@ import ( ) func TestMemBytesString(t *testing.T) { - var mem memBytes = 1048576 + var mem opts.MemBytes = 1048576 assert.Equal(t, mem.String(), "1 MiB") } func TestMemBytesSetAndValue(t *testing.T) { - var mem memBytes + var mem opts.MemBytes assert.NilError(t, mem.Set("5kb")) assert.Equal(t, mem.Value(), int64(5120)) } diff --git a/container/container_unix.go b/container/container_unix.go index d311b6c0bf..5c70eac6e7 100644 --- a/container/container_unix.go +++ b/container/container_unix.go @@ -22,9 +22,7 @@ import ( ) const ( - // DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container - DefaultSHMSize int64 = 67108864 - containerSecretMountPath = "/run/secrets" + containerSecretMountPath = "/run/secrets" ) // Container holds the fields specific to unixen implementations. diff --git a/daemon/config_unix.go b/daemon/config_unix.go index e0b5759de4..8f71c8e5e6 100644 --- a/daemon/config_unix.go +++ b/daemon/config_unix.go @@ -14,6 +14,7 @@ var ( defaultPidFile = "/var/run/docker.pid" defaultGraph = "/var/lib/docker" defaultExecRoot = "/var/run/docker" + defaultShmSize = int64(67108864) ) // Config defines the configuration of a docker daemon. @@ -36,6 +37,7 @@ type Config struct { Init bool `json:"init,omitempty"` InitPath string `json:"init-path,omitempty"` SeccompProfile string `json:"seccomp-profile,omitempty"` + ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` } // bridgeConfig stores all the bridge driver specific @@ -66,6 +68,9 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) { config.Ulimits = make(map[string]*units.Ulimit) + // Set default value for `--default-shm-size` + config.ShmSize = opts.MemBytes(defaultShmSize) + // Then platform-specific install flags flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support") flags.Var(opts.NewUlimitOpt(&config.Ulimits), "default-ulimit", "Default ulimits for containers") @@ -89,6 +94,7 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) { flags.Int64Var(&config.CPURealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") flags.Int64Var(&config.CPURealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") flags.StringVar(&config.SeccompProfile, "seccomp-profile", "", "Path to seccomp profile") + flags.Var(&config.ShmSize, "default-shm-size", "Default shm size for containers") config.attachExperimentalFlags(flags) } diff --git a/daemon/config_unix_test.go b/daemon/config_unix_test.go index 86c16f57ba..9e73bf430b 100644 --- a/daemon/config_unix_test.go +++ b/daemon/config_unix_test.go @@ -4,7 +4,12 @@ package daemon import ( "io/ioutil" + "runtime" + "testing" + + "github.com/docker/docker/pkg/testutil/assert" + "github.com/spf13/pflag" ) func TestDaemonConfigurationMerge(t *testing.T) { @@ -78,3 +83,52 @@ func TestDaemonConfigurationMerge(t *testing.T) { } } } + +func TestDaemonParseShmSize(t *testing.T) { + if runtime.GOOS == "solaris" { + t.Skip("ShmSize not supported on Solaris\n") + } + flags := pflag.NewFlagSet("test", pflag.ContinueOnError) + + config := &Config{} + config.InstallFlags(flags) + // By default `--default-shm-size=64M` + expectedValue := 64 * 1024 * 1024 + if config.ShmSize.Value() != int64(expectedValue) { + t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value()) + } + assert.NilError(t, flags.Set("default-shm-size", "128M")) + expectedValue = 128 * 1024 * 1024 + if config.ShmSize.Value() != int64(expectedValue) { + t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value()) + } +} + +func TestDaemonConfigurationMergeShmSize(t *testing.T) { + if runtime.GOOS == "solaris" { + t.Skip("ShmSize not supported on Solaris\n") + } + f, err := ioutil.TempFile("", "docker-config-") + if err != nil { + t.Fatal(err) + } + + configFile := f.Name() + + f.Write([]byte(` + { + "default-shm-size": "1g" + }`)) + + f.Close() + + c := &Config{} + cc, err := MergeDaemonConfigurations(c, nil, configFile) + if err != nil { + t.Fatal(err) + } + expectedValue := 1 * 1024 * 1024 * 1024 + if cc.ShmSize.Value() != int64(expectedValue) { + t.Fatalf("expected default shm size %d, got %d", expectedValue, cc.ShmSize.Value()) + } +} diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 3856396487..c5e623cdd3 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -117,7 +117,7 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error { return err } - shmSize := container.DefaultSHMSize + shmSize := int64(daemon.configStore.ShmSize) if c.HostConfig.ShmSize != 0 { shmSize = c.HostConfig.ShmSize } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 8a2e6674bb..b048da2979 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -256,7 +256,10 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf hostConfig.MemorySwap = hostConfig.Memory * 2 } if hostConfig.ShmSize == 0 { - hostConfig.ShmSize = container.DefaultSHMSize + hostConfig.ShmSize = defaultShmSize + if daemon.configStore != nil { + hostConfig.ShmSize = int64(daemon.configStore.ShmSize) + } } var err error opts, err := daemon.generateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode, hostConfig.Privileged) @@ -576,6 +579,10 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string { daemon.configStore.DefaultRuntime = config.DefaultRuntime } + if config.IsValueSet("default-shm-size") { + daemon.configStore.ShmSize = config.ShmSize + } + // Update attributes var runtimeList bytes.Buffer for name, rt := range daemon.configStore.Runtimes { @@ -586,8 +593,9 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string { } return map[string]string{ - "runtimes": runtimeList.String(), - "default-runtime": daemon.configStore.DefaultRuntime, + "runtimes": runtimeList.String(), + "default-runtime": daemon.configStore.DefaultRuntime, + "default-shm-size": fmt.Sprintf("%d", daemon.configStore.ShmSize), } } diff --git a/docs/reference/commandline/build.md b/docs/reference/commandline/build.md index 2f8c59c387..5b6f1fec61 100644 --- a/docs/reference/commandline/build.md +++ b/docs/reference/commandline/build.md @@ -49,7 +49,7 @@ Options: -q, --quiet Suppress the build output and print image ID on success --rm Remove intermediate containers after a successful build (default true) --security-opt value Security Options (default []) - --shm-size string Size of /dev/shm, default value is 64MB. + --shm-size bytes Size of /dev/shm The format is ``. `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. diff --git a/docs/reference/commandline/create.md b/docs/reference/commandline/create.md index 3587e03fd0..cbb9598a78 100644 --- a/docs/reference/commandline/create.md +++ b/docs/reference/commandline/create.md @@ -107,7 +107,7 @@ Options: --rm Automatically remove the container when it exits --runtime string Runtime to use for this container --security-opt value Security Options (default []) - --shm-size string Size of /dev/shm, default value is 64MB. + --shm-size bytes Size of /dev/shm The format is ``. `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. diff --git a/docs/reference/commandline/dockerd.md b/docs/reference/commandline/dockerd.md index 80d776f91c..e4b5a33a87 100644 --- a/docs/reference/commandline/dockerd.md +++ b/docs/reference/commandline/dockerd.md @@ -37,6 +37,7 @@ Options: --default-gateway value Container default gateway IPv4 address --default-gateway-v6 value Container default gateway IPv6 address --default-runtime string Default OCI runtime for containers (default "runc") + --default-shm-size bytes Set the default shm size for containers (default 64 MiB) --default-ulimit value Default ulimits for containers (default []) --disable-legacy-registry Disable contacting legacy registries --dns value DNS server to use (default []) @@ -1161,6 +1162,7 @@ This is a full example of the allowed configuration options on Linux: "cluster-advertise": "", "max-concurrent-downloads": 3, "max-concurrent-uploads": 5, + "default-shm-size": "64M", "shutdown-timeout": 15, "debug": true, "hosts": [], diff --git a/docs/reference/commandline/run.md b/docs/reference/commandline/run.md index 3cddb9d374..837ba79b9e 100644 --- a/docs/reference/commandline/run.md +++ b/docs/reference/commandline/run.md @@ -117,7 +117,7 @@ Options: --rm Automatically remove the container when it exits --runtime string Runtime to use for this container --security-opt value Security Options (default []) - --shm-size string Size of /dev/shm, default value is 64MB. + --shm-size bytes Size of /dev/shm The format is ``. `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. diff --git a/docs/reference/commandline/service_create.md b/docs/reference/commandline/service_create.md index 08771272a7..9992996597 100644 --- a/docs/reference/commandline/service_create.md +++ b/docs/reference/commandline/service_create.md @@ -39,7 +39,7 @@ Options: --hostname string Container hostname -l, --label list Service labels (default []) --limit-cpu decimal Limit CPUs (default 0.000) - --limit-memory bytes Limit Memory (default 0 B) + --limit-memory bytes Limit Memory --log-driver string Logging driver for service --log-opt list Logging driver options (default []) --mode string Service mode (replicated or global) (default "replicated") @@ -51,7 +51,7 @@ Options: --read-only Mount the container's root filesystem as read only --replicas uint Number of tasks --reserve-cpu decimal Reserve CPUs (default 0.000) - --reserve-memory bytes Reserve Memory (default 0 B) + --reserve-memory bytes Reserve Memory --restart-condition string Restart when condition is met (none, on-failure, or any) --restart-delay duration Delay between restart attempts (ns|us|ms|s|m|h) --restart-max-attempts uint Maximum number of restarts before giving up diff --git a/docs/reference/commandline/service_update.md b/docs/reference/commandline/service_update.md index 654c59b875..0afbc3bb15 100644 --- a/docs/reference/commandline/service_update.md +++ b/docs/reference/commandline/service_update.md @@ -50,7 +50,7 @@ Options: --label-add list Add or update a service label (default []) --label-rm list Remove a label by its key (default []) --limit-cpu decimal Limit CPUs (default 0.000) - --limit-memory bytes Limit Memory (default 0 B) + --limit-memory bytes Limit Memory --log-driver string Logging driver for service --log-opt list Logging driver options (default []) --mount-add mount Add or update a mount on a service @@ -61,7 +61,7 @@ Options: --read-only Mount the container's root filesystem as read only --replicas uint Number of tasks --reserve-cpu decimal Reserve CPUs (default 0.000) - --reserve-memory bytes Reserve Memory (default 0 B) + --reserve-memory bytes Reserve Memory --restart-condition string Restart when condition is met (none, on-failure, or any) --restart-delay duration Delay between restart attempts (ns|us|ms|s|m|h) --restart-max-attempts uint Maximum number of restarts before giving up diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index dcc56ca162..e6c5ddb75d 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -2879,3 +2879,60 @@ func (s *DockerDaemonSuite) TestRestartPolicyWithLiveRestore(c *check.C) { out, err = s.d.Cmd("stop", id) c.Assert(err, check.IsNil, check.Commentf("output: %s", out)) } + +func (s *DockerDaemonSuite) TestShmSize(c *check.C) { + testRequires(c, DaemonIsLinux) + + size := 67108864 * 2 + pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) + + s.d.StartWithBusybox(c, "--default-shm-size", fmt.Sprintf("%v", size)) + + name := "shm1" + out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(pattern.MatchString(out), checker.True) + out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) +} + +func (s *DockerDaemonSuite) TestShmSizeReload(c *check.C) { + testRequires(c, DaemonIsLinux) + + configPath, err := ioutil.TempDir("", "test-daemon-shm-size-reload-config") + c.Assert(err, checker.IsNil, check.Commentf("could not create temp file for config reload")) + defer os.RemoveAll(configPath) // clean up + configFile := filepath.Join(configPath, "config.json") + + size := 67108864 * 2 + configData := []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) + c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload")) + pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) + + s.d.StartWithBusybox(c, "--config-file", configFile) + + name := "shm1" + out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(pattern.MatchString(out), checker.True) + out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) + + size = 67108864 * 3 + configData = []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) + c.Assert(ioutil.WriteFile(configFile, configData, 0666), checker.IsNil, check.Commentf("could not write temp file for config reload")) + pattern = regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) + + err = s.d.ReloadConfig() + c.Assert(err, checker.IsNil, check.Commentf("error reloading daemon config")) + + name = "shm2" + out, err = s.d.Cmd("run", "--name", name, "busybox", "mount") + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(pattern.MatchString(out), checker.True) + out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) + c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + c.Assert(strings.TrimSpace(out), check.Equals, fmt.Sprintf("%v", size)) +} diff --git a/integration-cli/docker_cli_events_unix_test.go b/integration-cli/docker_cli_events_unix_test.go index bbbef57ecd..39650d2372 100644 --- a/integration-cli/docker_cli_events_unix_test.go +++ b/integration-cli/docker_cli_events_unix_test.go @@ -427,7 +427,7 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) { out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c)) c.Assert(err, checker.IsNil) - 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)) + 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)) } func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(c *check.C) { diff --git a/man/dockerd.8.md b/man/dockerd.8.md index d64fe1f21e..24cec7fa98 100644 --- a/man/dockerd.8.md +++ b/man/dockerd.8.md @@ -21,6 +21,7 @@ dockerd - Enable daemon mode [**--default-gateway**[=*DEFAULT-GATEWAY*]] [**--default-gateway-v6**[=*DEFAULT-GATEWAY-V6*]] [**--default-runtime**[=*runc*]] +[**--default-shm-size**[=*64MiB*]] [**--default-ulimit**[=*[]*]] [**--disable-legacy-registry**] [**--dns**[=*[]*]] @@ -164,6 +165,9 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru **--default-runtime**="runc" Set default runtime if there're more than one specified by `--add-runtime`. +**--default-shm-size**=*64MiB* + Set the daemon-wide default shm size for containers. Default is `64MiB`. + **--default-ulimit**=[] Default ulimits for containers. diff --git a/opts/opts.go b/opts/opts.go index c0f9cebf60..3ae0fdb6b9 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/docker/docker/api/types/filters" + units "github.com/docker/go-units" ) var ( @@ -402,3 +403,44 @@ func ValidateLink(val string) (string, error) { _, _, err := ParseLink(val) return val, err } + +// MemBytes is a type for human readable memory bytes (like 128M, 2g, etc) +type MemBytes int64 + +// String returns the string format of the human readable memory bytes +func (m *MemBytes) String() string { + // NOTE: In spf13/pflag/flag.go, "0" is considered as "zero value" while "0 B" is not. + // We return "0" in case value is 0 here so that the default value is hidden. + // (Sometimes "default 0 B" is actually misleading) + if m.Value() != 0 { + return units.BytesSize(float64(m.Value())) + } + return "0" +} + +// Set sets the value of the MemBytes by passing a string +func (m *MemBytes) Set(value string) error { + val, err := units.RAMInBytes(value) + *m = MemBytes(val) + return err +} + +// Type returns the type +func (m *MemBytes) Type() string { + return "bytes" +} + +// Value returns the value in int64 +func (m *MemBytes) Value() int64 { + return int64(*m) +} + +// UnmarshalJSON is the customized unmarshaler for MemBytes +func (m *MemBytes) UnmarshalJSON(s []byte) error { + if len(s) <= 2 || s[0] != '"' || s[len(s)-1] != '"' { + return fmt.Errorf("invalid size: %q", s) + } + val, err := units.RAMInBytes(string(s[1 : len(s)-1])) + *m = MemBytes(val) + return err +}