Search code examples
dockerdocker-compose

Conditional "depends_on" in compose.yml


I have a compose file where I have a php and db service. In the development environment the application is dependent on the local db service, but in production there's already a (non-dockerized) database running. I gave the db service a profile called "development", but now when I run it in production with docker compose up without the profile, I get the following:

service db is required by php but is disabled. Can be enabled by profiles [development]

Is there a way to have this depends_on option only applicable based on a condition? For example if APP_ENV=development, or something like that? And if not, what would be the most elegant alternative?

version: "3.9"

services:
  php:
    context: "./docker/php"
    target: "${APP_ENV:?}"
    depends_on:
      db:
        condition: "service_started"
  db:
    build:
      context: "./docker/db"
      profiles:
        - development


Solution

  • You can have multiple Compose files. These files are merged together, and override files can have extra settings or entire extra containers.

    In the setup you describe, your base Compose file would have the main application, but not the database

    # docker-compose.yml
    version: '3.8'
    services:
      php:
        image: registry.example.com/php:${PHP_TAG:-latest}
    

    You could augment this with settings for production only

    # docker-compose.prod.yaml
    version: '3.8'
    services:
      php:
        environment:
          PGHOST: database.example.com
    

    or have a separate Compose file with developer-oriented settings. These would include the instructions on how to build the image, and in your setup it would also include the dedicated database container.

    # docker-compose.dev.yaml
    version: '3.8'
    services:
      php:
        build: ./docker/php
        depends_on:
          db:
            condition: service_started
        environment:
          PGHOST: db
      db:
        build: ./docker/db
    

    Probably the easiest way to use these is to use a symbolic link to make one of the files named docker-compose.override.yaml

    ln -s docker-compose.dev.yaml docker-compose.override.yaml
    

    but you can also use a docker-compose -f option; note that you need to list every Compose file if you do, and you need to include it on every Compose invocation.

    docker-compose \
      -f docker-compose.yaml \
      -f docker-compose.dev.yaml \
      up -d