codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
EDU›Docker · Caddy · Cloud — 10 deploy options›Step 2

Step 2

Step 2 — docker-compose patterns

0 views

Step 2 — docker-compose patterns

Real services aren't single containers. App + DB + Redis + queue — docker-compose brings them up together.

First docker-compose.yml

services:
  postgres:
    image: postgres:17-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: secret
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
      interval: 5s

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

  app:
    build: .
    depends_on:
      postgres: { condition: service_healthy }
      redis:    { condition: service_started }
    environment:
      DB_URL: postgresql://user:secret@postgres:5432/myapp
      REDIS_URL: redis://redis:6379
    ports:
      - "127.0.0.1:3000:3000"
    restart: unless-stopped

volumes:
  pg-data:
  redis-data:
docker compose up -d
docker compose ps
docker compose logs -f app
docker compose down

Seven patterns

  1. healthcheck — gate depends_on with condition: service_healthy
  2. 127.0.0.1 binding — only Caddy reaches the app port
  3. named volumes — pg-data for production
  4. env_file — secrets out of YAML
  5. depends_on — startup order
  6. restart: unless-stopped — survive reboots
  7. logging driver cap — the default json-file driver grows without limit. Define it once via an anchor and attach to every service:
    x-logging: &default-logging
      driver: json-file
      options: { max-size: "10m", max-file: "3" }
    
    services:
      postgres:
        logging: *default-logging
      app:
        logging: *default-logging
    
    warragon monorepo: 7 compose files × 36+ services with a single anchor → 30MB cap per container.

.env split

services:
  app:
    env_file: [.env.prod]

DEV vs PROD split

infra/
├── dev/docker-compose.yml
└── prod/docker-compose.yml

DEV: hot-reload + direct exposure. PROD: behind Caddy + loopback only.

Try it

Bring up Postgres + Redis + app from the YAML above. docker compose ps should show all healthy.

Going deeper

  • docker-compose patterns

Next

Step 3 — Caddy.

← Step 1

Step 1 — Docker basics

Step 3 →

Step 3 — Caddy automatic HTTPS