Docker Compose depends_on: 서비스 의존성과 시작 순서 제어

depends_on의 단축·긴 구문, service_started/service_healthy/service_completed_successfully 세 가지 condition 타입, restart 옵션까지 실전 예제로 정리합니다.

· 5 min read · PALDYN Team

지난 글에서 환경 변수 전달 방법과 우선순위를 살펴봤다. 이번에는 서비스들의 시작 순서를 선언적으로 제어하는 depends_on을 깊이 파고든다.

depends_on이 필요한 이유

멀티 서비스 애플리케이션에서 web이 api보다 먼저 뜨면 연결 오류가 난다. api는 db가 완전히 준비되기 전에 쿼리를 보내면 패닉한다. Compose는 depends_on으로 이 순서를 선언한다.

services:
  web:
    image: nginx
    depends_on:
      - api
  api:
    image: my-api
    depends_on:
      - db
  db:
    image: postgres

위 설정에서 compose up을 실행하면 db → api → web 순으로 시작된다. compose down은 반대로 web → api → db 순으로 정지한다.

depends_on 서비스 의존성 다이어그램

단축 구문 vs 긴 구문

단축 구문

배열로 나열하면 condition: service_started가 묵시적으로 적용된다.

depends_on:
  - db
  - redis

service_started는 컨테이너 프로세스가 시작됐다는 신호만 확인한다. PostgreSQL이 ready to accept connections를 출력하기 전일 수도 있어서, 앱 쪽에서 재시도 로직이 없으면 여전히 연결 오류가 발생할 수 있다.

긴 구문 — condition 명시

services:
  api:
    depends_on:
      db:
        condition: service_healthy
        restart: true
      migrate:
        condition: service_completed_successfully

긴 구문에서는 세 가지 condition을 선택할 수 있다.

condition의미
service_started컨테이너 프로세스가 시작됨 (기본값)
service_healthyhealthcheck가 healthy 상태
service_completed_successfully컨테이너가 exit code 0으로 종료됨

service_healthy 실전 패턴

service_healthy를 쓰려면 의존 대상 서비스에 healthcheck 블록이 있어야 한다.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 10s

  api:
    image: my-api
    depends_on:
      db:
        condition: service_healthy

start_period는 컨테이너가 초기화되는 동안 healthcheck 실패를 무시하는 유예 시간이다. DB 초기화가 오래 걸릴 때 유용하다.

depends_on 구문 코드 예시

service_completed_successfully — 마이그레이션 패턴

DB 스키마 마이그레이션을 별도 서비스로 분리할 때 사용한다.

services:
  migrate:
    image: my-api
    command: ["python", "manage.py", "migrate"]
    depends_on:
      db:
        condition: service_healthy

  api:
    image: my-api
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy

migrate 서비스가 exit 0으로 끝난 뒤에야 api가 시작된다. 마이그레이션 실패(exit 1)이면 api는 아예 시작되지 않는다.

restart 옵션

depends_on:
  db:
    condition: service_healthy
    restart: true     # db가 재시작되면 api도 재시작

restart: true를 설정하면 의존 서비스가 비정상 종료·재시작될 때 현재 서비스도 함께 재시작된다. 기본값은 false다.

자주 빠지는 함정

depends_on은 시작 순서만 보장한다. DB 컨테이너가 시작됐다고 해서 PostgreSQL이 연결을 받을 준비가 됐다는 뜻이 아니다. service_started만 쓰면서 앱 쪽 재시도 로직이 없으면 연결 실패가 계속 발생한다.

해결책은 두 가지다.

  1. service_healthy + healthcheck 조합으로 실제 준비 완료를 기다린다.
  2. 앱 코드에 재시도 로직(exponential backoff)을 구현한다.

둘 다 적용하는 것이 가장 견고하다.

# depends_on 없이 순서 강제하는 확인 방법
docker compose up --wait  # 모든 서비스가 healthy 상태가 될 때까지 대기

--wait 플래그는 healthcheck 없는 서비스는 started 상태로 간주하고, healthcheck 있는 서비스는 healthy까지 기다린다.


지난 글: Docker Compose environment: 환경 변수 완전 정복

다음 글: Docker Compose healthcheck: 서비스 상태 검사 완전 정복


읽어주셔서 감사합니다. 😊