diff --git a/api/client/build.go b/api/client/build.go index 63cc63bc9e..fb022e38d9 100644 --- a/api/client/build.go +++ b/api/client/build.go @@ -55,6 +55,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error { flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit") flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap") flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") + flCpuQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota") flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)") flCPUSetMems := cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)") @@ -281,6 +282,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error { v.Set("cpusetcpus", *flCPUSetCpus) v.Set("cpusetmems", *flCPUSetMems) v.Set("cpushares", strconv.FormatInt(*flCPUShares, 10)) + v.Set("cpuquota", strconv.FormatInt(*flCpuQuota, 10)) v.Set("memory", strconv.FormatInt(memory, 10)) v.Set("memswap", strconv.FormatInt(memorySwap, 10)) diff --git a/api/server/server.go b/api/server/server.go index 830e731a7e..cdc6c18154 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -1343,6 +1343,7 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R buildConfig.MemorySwap = int64Value(r, "memswap") buildConfig.Memory = int64Value(r, "memory") buildConfig.CpuShares = int64Value(r, "cpushares") + buildConfig.CpuQuota = int64Value(r, "cpuquota") buildConfig.CpuSetCpus = r.FormValue("cpusetcpus") buildConfig.CpuSetMems = r.FormValue("cpusetmems") diff --git a/builder/evaluator.go b/builder/evaluator.go index 2f9d4ff85b..9a2b57a8f9 100644 --- a/builder/evaluator.go +++ b/builder/evaluator.go @@ -124,6 +124,7 @@ type Builder struct { cpuSetCpus string cpuSetMems string cpuShares int64 + cpuQuota int64 memory int64 memorySwap int64 diff --git a/builder/internals.go b/builder/internals.go index 731ca84fed..ba7d45bcb1 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -547,6 +547,7 @@ func (b *Builder) create() (*daemon.Container, error) { hostConfig := &runconfig.HostConfig{ CpuShares: b.cpuShares, + CpuQuota: b.cpuQuota, CpusetCpus: b.cpuSetCpus, CpusetMems: b.cpuSetMems, Memory: b.memory, diff --git a/builder/job.go b/builder/job.go index 115d89a4b9..acffa8b460 100644 --- a/builder/job.go +++ b/builder/job.go @@ -49,6 +49,7 @@ type Config struct { Memory int64 MemorySwap int64 CpuShares int64 + CpuQuota int64 CpuSetCpus string CpuSetMems string AuthConfig *cliconfig.AuthConfig @@ -169,6 +170,7 @@ func Build(d *daemon.Daemon, buildConfig *Config) error { ConfigFile: buildConfig.ConfigFile, dockerfileName: buildConfig.DockerfileName, cpuShares: buildConfig.CpuShares, + cpuQuota: buildConfig.CpuQuota, cpuSetCpus: buildConfig.CpuSetCpus, cpuSetMems: buildConfig.CpuSetMems, memory: buildConfig.Memory, diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 7f87e50f5d..f3b8331587 100755 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -279,7 +279,7 @@ _docker_build() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--cpu-shares -c --cpuset-cpus --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--cpu-shares -c --cpuset-cpus --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) ) ;; *) local counter="$(__docker_pos_first_nonflag '--tag|-t')" diff --git a/docs/man/docker-build.1.md b/docs/man/docker-build.1.md index fe6250fc19..4a8eba67df 100644 --- a/docs/man/docker-build.1.md +++ b/docs/man/docker-build.1.md @@ -17,6 +17,7 @@ docker-build - Build a new image from the source code at PATH [**-m**|**--memory**[=*MEMORY*]] [**--memory-swap**[=*MEMORY-SWAP*]] [**-c**|**--cpu-shares**[=*0*]] +[**--cpu-quota**[=*0*]] [**--cpuset-cpus**[=*CPUSET-CPUS*]] PATH | URL | - diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 70e4ba114c..72d15c177b 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -5371,7 +5371,7 @@ func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { c.Fatal(err) } - cmd := exec.Command(dockerBinary, "build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "-t", name, ".") + cmd := exec.Command(dockerBinary, "build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "-t", name, ".") cmd.Dir = ctx.Dir out, _, err := runCommandWithOutput(cmd) @@ -5388,6 +5388,7 @@ func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { CpusetCpus string CpusetMems string CpuShares int64 + CpuQuota int64 } cfg, err := inspectFieldJSON(cID, "HostConfig") @@ -5399,9 +5400,9 @@ func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { if err := json.Unmarshal([]byte(cfg), &c1); err != nil { c.Fatal(err, cfg) } - if c1.Memory != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "0" || c1.CpusetMems != "0" || c1.CpuShares != 100 { - c.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d", - c1.Memory, c1.MemorySwap, c1.CpusetCpus, c1.CpusetMems, c1.CpuShares) + if c1.Memory != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "0" || c1.CpusetMems != "0" || c1.CpuShares != 100 || c1.CpuQuota != 8000 { + c.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d", + c1.Memory, c1.MemorySwap, c1.CpusetCpus, c1.CpusetMems, c1.CpuShares, c1.CpuQuota) } // Make sure constraints aren't saved to image @@ -5415,9 +5416,9 @@ func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { if err := json.Unmarshal([]byte(cfg), &c2); err != nil { c.Fatal(err, cfg) } - if c2.Memory == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "0" || c2.CpusetMems == "0" || c2.CpuShares == 100 { - c.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d", - c2.Memory, c2.MemorySwap, c2.CpusetCpus, c2.CpusetMems, c2.CpuShares) + if c2.Memory == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "0" || c2.CpusetMems == "0" || c2.CpuShares == 100 || c2.CpuQuota == 8000 { + c.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d", + c2.Memory, c2.MemorySwap, c2.CpusetCpus, c2.CpusetMems, c2.CpuShares, c2.CpuQuota) } }