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 #81: tty and stdin_open for interactive containers

Drop a bash or python service into a compose.yaml and it exits immediately on up. The container starts, sees no stdin, prints nothing, and stops. The fix is the Compose equivalent of docker run -it: tty: true and stdin_open: true. What each flag does The two flags map directly to the docker run flags everyone has typed a thousand times: stdin_open: true ⇔ docker run -i — keep STDIN open even when not attached. tty: true ⇔ docker run -t — allocate a pseudo-TTY. services: shell: image: alpine command: sh stdin_open: true tty: true Set both for an interactive shell. Set only tty: true for a process that wants a terminal (for color output, line-buffered logs) but doesn’t read from stdin. stdin_open: true alone is rare — almost always paired with tty. ...

June 26, 2026 · 3 min · 610 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