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: | 서비스 의존성 |
다음 편에서는 볼륨과 네트워크 — 데이터 영속성과 컨테이너 간 통신을 깊이 이해합니다.