Docker Compose Tip #83: Why up recreated containers that never changed

A service recreates on every single docker compose up. No file change, no rebuild, nothing actually different about the image. Before Compose 5.5.0, that wasn’t a flaky environment, it was a real bug class in how Compose decided an image had changed. One image, three ways to name its digest Compose decides whether to recreate a container by comparing the image’s current identity against a label it recorded last time, com.docker.compose.image. Before 5.5.0, that identity was computed differently depending on how the image got there: ...

September 9, 2026 · 3 min · 578 words · Guillaume Lours

Docker Compose Tip #82: pre_start hooks and native init containers

Tips are back after the summer break, and there are three months of Compose releases to catch up on, v5.2.0 through v5.5.1 shipped while the series was paused. The biggest addition: native init containers, through a new pre_start lifecycle hook. What pre_start does Tip #41 covered post_start and pre_stop, which run a command inside the already-running service container. pre_start is different: each step runs in its own ephemeral container, created after the service container exists but before it starts. It also waits on the service’s own depends_on conditions first, so a step can talk to those dependencies exactly like the main service command does. ...

September 7, 2026 · 4 min · 729 words · Guillaume Lours

Docker Compose Tip #80: additional_contexts for multi-context builds

A Dockerfile has one build context, the directory you point docker build at. That’s enough for the vast majority of builds, but sometimes you need files from somewhere else: a base image, a separate git repository, a local directory outside the project root, or another service’s build output. additional_contexts lets you wire all of those into a single build. The basic shape Under build:, declare named contexts. Inside the Dockerfile, reference them with COPY --from=<name>: ...

June 24, 2026 · 4 min · 640 words · Guillaume Lours

Docker Compose Tip #79: docker compose run advanced flags

docker compose run creates a fresh container for a service and attaches your terminal to it. Compared to exec (Tip #34), which jumps into a running container, run is for one-shot tasks — migrations, ad-hoc scripts, REPLs, smoke tests. The flags around it decide what gets started, what gets cleaned up, and whether ports are published. –rm — clean up after exit By default, the container created by run stays around (stopped) after the command finishes. That accumulates dead containers fast in a dev loop. --rm removes the container as soon as it exits: ...

June 22, 2026 · 4 min · 684 words · Guillaume Lours

Docker Compose Tip #78: The COMPOSE_* environment variables

Almost every Compose CLI flag has an environment-variable counterpart. Setting them once in a project .env file, in your shell, or in CI removes the need to retype the same flags on every command — and makes the configuration of a stack visible to anything that reads the environment. The core set The variables you reach for most often: Variable What it sets CLI equivalent COMPOSE_FILE Path(s) to the Compose file(s) -f, --file COMPOSE_PATH_SEPARATOR Separator when listing multiple files (in COMPOSE_FILE) COMPOSE_PROJECT_NAME Project name -p, --project-name COMPOSE_PROFILES Profiles to enable --profile COMPOSE_ENV_FILES Project-level env files --env-file COMPOSE_PARALLEL_LIMIT Max parallel operations --parallel (on some subcommands) COMPOSE_IGNORE_ORPHANS Don’t warn about orphan containers (no flag) COMPOSE_REMOVE_ORPHANS Always remove orphans on up/down --remove-orphans COMPOSE_ANSI Control ANSI output (auto, never, always) --ansi COMPOSE_PROGRESS Progress style (auto, tty, plain, json, quiet) --progress COMPOSE_STATUS_STDOUT Send status messages to stdout instead of stderr (no flag) COMPOSE_MENU Disable the interactive Docker Desktop menu (no flag) The full list lives in the Compose docs. The table above covers the ones that show up in real workflows. ...

June 19, 2026 · 4 min · 702 words · Guillaume Lours