READ-ONLY PACKAGE PREVIEW

docker-compose-patterns/assets/bad-vs-good.md

Version 3e1cbd179989 · Apache-2.0. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.

← Return to resource and package checksum

Common Compose Mistakes: Before and After

1. Missing health checks on database dependencies

Bad

services:
  web:
    build: .
    depends_on:
      - db
  db:
    image: postgres:17

depends_on without a condition only waits for the container to start, not for Postgres to accept connections. The web service will crash on startup.

Good

services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:17
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 3
      start_period: 10s

2. Using latest tag

Bad

services:
  cache:
    image: redis:latest

latest is mutable. Builds become non-reproducible and can break without warning.

Good

services:
  cache:
    image: redis:7

Pin to a specific major or minor version.


3. Hardcoded secrets in compose.yaml

Bad

services:
  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: supersecretpassword123

Secrets in the Compose file end up in version control.

Good

services:
  db:
    image: postgres:17
    env_file:
      - .env

With .env containing POSTGRES_PASSWORD=supersecretpassword123 and .env listed in .gitignore.


4. Bind mount for database data

Bad

services:
  db:
    image: postgres:17
    volumes:
      - ./pgdata:/var/lib/postgresql/data

Bind mounts for database storage cause permission issues and poor I/O performance on macOS and Windows.

Good

services:
  db:
    image: postgres:17
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Named volumes are managed by Docker and perform correctly on all platforms.


5. Legacy filename

Bad

docker-compose.yml

Good

compose.yaml

compose.yaml is the canonical filename. docker-compose.yml is legacy.


6. Development settings in the base Compose file

Bad

A single compose.yaml with bind mounts, debug ports, and development environment variables mixed in with production settings.

Good

Base compose.yaml with production-appropriate defaults. Development-only settings in compose.override.yaml, which Compose loads automatically:

# compose.override.yaml
services:
  web:
    ports:
      - "9229:9229"
    environment:
      LOG_LEVEL: debug
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src

7. No restart policy

Bad

services:
  web:
    image: myapp:1.0.0

Without a restart policy, the container stays down after a crash or host reboot.

Good

services:
  web:
    image: myapp:1.0.0
    restart: unless-stopped