In Docker Swarm you can set maximum system requirements like so:
my-service
image: hello-world
deploy:
resources:
limits:
cpus: '2'
memory: 4GB
I have a container that has minimum system requirements of 2 CPU cores and 4GB of RAM which is the exact size of the nodes in my Docker Swarm. This means that when this container is running, it needs to be the only container running on that node.
However, when I run the container alongside others, other containers get placed on the same node. How can I ensure that Docker gives this container a minimum level of CPU and RAM?
I added reservations
as suggested by @yamenk, however I still get other containers starting on the same node which causes performance problems for the container I am trying to protect:
my-service
image: hello-world
deploy:
resources:
reservations:
cpus: '2'
memory: 4GB
Update
Apparently the effect of memory reservations in docker swarm are not very well documented and they work as a best effort. To understand the effect of memory reservation flag, check the documentation:
When memory reservation is set, Docker detects memory contention or low memory and forces containers to restrict their consumption to a reservation limit.
...
Memory reservation is a soft-limit feature and does not guarantee the limit won’t be exceeded. Instead, the feature attempts to ensure that, when memory is heavily contended for, memory is allocated based on the reservation hints/setup.
To enforce that no other container runs on the same node, you need to set service constraints. What you can do is give nodes in the swarm specific labels and use these labels to scheduel services to run only on nodes that have those specific labels.
As decribed here, node labels can be added to a node using the command:
docker node update --label-add hello-world=yes <node-name>
Then inside your stack file, you can restrict the container to run on nodes only having the specified label, and other container to avoid nodes labeled with hello-world=yes
.
my-service:
image: hello-world
deploy:
placement:
constraints:
- node.labels.hello-world == yes
other-service:
...
deploy:
placement:
constraints:
- node.labels.hello-world == no
If you want to start replicas of my-service on multiple nodes, and still have one container running on each node, you need to set the global mode of my-service, and add the same label to nodes where you want a container to run.
The global mode ensures that exactly one container will run each node that satisfies the service constraints:
my-service:
image: hello-world
deploy:
mode: global
placement:
constraints:
- node.labels.hello-world == yes
Old Answer:
You can set resource reservations as such:
version: '3'
services:
redis:
image: redis:alpine
deploy:
resources:
reservations:
cpus: '1'
memory: 20M