Override docker-compose.yml files

Override docker-compose.yml files

Sometimes we want to have different versions of docker-compose.yml files (one for production and one for development). Each environment has their own characteristics (slightly different images for example) we show here a good way to override sections of a docker-compose.yml file easily.

Why?

Sometimes we have several environments that share almost all docker configuration. Having a common docker-compose.yml file and several docker-compose.override.yml files is a great way to manage your service configurations.

How?

Use several docker-compose.yml files.

You only have to create several docker-compose.yml files and replicate the section of the service you want to add, overwrite or extend.

Let us see an example:

# docker-compose.yml
version: "3.9"

services:
  db:
    hostname: project_db
    container_name: project_db
    image: postgres
    environment:
      - POSTGRES_DB=project
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    ports:
      - '5432:5432'
    restart: always
    volumes:
      - db:/var/lib/postgresql/data
    networks:
      - project_network

  rabbitmq:
    hostname: project_rabbitmq
    container_name: project_rabbitmq
    image: rabbitmq:3-management-alpine
    ports:
      - 5672:5672
      - 15672:15672
    environment:
      - RABBITMQ_USER=guest
      - RABBITMQ_PASSWORD=guest
    volumes:
      - ./tmp/rabbitmq/data/:/var/lib/rabbitmq/
      - ./tmp/rabbitmq/log/:/var/log/rabbitmq
    networks:
      - project_network
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://localhost:15672" ]
      interval: 30s
      timeout: 10s
      retries: 5

  web:
    hostname: project_web
    container_name: project_web
    build:
      context: .
      dockerfile: ./docker/web/Dockerfile
    command: /opt/app/docker-entrypoint.sh
    ports:
      - "9000:9000"
    environment:
      - DB_BACKEND=postgresql
      - DB_NAME=project
      - DB_USER=postgres
      - DB_PASSWORD=postgres
      - DB_HOST=project_db
      - DB_PORT=5432
      - QUEUE_HOST=project_rabbitmq
      - QUEUE_PORT=5672
      - LOG_NAME=web
      - LOG_LEVEL=INFO
    depends_on:
      - db
      - rabbitmq
    networks:
      - project_network
    restart: always

networks:
  project_network:
    name: project_network
    driver: bridge
volumes:
  db:
    driver: local
  project_rabbitmq:
    driver: local

Imagine we want to use a different Dockerfile for the project’s web service tests. You only need to create a different docker-compose.yml (with a meaningful name like docker-compose.web-test-override.ymll) and overwrite the property dockerfile of the main docker-compose.yml file.

# docker-compose.web-test-override.yml
version: "3.9"

services:
 web:
    build:
      dockerfile: ./docker/web/web.Dockerfile
    environment:
      - LOG_LEVEL=DEBUG

In our case, we have override the property dockerfile and the LOG_LEVEL environment variable.

How do you use it?

Use the -f or –file parameter to add several files to the docker-compose command you want to use, e.g.

docker-compose -f docker-compose.yml -f docker-compose.web-test.override.yml run web

What’s the catch?

You only can overwrite sections that containe a lone value. In the case of sections with several values (like ports), you can add new values but not remove or overwrite entirely the section.

So maybe a good practice is to have multiple-value sections in different docker-compose.yml files.

Conclusion

You can use several docker-compose.yml with the intent of overwritting concrete parts of a main docker-compose.yml file. This can be useful for customizing properties and sharing most of the configuration for different environments.