본문으로 바로가기

2단계

2단계 — docker-compose 패턴

5회 조회

목차

진짜 서비스는 컨테이너 한 개 가 아니에요. 앱 + DB + Redis + 작업 큐 — docker-compose 가 이 묶음을 한 줄로 띄워 줍니다.

첫 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
      timeout: 3s
      retries: 5

  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"   # 외부 직접 노출 X — Caddy 만 받음
    restart: unless-stopped

volumes:
  pg-data:
  redis-data:
docker compose up -d           # 백그라운드 띄우기
docker compose ps              # 상태
docker compose logs -f app     # 로그
docker compose down            # 종료 (volume 보존)
docker compose down -v         # volume 까지 삭제 (위험)

핵심 패턴 7

  1. healthcheck — DB 가 준비되기 전에 앱이 뜨면 connect 실패. condition: service_healthy 로 동기화
  2. 127.0.0.1 바인딩 — 외부에서 직접 :3000 접근 불가, Caddy 만 통과 (4단계)
  3. named volumepg-data 같은 이름 지정 volume 이 운영 표준
  4. environment vs .env 파일 — 비밀번호는 .env 파일 (gitignore)
  5. depends_on — 시작 순서 조절
  6. restart: unless-stopped — 재부팅 시 자동 재시작
  7. logging driver 상한 — json-file 기본은 무제한 누적. anchor 한 곳에서 정의해 모든 service 에 일괄 부착:
    x-logging: &default-logging
      driver: json-file
      options: { max-size: "10m", max-file: "3" }
    
    services:
      postgres:
        logging: *default-logging
      app:
        logging: *default-logging
    
    대형 모노레포 운영 사례: 여러 compose 파일 × 수십 개 서비스에 단일 anchor를 부착 → 컨테이너당 30MB 상한.

.env 분리

services:
  app:
    env_file:
      - .env.prod
# .env.prod (gitignore)
DB_PASSWORD=real-secret
JWT_SECRET=very-long-random-string

DEV 와 PROD 분리

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

DEV 는 hot-reload·외부 직접 노출, PROD 는 Caddy 뒤·loopback 만.

직접 해 보기

위 yml 을 그대로 복사해 PostgreSQL + Redis + 앱 한 묶음을 띄워 보세요. docker compose ps 가 모두 healthy 면 성공.

더 깊이

다음 단계

3단계에서는 외부 트래픽을 받는 Caddy 를 만나요.

이 글에서 만나는 용어