34

I have a 4-core CPU, I want to allocate 50% CPU resource to a docker container.
After reading the docker-run manual and config.go source code.
I still don't know how to use the -c, --cpu-shares=0 option.

docker run -c 0.5 -i -t ubuntu /bin/bash

Or

docker run -c 2 -i -t ubuntu /bin/bash
Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
kev
  • 155,172
  • 47
  • 273
  • 272
  • Have you seen the `"Runtime constraints on resources"` Part in https://docs.docker.com/engine/reference/run/ – Gary Gauh Mar 10 '16 at 11:00
  • 1
    I know this question is answered, but to make this question more useful, I recommend to clarify: is it about setting a _minimum_ (QOS) or a _maximum_ (limitation, quota) of cpu ressources? the title says _min_, but the example is _max_. The accepted answer is both (cpu-shares is _min_ but cpuset is _max_) – Daniel Alder Jan 10 '18 at 13:43

5 Answers5

36

cpu-shares is a 'relative weight', relative to the default setting of 1024, so if you had two containers running on the same core, you could give them the CPU 50-50 or 80-20 or whatever you wanted by adjusting the numbers. It is an integer.

You cannot give an overall limit, as you want to, using this flag, but you can restrict the set of CPUs that the container runs on using --cpuset mentioned here.

The number 1024 is in the Cgroups docs.

This blog post from Marek Goldmann explains resource management in Docker.

See also Setting absolute limits on CPU for Docker containers, which says it can be done with lxc (older Docker implementation) but not libcontainer (current Docker implementation).

Community
  • 1
  • 1
Bryan
  • 11,398
  • 3
  • 53
  • 78
  • Do I need to pass a integer (1024) to `-c` option, or a float (0.2)? – kev Nov 10 '14 at 11:39
  • 1
    Is shipyard `--cpus 0.1` option directly past to docker? http://shipyard-project.com/docs/containers/ Thank you. – kev Nov 10 '14 at 11:42
  • For plain Docker, cpu-shares takes an integer. Here it is in the code: https://github.com/docker/docker/blob/9eb8fcd58a5dc0a6fd812fc2bdc410f36dd63cc0/runconfig/parse.go#L59 – Bryan Nov 10 '14 at 12:50
  • Don't know much about Shipyard, but from their code, 'cpus' is a float; I don't see how it could be passed directly to Docker since Docker doesn't have that option. – Bryan Nov 10 '14 at 12:57
16

It depends on the environment, so there is no straight answer but keep reading.

From the docker run --help command:

-c, --cpu-shares=0         CPU shares (relative weight)

Since Docker is based on cgroups. The CPU will be distributed among the running containers. By default the value is 1024.

cat /sys/fs/cgroup/cpu/docker/cpu.shares
1024



So, if we have 2 containers, one for the database and one more for the web server

sudo docker run -c 614 -dit --name db postgres /postgres.sh
sudo docker run -c 410 -dit --name web nginx /nginx.sh

Will give 60% to the db container (614 is 60% of 1024) and 40% to the web container.



For further reading see:

user454322
  • 7,300
  • 5
  • 41
  • 52
8

Since Docker 1.13, in your 4-core machine just add docker container run --cpus 2.0 [args...].

Explanation from this blog post:

In 1.13 though, if you want a container to be limited to one cpu then you can just add --cpus 1.0 to your Docker run/create command line. If you would like two and a half cpus as the limit of the container then just add --cpus 2.5. In Docker we are using the CFS quota and period to limit the container’s cpu usage to what you want and doing the calculations for you.

Also check the docs.

Yajo
  • 5,808
  • 2
  • 30
  • 34
3

Note: PR 15078 is implementing (Dec. 2015) support for changing resources (including CPU) both for stopped and running container (possibly docker 1.10 ou 1.11)

We decided to allow to set what we called resources, which consists of cgroup thingies for now, hence the following PR #18073.
The only allowed mutable elements of a container are in HostConfig and precisely in Resources (see the struct).

resources := runconfig.Resources{
        BlkioWeight:       *flBlkioWeight,
        CpusetCpus:        *flCpusetCpus,    <====
        CpusetMems:        *flCpusetMems,    <====
        CPUShares:         *flCPUShares,     <====
        Memory:            flMemory,
        MemoryReservation: memoryReservation,
        MemorySwap:        memorySwap,
        KernelMemory:      kernelMemory,
        CPUPeriod:         *flCPUPeriod,
        CPUQuota:          *flCPUQuota,
    }
  • The command should be set.
  • The allowed changes are passed as flags : e.g. --memory=1Gb --cpushare=… (as this PR does).
  • There is one flag for each attribute of the Resources struct (and no more, no less).

Note that making changes via docker set should persist.
I.e., those changes would be permanent (updated in the container's JSON)


Check also the latest (July 2019, 4 years later) openJDK 8u212 (or later) which does have official Docker support in it.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
1

Take a look here, this is apparently what you were looking for:

https://docs.docker.com/engine/reference/run/#cpu-period-constraint

The default CPU CFS (Completely Fair Scheduler) period is 100ms. We can use --cpu-period to set the period of CPUs to limit the container’s CPU usage. And usually --cpu-period should work with --cpu-quota.

Examples:

$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:14.04 /bin/bash

If there is 1 CPU, this means the container can get 50% CPU worth of run-time every 50ms.

period and quota definition:

Within each given "period" (microseconds), a group is allowed to consume only up to "quota" microseconds of CPU time. When the CPU bandwidth consumption of a group exceeds this limit (for that period), the tasks belonging to its hierarchy will be throttled and are not allowed to run again until the next period.

Mohammed Noureldin
  • 14,913
  • 17
  • 70
  • 99