I'm looking for a way to conditionally start a service with docker-compose. Here is my scenario:
version: "3"
services:
postgres:
container_name: ecoo-postgres
image: postgis/postgis
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: ecoo_db
ports:
- "5432:5432"
smtp4dev:
container_name: ecoo-smtp
image: rnwood/smtp4dev:v3
ports:
- "3010:80"
- "2525:25"
server:
container_name: ecoo-server
build:
context: .
dockerfile: Dockerfile
volumes:
- ./src:/app/src
- ./test:/app/test
- ./prisma:/app/prisma
depends_on:
- postgres
- smtp4dev
network_mode: "host"
restart: always
I'm setting up the environment in my .env file, and want the smpt4dev service to conditionally start based on the ENV variable. Example: If env="dev", start the smpt4dev service, otherwise no.
Any ideas are appreciated.
There is no way to conditionally start a service based on an environment variable. You can conditionally start certain services when you run docker compose up
by making use of docker compose profiles. For example, if you were to to use a compose file like this:
version: "3"
services:
postgres:
image: docker.io/postgis/postgis
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 20s
retries: 3
smtp4dev:
image: docker.io/rnwood/smtp4dev:v3
profiles:
- dev
server:
image: docker.io/alpinelinux/darkhttpd
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
depends_on:
postgres:
condition: service_healthy
Then running docker compose up
would start only postgres and your server, but running docker compose --profile dev up
would also start the smtp4dev
container.
Alternately, you could arrange for your service to exit when the variable is unset. Something like:
smtp4dev:
image: docker.io/rnwood/smtp4dev:v3
environment:
ENV: ${ENV}
entrypoint:
- sh
- -c
- |
[ "$ENV" = "DEV" ] || exit 0
exec "$@"
When you run docker compose up
, the smtp4dev
container would exit without an error unless ENV
was equal to dev
.
In either of the above cases, you would need to remove the dependency between your server
container and the smtp4dev
container, since in many cases the smtp4dev
container will not be running. Your application should gracefully handle an unavailable smtp server.
If you feel that you really need the dependency, you could create two versions of the server
container using different profiles
, and only have the dependency when using --profile dev
.
Unrelated to your question, but your existing depends_on
directive is effectively a no-op. To create the sort of dependencies you want, you need to (a) implement healthchecks for the target service, and then (b) use the extended form of depends_on
in the dependent service.