← Agent Learning knowledge code-senior

Docker Compose health-gated reverse proxy stack

무엇을 학습 FastAPI/Next.js/Postgres/Redis 서비스를 Docker Compose와 NPM/Nginx reverse proxy 뒤에서 운영할 때, “컨테이너 running”이 아니라 “서비스 ready”를 기준으로 startup, deploy, smoke test를 설계한다. 1. `depends_on` short syntax는 준비 완료를 보장하지 않는다. 2. dependency…
어디에 정리 02_Code_Senior/Patterns/docker-compose-health-gated-reverse-proxy-stack.md
앞으로 어떻게 쓸 것인가 브리프·체크리스트·자동화 패턴에 즉시 참조

Docker Compose health-gated reverse proxy stack

목적

FastAPI/Next.js/Postgres/Redis 서비스를 Docker Compose와 NPM/Nginx reverse proxy 뒤에서 운영할 때, “컨테이너 running”이 아니라 “서비스 ready”를 기준으로 startup, deploy, smoke test를 설계한다.

핵심 규칙

  1. depends_on short syntax는 준비 완료를 보장하지 않는다.
  2. dependency service에 healthcheck를 둔다.
  3. dependent service는 long syntax condition: service_healthy를 사용한다.
  4. depends_on.restart: true는 명시적 Compose 재시작/업데이트 후 dependent 재시작을 유도하는 장치이지, 모든 runtime crash 전파를 뜻하지 않는다.
  5. proxy health와 internal health를 분리해서 테스트한다.

Compose 템플릿

services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
        restart: true
      redis:
        condition: service_started
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import urllib.request; urllib.request.urlopen(\"http://127.0.0.1:8000/healthz\", timeout=2)'"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s

  db:
    image: postgres:18
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 30s

  redis:
    image: redis:7

FastAPI health endpoint 기준

from fastapi import FastAPI

app = FastAPI()

@app.get('/healthz')
def healthz():
    return {'status': 'ok'}

운영형 readiness는 별도 /readyz에서 DB ping/config check를 수행한다. /healthz는 너무 무겁게 만들지 않는다.

systemd wrapper 예시

[Unit]
Description=project compose stack
After=docker.service network-online.target
Requires=docker.service
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/my-project
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=180
Restart=on-failure
RestartSec=10s
RestartSteps=4
RestartMaxDelaySec=160s

[Install]
WantedBy=multi-user.target

RestartSteps/RestartMaxDelaySec는 systemd 254+ 기능이다. 적용 전 대상 서버의 systemctl --version을 확인한다.

배포 후 검증 순서

# 1. Compose 상태
/usr/bin/docker compose ps

# 2. Internal health
/usr/bin/docker compose exec api python -c 'import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:8000/healthz", timeout=3).status)'

# 3. Proxy health
curl -fsS https://app.example.com/healthz

장애 분류

  • internal health 실패: app boot, dependency readiness, migration, env/config 문제 우선.
  • internal health 성공 + proxy 실패: NPM host, upstream host/port, Docker network, DNS, TLS, firewall 문제 우선.
  • dependency가 자주 재시작: Compose/Docker restart policy, DB volume, credential/env, resource limit 확인.

관련 링크

Study Room

내일 학습·스터디 큐

내일 학습 큐가 아직 추출되지 않았습니다.

스터디 대화

코칭뿐 아니라 학습 내용에 대해 에이전트별 토론·스터디 지시를 남기는 공간입니다. 저장된 메시지는 다음 학습 큐 조정의 근거가 됩니다.

아직 스터디 대화가 없습니다.

인사이트로 Second Brain에 저장

스터디 대화와 approved 큐를 원문 덤프가 아닌 Phillip의 큐레이션 인사이트 노트로 승격합니다.