✦ For everyone, free.

Practical knowledge for real and everyday life

Home

17.3.2.1 Dev Override Practice

A focused guide to Dev Override Practice, connecting core concepts with practical Docker and container operations.

Dev override practice concerns the specific convention around docker-compose.override.yml, the one override filename Compose loads automatically without needing an explicit -f flag, and the distinction between using it for a shared, committed development convenience layer versus a genuinely personal, gitignored set of individual tweaks, since conflating these two uses produces confusion about what the file actually represents for a given project.

Why this specific filename is automatically loaded

Unlike any other override file, which requires an explicit -f flag to be included, docker-compose.override.yml is loaded automatically alongside the base docker-compose.yml whenever no other files are explicitly specified, which is precisely why it has historically been used as the default location for local development customization:

docker compose up -d
services:
  api:
    volumes:
      - .:/app
    ports:
      - "9229:9229"

Running the bare up command here automatically picks up both files together, applying the development-specific bind mount and debug port without needing any explicit reference to the override file at all.

Shared, committed development conveniences

For conveniences genuinely useful to every developer working on the project, a bind mount for live code reloading, a debug port exposed by default, a development-only service like a mail catcher, committing docker-compose.override.yml to version control makes this convenience available automatically to anyone who clones the repository and runs the default command:

services:
  api:
    volumes:
      - .:/app
  mailhog:
    image: mailhog/mailhog
    ports:
      - "8025:8025"

This shared, committed approach works well when every developer's local setup genuinely benefits from the identical set of overrides, with no individual customization needed beyond what is already committed.

Personal, gitignored local customization

For genuinely individual, personal tweaks, a specific port mapping that avoids a conflict with something else running on one particular developer's machine, a locally adjusted resource limit, gitignoring the file entirely and letting each developer maintain their own, uncommitted version avoids polluting version control with changes that are only ever relevant to one specific person's local environment:

docker-compose.override.yml
git status
?? docker-compose.override.yml

In this pattern, the file exists locally for each developer but is never committed, which means the repository itself contains no override file at all, and each developer who wants this kind of personal customization creates their own, entirely independently.

Choosing one approach deliberately, not mixing both

A project should choose deliberately between treating this file as a shared, committed convenience layer or as personal, gitignored customization, rather than attempting both simultaneously, since mixing the two produces confusion about whether the committed version represents the team's shared convention or merely whatever one specific person happened to commit at some point:

git log -- docker-compose.override.yml

Reviewing the commit history for this specific file clarifies which pattern a given project has actually been following; a history of frequent, varied commits from different contributors suggests the shared-convenience pattern, while its complete absence from version control entirely (visible only through a .gitignore entry) confirms the personal-customization pattern is the one in effect.

Providing a documented example for the personal customization pattern

When the personal, gitignored pattern is the chosen convention, providing a committed example file, distinctly named so it is never itself automatically loaded, documents the expected structure and common customizations without forcing every developer to start from a completely blank file:

docker-compose.override.yml.example
cp docker-compose.override.yml.example docker-compose.override.yml

This gives new contributors a documented starting point while keeping the actual, individually customized file itself out of version control, combining the discoverability benefit of the shared pattern with the flexibility of genuinely personal customization.

Being explicit in project documentation about which pattern is in use

Because the automatic-loading behavior of this specific filename is itself a detail not every developer, particularly someone newer to Compose, will already know, documenting directly in the project's setup instructions whether this file is expected to be committed, gitignored, or created from a provided example removes ambiguity about how local development is actually meant to be configured:

# README.md
Copy docker-compose.override.yml.example to docker-compose.override.yml
and adjust the ports section if 3000 conflicts with something else on your machine.

Common mistakes

  • Not recognizing that docker-compose.override.yml specifically, unlike any other override file, is loaded automatically without an explicit -f flag, leading to confusion about why certain overrides seem to apply without being referenced anywhere.
  • Mixing the shared-committed and personal-gitignored patterns inconsistently, leaving the file's actual purpose and expected handling ambiguous for the project.
  • Committing genuinely personal, individual customizations that only make sense for one specific developer's machine, polluting version control with changes irrelevant to everyone else.
  • Not providing a documented example file when following the personal-customization pattern, forcing every new contributor to reconstruct the expected structure from scratch.
  • Failing to document which pattern a given project follows, leaving new contributors uncertain about whether to expect this file already present, gitignored, or created from an example.

Dev override practice depends on deliberately choosing, and clearly documenting, whether docker-compose.override.yml represents a shared, committed development convenience or a genuinely personal, gitignored customization layer, since the file's automatic loading behavior makes either choice work seamlessly from a usage perspective, but only consistent, documented intent prevents confusion about what the file actually represents for a given project.