Foreword: So recently I had the problem that I've deployed some software (Sentry) via docker-compose and needed to add some changes to the docker-compose.yml file to implement the correct routing for my setup. In doing so, I didn't want to fork the project to make my changes in the official docker-compose file and so I found the override "function" for docker-compose. And here is how you can use it.
Different Environments with differing scopes
While it is good practice to keep your environments as similar as possible, there can still be differences in their configuration. A few examples of this would be:
- As a software developer, you want to test your code on your local machine and you want to set up your application from source code, rather than from a final built container.
- You don't use the same database for your live and test systems.
- Your testing environment maybe use a different instance for example for your logging or your monitoring.
How docker-compose overrides work?
So docker-compose has an inbuilt function to merge two or more compose files together into a single merged file.
From the official docker-compose documentation:
By default, Compose reads two files, a
docker-compose.ymland an optional
docker-compose.override.ymlfile. By convention, the
docker-compose.ymlcontains your base configuration. The override file, as its name implies, can contain configuration overrides for existing services or entirely new services.
If a service is defined in both files, Compose merges the configurations using the rules described in Adding and overriding configuration.
Through this feature, in my specific case, I was able to take the official docker-compose file and make my changes to docker-compose.override.yml. This spared me the creation of a repository fork and additionally, I get notified about direct changes in the official repository.
To show the explained functionality a bit clearer I would like to show an example how the whole thing can look like. The example is based on the official Sentry docker-compose.yml and my docker-compose.override.yml to implement my traefik setup in front of the Sentry containers.
So here is a snippet of one of the services out of the official docker-compose.yml that I want to modify for my personal needs:
services: nginx: <<: *restart_policy ports: - "$SENTRY_BIND:80/tcp" image: "nginx:1.21.5-alpine" volumes: - type: bind read_only: true source: ./nginx target: /etc/nginx depends_on: - web - relay
And here is the content from my docker-compose.override.yml file:
version: '3' networks: default: traefik: external: name: traefik_network services: nginx: networks: - traefik - default labels: traefik.enable: true traefik.http.routers.sentry.rule: "Host(`example.com`)" traefik.docker.network: traefik_network traefik.http.routers.sentry.entrypoints: websecure traefik.http.routers.sentry.tls: true traefik.http.routers.sentry.tls.certresolver: default
As you can see, we add the traefik labels and some network configuration in our 'override' file.
After that, you can safe both compose files in the same location and just do your normal
docker-compose up -d
This is just a simple example. With the infinite flexibility of overrides, you can create any combination of environments to suit your needs.
Docker Compose documentation - https://docs.docker.com/compose/
Official Sentry repository - https://github.com/getsentry/self-hosted
Traefik documentation - https://doc.traefik.io/traefik/