Docker Compose Tip #44: Signal handling in containers

When you run docker compose down or docker compose stop, Compose sends a signal to your containers. Understanding which signal is sent and how your application handles it is key to graceful shutdowns. Default behavior By default, Compose sends SIGTERM to the main process (PID 1), waits 10 seconds, then sends SIGKILL: services: app: image: myapp # Default: SIGTERM, 10s grace period, then SIGKILL Changing the stop signal Some applications expect a different signal. Nginx, for example, uses SIGQUIT for graceful shutdown: ...

March 25, 2026 · 2 min · 386 words · Guillaume Lours

Docker Compose Tip #43: Read-only root filesystems

Making a container’s root filesystem read-only is one of the simplest and most effective hardening measures. If an attacker gets in, they can’t modify binaries or drop malicious files. Basic usage services: app: image: myapp read_only: true That’s it. The container’s filesystem is now immutable. But most applications need to write somewhere — logs, temp files, caches. That’s where tmpfs comes in. Read-only with tmpfs for writable directories Combine read_only with tmpfs to allow writes only where needed: ...

March 23, 2026 · 2 min · 336 words · Guillaume Lours

Docker Compose Tip #42: Variable substitution and defaults

Docker Compose supports shell-style variable substitution in your Compose files. Combined with defaults and error messages, it makes your configurations flexible and safe. Basic substitution Reference environment variables or .env file values: services: app: image: myapp:${TAG} environment: DATABASE_URL: postgres://${DB_USER}:${DB_PASS}@db/${DB_NAME} # .env TAG=2.1.0 DB_USER=admin DB_PASS=secret DB_NAME=myapp Default values Provide fallback values when a variable is unset or empty: services: app: image: myapp:${TAG:-latest} environment: LOG_LEVEL: ${LOG_LEVEL:-info} PORT: ${PORT:-3000} deploy: replicas: ${REPLICAS:-1} Two syntaxes with a subtle difference: ...

March 20, 2026 · 2 min · 417 words · Guillaume Lours

Docker Compose Tip #41: Container lifecycle hooks

Docker Compose supports lifecycle hooks that let you run commands at specific points in a container’s lifecycle, right after it starts and just before it stops. post_start hook Run a command inside the container right after it starts — perfect for initialization tasks like database migrations: services: api: image: myapp-api post_start: - command: /app/migrate.sh depends_on: postgres: condition: service_healthy Or warming up caches so the service is ready to handle traffic: ...

March 18, 2026 · 2 min · 306 words · Guillaume Lours

Docker Compose Tip #40: Using labels for service organization and monitoring

Labels are key-value metadata attached to containers. They cost nothing at runtime but unlock powerful filtering, organization, and tool integrations. Adding labels to services services: api: image: myapp-api labels: com.example.team: "backend" com.example.env: "production" com.example.version: "2.1.0" worker: image: myapp-worker labels: com.example.team: "backend" com.example.env: "production" com.example.role: "async-processing" You can also use the list syntax: services: api: image: myapp-api labels: - "com.example.team=backend" - "com.example.env=production" Filtering with labels Labels become powerful with docker compose ps: ...

March 16, 2026 · 2 min · 258 words · Guillaume Lours