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 #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 #24: Using profiles to organize optional services

Keep your Compose stack flexible! Profiles let you include or exclude services based on your current needs. Basic profiles Define optional services with profiles: services: app: image: myapp:latest ports: - "3000:3000" # No profile - always starts debug: image: debug-tools profiles: - debug # Only starts with --profile debug test-db: image: postgres:15 profiles: - test environment: POSTGRES_DB: test_db Starting with profiles Choose which services to include: ...

February 5, 2026 · 2 min · 376 words · Guillaume Lours

Docker Compose Tip #19: Override files for local development

Keep production and development configs separate. Docker Compose automatically merges compose.override.yml for local development tweaks. The magic Compose automatically loads two files: compose.yml (base configuration) compose.override.yml (local overrides) # These are equivalent: docker compose up docker compose -f compose.yml -f compose.override.yml up Basic setup compose.yml (production-ready): services: web: image: myapp:latest ports: - "80:80" environment: NODE_ENV: production LOG_LEVEL: warn compose.override.yml (developer-friendly): services: web: build: . # Build locally instead of using image ports: - "3000:80" # Different port for development volumes: - .:/app # Mount source code environment: NODE_ENV: development LOG_LEVEL: debug DEBUG: "true" Real development example compose.yml: ...

January 29, 2026 · 2 min · 348 words · Guillaume Lours

Docker Compose Tip #11: Mastering docker compose up --watch for hot reload

Stop manually restarting containers when code changes. Docker Compose Watch automatically syncs files and reloads services - zero interruption development. The basics Enable watch mode with: docker compose up --watch # If you don't want mixed logs, you can run it in a dedicated process, you need to have your stack started on its own process docker compose watch Then configure watching in your compose.yml: services: web: image: node:20 command: npm start develop: watch: - path: ./src target: /app/src action: sync - path: package.json action: rebuild Files in ./src sync instantly. Changes to package.json trigger a rebuild. ...

January 19, 2026 · 2 min · 365 words · Guillaume Lours