DockerDocker 기초 · 3기초

Docker Compose — 멀티 컨테이너 앱 관리

DockerDockerCompose멀티컨테이너볼륨네트워크

Compose가 필요한 이유

웹 앱은 보통 여러 서비스로 구성됩니다:

# Compose 없이 — 명령이 너무 길고 순서를 기억해야 함
docker run -d --name postgres -e POSTGRES_PASSWORD=pass -p 5432:5432 postgres
docker run -d --name redis -p 6379:6379 redis
docker run -d --name app --link postgres --link redis -p 3000:3000 my-app

docker-compose.yml 기본

# docker-compose.yml
version: "3.9"

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/mydb
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_DB: mydb
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data  # 데이터 영구 저장
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Compose 명령어

# 모든 서비스 시작 (빌드 포함)
docker compose up --build

# 백그라운드 실행
docker compose up -d

# 서비스 중지 (컨테이너 삭제)
docker compose down

# 볼륨까지 삭제
docker compose down -v

# 서비스 상태 확인
docker compose ps

# 로그 확인
docker compose logs
docker compose logs -f app   # 특정 서비스 실시간

# 특정 서비스만 실행
docker compose up -d db cache

# 컨테이너 안 명령 실행
docker compose exec app bash
docker compose exec db psql -U postgres mydb

환경 파일 분리

# docker-compose.yml
services:
  app:
    env_file:
      - .env
# .env
POSTGRES_PASSWORD=devpassword
OPENAI_API_KEY=sk-...
SECRET_KEY=dev-secret

# .env.example (git에 포함)
POSTGRES_PASSWORD=
OPENAI_API_KEY=
SECRET_KEY=

개발 환경 오버라이드

# docker-compose.override.yml (자동으로 병합됨)
services:
  app:
    build:
      context: .
      target: development   # 개발용 스테이지
    volumes:
      - .:/app              # 소스 코드 마운트 (실시간 반영)
      - /app/node_modules   # node_modules는 마운트 제외
    command: npm run dev    # 개발 서버 실행
    environment:
      - NODE_ENV=development
# 개발 환경 (override 자동 적용)
docker compose up

# 프로덕션 환경 (override 제외)
docker compose -f docker-compose.yml up

프로필로 선택적 실행

services:
  app:
    build: .
  
  db:
    image: postgres:16

  adminer:    # DB 관리 UI
    image: adminer
    ports:
      - "8080:8080"
    profiles: [tools]   # 명시적으로 지정해야 실행됨

  prometheus:
    image: prom/prometheus
    profiles: [monitoring]
# 기본: app, db만 실행
docker compose up

# tools 포함
docker compose --profile tools up

실전: FastAPI + PostgreSQL + Redis

services:
  api:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    volumes:
      - ./logs:/app/logs

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${DB_NAME:-appdb}
      POSTGRES_USER: ${DB_USER:-app}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: pg_isready -U ${DB_USER:-app}
      interval: 5s
      retries: 10

  cache:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD}

volumes:
  db_data:

정리

명령역할
docker compose up모든 서비스 시작
docker compose down모든 서비스 중지
docker compose ps서비스 상태
docker compose logs로그
docker compose exec컨테이너 명령 실행
volumes:데이터 영구 저장
depends_on:서비스 의존성

다음 편에서는 볼륨과 네트워크 — 데이터 영속성과 컨테이너 간 통신을 깊이 이해합니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.