diff --git a/daemon/create.go b/daemon/create.go index 166af3bf73..ca9e2c760c 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -21,7 +21,7 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig } - warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config) + warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false) if err != nil { return types.ContainerCreateResponse{Warnings: warnings}, err } diff --git a/daemon/daemon.go b/daemon/daemon.go index 8066a802d8..c2b2d884b9 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -1450,7 +1450,7 @@ func setDefaultMtu(config *Config) { // verifyContainerSettings performs validation of the hostconfig and config // structures. -func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { +func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { // First perform verification of settings common across all platforms. if config != nil { @@ -1487,7 +1487,7 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon } // Now do platform-specific verification - return verifyPlatformContainerSettings(daemon, hostConfig, config) + return verifyPlatformContainerSettings(daemon, hostConfig, config, update) } // Checks if the client set configurations for more than one network while creating a container diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index c15621d131..ca0d50f67f 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -221,7 +221,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf return nil } -func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) { +func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) { warnings := []string{} // memory subsystem checks and adjustments @@ -242,7 +242,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi if resources.Memory > 0 && resources.MemorySwap > 0 && resources.MemorySwap < resources.Memory { return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") } - if resources.Memory == 0 && resources.MemorySwap > 0 { + if resources.Memory == 0 && resources.MemorySwap > 0 && !update { return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") } if resources.MemorySwappiness != nil && *resources.MemorySwappiness != -1 && !sysInfo.MemorySwappiness { @@ -383,7 +383,7 @@ func (daemon *Daemon) usingSystemd() bool { // verifyPlatformContainerSettings performs platform-specific validation of the // hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { +func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { warnings := []string{} sysInfo := sysinfo.New(true) @@ -392,7 +392,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. return warnings, err } - w, err := verifyContainerResources(&hostConfig.Resources, sysInfo) + w, err := verifyContainerResources(&hostConfig.Resources, sysInfo, update) if err != nil { return warnings, err } diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index b4a6310475..609506f7b1 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -85,7 +85,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf // verifyPlatformContainerSettings performs platform-specific validation of the // hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { +func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { return nil, nil } diff --git a/daemon/start.go b/daemon/start.go index b467da6b6f..bf697442d5 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -58,7 +58,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos // check if hostConfig is in line with the current system settings. // It may happen cgroups are umounted or the like. - if _, err = daemon.verifyContainerSettings(container.HostConfig, nil); err != nil { + if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil { return err } // Adapt for old containers in case we have updates in this function and diff --git a/daemon/update.go b/daemon/update.go index dab1a8ccb1..f89d914278 100644 --- a/daemon/update.go +++ b/daemon/update.go @@ -12,7 +12,7 @@ import ( func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) { var warnings []string - warnings, err := daemon.verifyContainerSettings(hostConfig, nil) + warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true) if err != nil { return warnings, err } diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index bb261e8bec..3bdb17210a 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -139,6 +139,22 @@ func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) { c.Assert(strings.TrimSpace(out), checker.Equals, "104857600") } +func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) { + testRequires(c, DaemonIsLinux) + testRequires(c, memoryLimitSupport) + testRequires(c, swapMemorySupport) + + name := "test-update-container" + dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top") + dockerCmd(c, "update", "--memory-swap", "600M", name) + + c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600") + + file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes" + out, _ := dockerCmd(c, "exec", name, "cat", file) + c.Assert(strings.TrimSpace(out), checker.Equals, "629145600") +} + func (s *DockerSuite) TestUpdateStats(c *check.C) { testRequires(c, DaemonIsLinux) testRequires(c, memoryLimitSupport)