Recently, I tried upgrading a version 2 docker-compose yaml file to version 3. Specifically, I was going from 2.1 to 3.4. Using docker-compose version 1.18.0 and docker version 18.06.01.
The first attempt caused docker-compose to abort because of the presence of the Version 2 option: mem_limit. Reading these Version 3 docs, it clearly states mem_limit was removed and to see "upgrading" to guide usage away from this option. These instruction tell you to use the deploy section with resources. Making these changes to the docker-compose.yml file and the system started normally.
Unfortunately, I missed the disclaimer in there where it states that deploy is ignored by docker-compose! My question: is there a way to use Compose file reference 3 and docker-compose while still enforcing a container memory limit?
No, there is not.
Between versions 2.x and 3.x...several options have been removed
...mem_limit, memswap_limit: These have been replaced by the resources key under deploy. deploy configuration only takes effect when using docker stack deploy, and is ignored by docker-compose.
See Compose: Upgrading from 2 to 3
And also you don't have to upgrade, you don't even have any reason to upgrade if you don't use swarm.
Sadly in the official docker docs, there is stated
Version 3 (most current, and recommended)
which isn't actually really true, if you use docker-compose without swarm, there is hardly any reason to switch or to use on new project v3. In the official repository you can see comments like this [2][3].
Also in the compatibility-matrix you can see that v2 is still upgraded even when v3 is out for quite some time. And only v1 is marked as deprecated.
Here's an example Docker Compose file version 3.8 with memory limitations:
version: '3.8'
services:
web:
image: nginx:latest
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
resources:
limits:
memory: 256M
ports:
- "80:80"
volumes:
- type: volume
source: myapp-data
target: /var/www/html
networks:
- myapp-net
environment:
- NGINX_HOST=example.com
- NGINX_PORT=80
db:
image: mysql:latest
deploy:
replicas: 1
restart_policy:
condition: on-failure
resources:
limits:
memory: 512M
volumes:
- type: volume
source: myapp-db
target: /var/lib/mysql
networks:
- myapp-net
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=myapp
volumes:
myapp-data:
myapp-db:
networks:
myapp-net:
Related
I have a docker-compose file for some services, among them an airflow-webserver. I realized that I can both add restart and deploy-restart_policy to the compose file. I tried searching for a difference between the two, but could only find posts discussing the individual settings (like on-failure or always).
What is the difference of setting the configuration?
Which should I use?
Is it a versioning issue, e.g. restart is from older versions and deploy-restart_policy is the newer one?
Example docker-compose.yml:
version: "3"
services:
airflow-webserver:
container_name: airflow_container
image: puckel/docker-airflow
ports:
- '8080:8080'
networks:
- dataworld
volumes:
- ./airflow/dags:/usr/local/airflow/dags
- ./airflow/logs:/usr/local/airflow/logs
deploy:
restart_policy:
condition: on-failure
restart: on-failure
The restart and deploy.restart_policy options configure the same thing but depend on the way you run your containers:
restart is used by Docker Compose
deploy.restart_policy is used by Docker Swarm
The deploy option is used for Docker Swarm only and is ignored by Docker Compose.
From the documentation on deploy.restart_policy:
Configures if and how to restart containers when they exit. Replaces restart.
And here about restart:
The restart option is ignored when deploying a stack in swarm mode.
Hi guys and excuse me for my English. I'm using docker swarm, when I attempt to deploy docker application with this command
docker stack deploy -c docker-compose.yml -c docker-compose.prod.yml chatappapi
it shows the next error : services.chat-app-api Additional property pull_policy is not allowed
why this happens?
how do I solve this?
docker-compose.yml
version: "3.9"
services:
nginx:
image: nginx:stable-alpine
ports:
- "5000:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
chat-app-api:
build: .
image: username/myapp
pull_policy: always
volumes:
- ./:/app
- /app/node_modules
environment:
- PORT= 5000
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
- CLIENT_ID=${CLIENT_ID}
- CLIENT_SECRET=${CLIENT_SECRET}
- REDIRECT_URI=${REDIRECT_URI}
- REFRESH_TOKEN=${REFRESH_TOKEN}
depends_on:
- mongo-db
mongo-db:
image: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: 'username'
MONGO_INITDB_ROOT_PASSWORD: 'password'
ports:
- "27017:27017"
volumes:
- mongo-db:/data/db
volumes:
mongo-db:
docker-compose.prod.yml
version: "3.9"
services:
nginx:
ports:
- "80:80"
chat-app-api:
deploy:
mode: replicated
replicas: 8
restart_policy:
condition: any
update_config:
parallelism: 2
delay: 15s
build:
context: .
args:
NODE_ENV: production
environment:
- NODE_ENV=production
- MONGO_USER=${MONGO_USER}
- MONGO_PASSWORD=${MONGO_PASSWORD}
- MONGO_IP=${MONGO_IP}
command: node index.js
mongo-db:
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
Information
docker-compose version 1.29.2
Docker version 20.10.8
Ubuntu 20.04.2 LTS
Thanks in advance.
Your problem line is in docker-compose.yml
chat-app-api:
build: .
image: username/myapp
pull_policy: always # <== this is the bad line, delete it
The docker compose file reference doesn't have any pull_policy in the api because
If the image does not exist, Compose attempts to pull it, unless you have also specified build, in which case it builds it using the specified options and tags it with the specified tag.
I think pull_policy used to be a thing for compose? Maybe keep the latest api documentation open to refer to/search through whilst you're developing (things can and do change fairly frequently with compose).
If you want to ensure that the most recent version of an image is pulled onto all servers in a swarm then run docker compose -f ./docker-compose.yml pull on each server in turn (docker stack doesn't have functionality to run this over an entire swarm yet).
As an aside: I wouldn't combine two .yml files with a single docker stack command without a very good reason to do so.
You are mixing docker-compose and docker swarm ideas up in the same files:
It is probably worth breaking your project up into 3 files:
docker-compose.yml
This would contain just the basic service definitions common to both compose and swarm.
docker-compose.override.yml
Conveniently, docker-compose and docker compose both should read this file automatically. This file should contain any "port:", "depends_on:", "build:" directives, and any convenience volumes use for development.
stack.production.yml
The override file to be used in stack deployments should contain everything understood by swarm and not compose, and b. everything required for production.
Here you would use configs: or even secrets: rather than volume mappings to local folders to inject content into containers. Rather than relying on ports: directives, you would install an ingress router on the swarm such as traefik. and so on.
With this arrangement, docker compose can be used to develop and build your compose stack locally, and docker stack deploy won't have to be exposed to compose syntax it doesn't understand.
pull_policy is in the latest version of docker-compose.
To upgrade your docker-compose refer to:
https://docs.docker.com/compose/install/
The spec for more info:
https://github.com/compose-spec/compose-spec/blob/master/spec.md#pull_policy
I’m running Sonarqube on Docker compose and my file looks like this:
version: "3"
services:
sonarqube:
image: sonarqube
ports:
- "9000:9000"
- "5432:5432"
links:
- db:db
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
- SONARQUBE_JDBC_USERNAME=postgres
- SONARQUBE_JDBC_PASSWORD=sonar
volumes:
- ..../Work/tools/_SonarQube_home/conf:/opt/sonarqube/conf
# - sonarqube_data:/opt/sonarqube_new/data
- ...../Work/tools/_SonarQube_home/data:/opt/sonarqube/data
- ....../Work/tools/_SonarQube_home/extensions:/opt/sonarqube/extensions
- ..../Work/tools/_SonarQube_home/bundled-plugins:/opt/sonarqube/lib/bundled-plugins
db:
image: postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=sonar
- POSTGRES_DB=sonar
volumes:
- .../Work/tools/_PostgreSQL_data:/var/lib/postgresql
# This needs explicit mapping due to https://github.com/docker-library/postgres/blob/4e48e3228a30763913ece952c611e5e9b95c8759/Dockerfile.template#L52
- ..../Work/tools/_PostgreSQL_data/data:/var/lib/postgresql/data
Everything works and that’s great. One moment I saw that Sonarqube instance started to act slowly, therefore I checked docker stats. It looks like this:
| CPU | Mem Usage/ Limit |
|-------| --------------------
| 5.39% | 1.6GiB / 1.952GiB |
How do I define more RAM resources for the server, let’s say 4 GB? Previously it was mem_limit but now on version 3 it doesn’t exist.
What would be a good solution for that?
Thanks!
If you are deploying to Swarm, then you can use the resources keyword in your Compose file. (it's described under Resources in the file reference https://docs.docker.com/compose/compose-file/)
So you can do something like this is Swarm:
version: "3.7"
services:
redis:
image: redis:alpine
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
If you are using Compose, then you have the option to go back to Compose file version 2.0, as described in the Compose file reference by Docker.
Looking for options to set resources on non swarm mode containers?
The options described here are specific to the deploy key and swarm mode. If you want to set resource constraints on non swarm
deployments, use Compose file format version 2 CPU, memory, and other
resource options. If you have further questions, refer to the
discussion on the GitHub issue docker/compose/4513.
I'm not familiar with Sonarqube memory issue, but you may want to have a look at this https://docs.sonarqube.org/display/SONARqube71/Java+Process+Memory.
In Compose file version 3, resource limits moved to under a deploy: {resources: ...} key, but are also only documented to work in Swarm mode. So to actually set them you need to switch to a mostly-compatible version 2 Compose file.
version: '2'
services:
sonarqube:
mem_limit: 4g
The default should be for the container to be able to use an unlimited amount of memory. If you're running in an environment where Docker is inside a Linux VM (anything based on Docker Toolbox or Docker Machine, Docker for Mac) it's limited by the memory size of the VM.
I'm currently having some issues with the shared memory in one of my containers.
I have a docker-compose file in where I expect to be able to set the size. I basically converted an old docker run that had a --shm-size 16gb. I would guess it's as easy as adding shm_size:16gb to my service in the compose file.
Adding it just gives me the info: Ignoring unsupported options: shm_size.
I did check the docs, but it didn't really help me.
Just to clarify, it's not in the build but really for the "running" state.
Does one of you ever had this issue/know how to solve it?
Setup:
docker swarm with 7 nodes
Service should run on just a single node
Only running stacks
64 GB RAM host
32 GB shm (host)
Docker version 18.09.7, build 2d0083d
Using v 3.7 in my compose file
Compose file:
version: "3.7"
services:
server:
shm_size: 16GB # <<<<<<< This fails
image: local_repo/my_app:v1-dev
command: run
environment:
- UPDATES=enabled
volumes:
- type: volume
source: data
target: /var/lib/my_app/
- type: volume
source: db
target: /var/lib/postgresql/10/main
networks:
- xxx_traefik
deploy:
mode: replicated
labels:
- traefik.docker.network=xxx_traefik
- traefik.enable=true
- traefik.port=80
- traefik.frontend.rule=Host:my_container.xxx.com
- traefik.backend.loadbalancer.stickiness=true
- traefik.protocol=http
replicas: 1
placement:
constraints:
- node.hostname==node2
volumes:
db:
external: true
data:
external: true
networks:
xxx_traefik:
external: true
# shm_size: 16GB <<<<<<< Also tried to put it here since documentation doesn't show indents
Any help is appreciated:)
It should be below service, I can verify it, but here is what offical documentation said
SHM_SIZE
Added in version 3.5 file format
Set the size of the /dev/shm partition for this build’s containers.
Specify as an integer value representing the number of bytes or as a
string expressing a byte value.
build:
context: .
shm_size: '2gb'
compose-file-SHM_SIZE
Here is test
version: '3.7'
services:
your_service:
image: alpine
command: ash -c "sleep 2 && df /dev/shm"
shm_size: 2gb
Following along with the Docker getting started guide, https://docs.docker.com/get-started/part3/#your-first-docker-composeyml-file, I'm running into an issue. I've created the docker-compose.yml file and verified that the contents are correct:
version: "3"
services:
web:
image: joshuabelden/get-started:part2
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
I also verified that I can run my image outside of a swarm. After running the command:
docker stack deploy -c docker-compose.yml getstartedlab
I'm getting the following error:
Top-level object must be a mapping
I can't seem to find any information on the error message.
What I did to solve this is I removed the double quotes and made them single quotes to change
version: "3" -> version: '3'
This removed the error for me, also do this for all double quotes.
You probably didn't save after modifying the docker-compose.yml file. So if you run 'docker compose up' without having saved, you get the error about top-level object mappings.
You have to add the "volumes" where your code should be copied:
version: "3"
services:
web:
image: iconkam/get-started:part2
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
volumes:
- .:/app
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
I am using Symfony 6 on Linux Ubuntu and I had the same type of problem but not with "docker stack".
I had this problem simply when running:
docker-compose up
$ docker-compose up
Top-level object must be a mapping
I searched for a long time to find a solution.
No solution described here worked.
In fact the problem was caused by the presence of a default file in Symfony 6:
docker-compose.override.yml
I commented all the content inside but it was not enough.
Renaming the file made the command "docker-compose up" worked.
Deleting the file is also a solution ;-)
This happens when Docker is running in Kubernetes mode and not swarm.
I fixed it by changing it to Swarm through settings > Kubernetes
This error arises from the formatting of the file. Please try to convert the file encoding to UTF-8 and you will be able to run docker stack deploy command. Double quotes is not an issue here.
In my case, I wrapped all the values in double quotes expect the replica, and it got fixed. Like so:
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: "image details"
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: "50M"
restart_policy:
condition: "on-failure"
ports:
- "4000:80"
networks:
- "webnet"
networks:
webnet:
Sometimes it's just the formatting in the file. I recommend selecting your text in the compose file and seeing if you have a training blank space somewhere.
In my case, I had a space right after the image tag.
Just close and reopen Terminal again - and run command again.
p.s. I'm using Windows + WSL Terminal. Time to time randomly see same error.
Probably you forgot to save the docker compose file.
Another reason this may be happening while you're pulling your hair out:
You have the environment variable COMPOSE_FILE set, which refers to a file which is empty or an invalid yml file.
In my case it was set to docker-compose.combined.yml while running docker compose config > docker-compose.combined.yml, which first created an empty file to write to, and then stated the error Top-level object must be a mapping while trying to read that empty file.
I just had this problem and the reason was that I had an empty docker-compose.override.yml