Docker-Compose Restart Policy - docker

I looked thru the docs for docker-compose and I see that Version 3 has a deploy restart policy but it's only for swarm. I tried setting restart_policy on my service but got this error:
ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.web: 'restart_policy'
Is there any way to set a restart policy on services created using docker-compose outside of a swarm?

It looks like a gap in the documentation
In 3rd version, we can still use "restart" inside services same as before in v.2 (except for deploy into swarm)
version: '3'
services:
my-service:
restart: on-failure:5
https://docs.docker.com/compose/compose-file/compose-file-v3/#restart_policy

Version 2 supports restart policies, using the restart keyword, and should work fine for you if you don't need Swarm (which you said you don't need/want).
version: '2'
services:
web:
image: apache
restart: always
https://docs.docker.com/compose/compose-file/compose-file-v2/#restart
Compose format version 3 has a parameter called restart_policy, but so far as I can tell from documentation it is only valid as part of deploy, which is only used when deploying to a Swarm. So version 3 is probably not useful in your case.

Even if you're NOT in swarm mode, there is an option called --compatibility which will work with restart_policy, this will attempt to restart even if you're not deploying. The only glitch, is the sub-keys of 'delay' and 'window' will be ignored. Here is an example:
version: '3.7'
services:
build:
context: .
dockerfile: Dockerfile
container_name: example
deploy:
restart_policy:
condition: on-failure
max-attempts: 3
run this command:
docker-compose -f docker-compose.yml --compatibility up

Related

Portainer stacks and command line arguments

I have a portainer stack running one container. Lets use microbin as an example.
The docker-compose yaml looks like this:
---
version: "3"
services:
paste:
image: danielszabo99/microbin:latest
container_name: microbin
restart: always
ports:
- "8525:8080"
volumes:
- /mnt/docker_volumes/microbin-data:/app/pasta_data
This particular container is hosted on docker hub, and the maintainer provides examples of command line arguments that can be appended to the dockerfile to activate various features easily. One example would be:
--no-listing
Disables the /pastalist endpoint, essentially making all pastas private.
So this brings me to my issue. I don't want to maintain my own custom dockerfile, and in the past I have always inserted environment variables into the docker-compose yaml to call features like this.
An example would be like this - I have a stack running for Authentik (a sso/saml/idp gateway with a pretty web interface). You can see the "environment:" section and the variables I am calling.
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.5.3}
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
# WORKERS: 2
volumes:
- ./media:/media
- ./custom-templates:/templates
- geoip:/geoip
env_file:
- stack.env
So - not knowing how the development side of making these containers and hosting them on docker-hub goes... is there a way for me to use these command line arguments for microbin as environment variables in my docker-compose yaml / stack configuration file, or am I going to have to wait on the maintainer to implement this as a feature?
Thanks for your help in advance.
You can pass command line arguments in your docker-compose.yml file using the command attribute. That assumes of course the process started within the Docker image can deal with those, but that seems to be the case for your image and should generally be the case.
version: "3"
services:
paste:
image: danielszabo99/microbin:latest
container_name: microbin
restart: always
ports:
- "8525:8080"
volumes:
- /mnt/docker_volumes/microbin-data:/app/pasta_data
command: my command line --args here
See Docker Compose Reference - command for details.

Difference in restart and restart_policy in docker_compose.yml

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.

Docker stack deploy multiple errors from container on docker hub

I'm new to docker and trying to understand what docker stack does. Currently trying out this container https://hub.docker.com/r/instapy/instapy
this is the docker-compose file
services:
web:
image: instapy/instapy:latest
container_name: "${COMPOSE_PROJECT_NAME}_web"
env_file: .env
environment:
- PYTHONUNBUFFERED=0
- INSTAPY_WORKSPACE=/code/InstaPy
volumes:
- ./:/code
The errors I'm getting seem to indicate quite a few issues
Ignoring deprecated options:
container_name: Setting the container name is not supported.
service "web": container_name is deprecated
service "web": env_file are ignored
Stack.compose.docker.com "test" is invalid: test: Invalid value: "null": conversion to kube entities failed: C:\Users\roole\instapy-docker\docker-compose: only absolute paths can be specified in mount source
docker compose version info
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.0.2q 20 Nov 2018
Content asked for from ' docker-compose config'
services:
web:
container_name: instapy_web
environment:
COMPOSE_PROJECT_NAME: instapy
INSTAPY_WORKSPACE: /code/InstaPy
PYTHONUNBUFFERED: '0'
image: instapy/instapy:latest
volumes:
- C:\Users\roole\instapy-docker\docker-compose:/code:rw
version: '3.0'
Any help in understanding what the hell I'm supposed to be doing would be mega.
At the beginning of each docker-compose.yml file you need to specify the version. Each version of docker-compose supports certain versions of the yml file specification.
This should work for you:
version: "3.3"
services:
web:
image: instapy/instapy:latest
container_name: "${COMPOSE_PROJECT_NAME}_web"
env_file: .env
environment:
- PYTHONUNBUFFERED=0
- INSTAPY_WORKSPACE=/code/InstaPy
volumes:
- ./:/code
When deploying a stack the container name is not relevant (in fact after version "3" is not supported). The reason for that is that docker needs to be able to change the container name in case you scale your service (multiple versions of the same container might end up running on the same docker instance and then they need to have different container names).
Also when you specify a volume you need to specify full, absolute paths. You can simply replace your volume declaration with what you got from running docker-compose config (C:\Users\roole\instapy-docker\docker-compose:/code:rw) or you can use $PWD or the equivalent for your OS to refer to your current directory

Docker-compose: replace "build"-based service with pre-built image in production?

Let's say we have the following docker-compose.yml:
version: '3'
services:
db:
image: "postgres"
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=mysecretpassword
web:
build: web
depends_on: [ db ]
ports:
- "80:80"
The first service, db, just runs a container with the official postgres image from Docker Hub.
The second service, web, first builds a new image based on the Dockerfile in a folder also called web, then runs a container with that image.
While developing, we now can (repeatedly) make changes to whatever is in the web folder, then run docker-compose up --build to run our app locally.
Let's say we now want to deploy to production. My understanding is that docker-compose.yml can now be used to "define a stack in Docker's swarm mode" (see this answer, for instance). However, for the build step of the web service, Docker's compose file documentation states that
This option is ignored when deploying a stack in swarm mode with a (version 3) Compose file. The docker stack command accepts only pre-built images.
It probably wouldn't be a great idea to build the image on the production machine anyways, as this would leave build artifacts (source code) behind; this should happen on a build server.
My question is, is there a recommended way to modify docker-compose.yml en route to production to swap out build: web with image: <id> somehow?
Nothing on Use Compose in production on that. Is there something wrong with my approach in general?
docker-compose.yml should only contain canonical service definitions.
Anything that's specific to the build environment (e.g. dev vs prod) should be declared in a separate file docker-compose.override.yml. Each build environment can have its own version of that file.
The build: web declaration doesn't belong into docker-compose.yml, as it's only supposed to run locally (and possibly on a build server), not in production.
Therefore, in the example above, this is what docker-compose.yml should look like:
version: '3'
services:
db:
image: "postgres"
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=mysecretpassword
web:
depends_on: [ db ]
ports:
- "80:80"
And this would be the default docker-compose.override.yml for local development:
version: '3'
services:
web:
build: web
Running docker-compose up --build -d will now build the latest code changes and launch our app locally.
There could also be another version docker-compose.override.build.yml, targeting a build/CI server:
version: '3'
services:
web:
build: web
image: mydockeruser/web
Running docker-compose -f docker-compose.yml -f docker-compose.override.build.yml push will build the latest code changes and push the image to its registry/repository.
Finally, there could be another version docker-compose.override.prod.yml:
version: '3'
services:
web:
image: mydockeruser/web
Deploying to production (just to a single Docker host, not a cluster) can now be as simple as copying over only docker-compose.yml and docker-compose.override.prod.yml and running docker-compose -f docker-compose.yml -f docker-compose.override.prod.yml up -d.
The correct way to do it (i.e. the way I do it :P) is to have different docker-compose files; for example, docker-compose.dev.yml and docker-compose.prod.yml. You can then push your production-ready image to a repository, say Docker Hub, and reference that image in docker-compose.prod.yml's web service. All the while you can use the dev docker-compose file (the one with the build option) for local development.
Also, in case you've thought about this, you cannot use env variables as keys in docker-compose (see here). So there is no way to conditionally set either image or build options.

'docker-compose' creating multiple instances for the same image

I need to start multiple containers for the same image. If I create my compose file as shown below, it works fine.
version: '2'
services:
app01:
image: app
app02:
image: app
app03:
image: app
app04:
image: app
app05:
image: app
Is there an easy way for me to mention the number of instances for the compose instead of copy and pasting multiple times?
Updated answer (Oct 2017)
As others mentioned, the Docker API has changed. I'm updating my answer since it's the one most people will probably look at.
docker-compose up -d --scale app=5
Unfortunately, we cannot specify this in a docker-compose.yml file currently (as of version 3.5).
Details:
They did introduce the scale option for version 2.2 and 2.3 of docker-compose, but they removed it for version 3.0. Also, to use version 2.2 or 2.3 you would need to download an older version of the docker-compose tool. The current version does not support 2.2 or 2.3 (it does support 2.0 or 2.1 however).
There is also a new deploy section with replicas: 5 but it's only for swarm mode.
Old Answer
docker-compose scale app=5
See docker compose up.
Then you only need this docker-compose file:
version: '2'
services:
app:
image: app
You can do it with replica as mentioned in Compose specification:
version: '3'
services:
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 6
One can use docker-compose --compatibility up to make Docker accept a deploy section without using swarm.
The scale command is now deprecated, and you should use up instead.
docker-compose up --scale app=2
More details are on docker compose up.
You can do this:
version: "3.4"
services:
service1: &service_1
image: app
service2:
<<: *service_1
service3:
<<: *service_1
For more information on <<, see What is the << (double left arrow) syntax in YAML called, and where's it specified?.
Works for me well:
version: "3.9"
services:
web:
image: redis:6.2-alpine
...
deploy:
mode: replicated
replicas: 3
and run the command then:
docker-compose --compatibility up

Resources