본문으로 건너뛰기
Previous
Next
Docker Compose 실전 가이드 | 멀티 컨테이너·네트워크·볼륨·프로덕션 배포

Docker Compose 실전 가이드 | 멀티 컨테이너·네트워크·볼륨·프로덕션 배포

Docker Compose 실전 가이드 | 멀티 컨테이너·네트워크·볼륨·프로덕션 배포

이 글의 핵심

Docker Compose로 멀티 컨테이너 애플리케이션을 구성하고 배포하는 완벽 가이드. 네트워크, 볼륨, 환경 변수, 프로덕션 배포까지. 실전 예제와 코드로 개념부터 활용까지 정리합니다. Docker·Docker Compose·DevOps 중심으로 설명합니다.

이 글의 핵심

Docker Compose로 멀티 컨테이너 애플리케이션을 구성하고 배포하는 완벽 가이드입니다. 네트워크, 볼륨, 환경 변수, 헬스체크, 프로덕션 배포까지 실무에 바로 적용할 수 있습니다.

실무 경험 공유: 대규모 인프라의 모니터링 스택(Prometheus, Grafana, Loki)을 Docker Compose로 구축하면서, 개발 환경 구성 시간을 2시간에서 5분으로 단축한 경험을 공유합니다.

들어가며: “컨테이너 여러 개를 어떻게 관리하죠?”

실무 문제 시나리오

시나리오 1: 개발 환경 구성이 복잡해요

웹 서버, 데이터베이스, Redis, Nginx를 각각 설치하고 설정하는 데 하루가 걸립니다. Docker Compose로 docker compose up 한 번에 모든 환경을 구성할 수 있습니다. 시나리오 2: 팀원마다 환경이 달라요

“내 컴퓨터에서는 되는데요?” 문제가 반복됩니다. Docker Compose로 모든 팀원이 동일한 환경을 공유할 수 있습니다. 시나리오 3: 프로덕션 배포가 불안해요

개발 환경과 프로덕션 환경이 달라 배포 후 에러가 발생합니다. Docker Compose로 환경을 일치시킬 수 있습니다.

flowchart TB
    subgraph Before[문제 상황]
        A1[수동 설치]
        A2[환경 불일치]
        A3[배포 실패]
    end
    subgraph After[Docker Compose]
        B1[docker compose up]
        B2[동일 환경]
        B3[안정적 배포]
    end
    Before --> After

1. Docker Compose 기초

Docker Compose란?

여러 컨테이너를 정의하고 실행하는 도구입니다. YAML 파일로 서비스, 네트워크, 볼륨을 선언적으로 정의합니다.

설치

# Docker Desktop 설치 시 자동 포함
docker compose version
# Linux에서 별도 설치
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

최소 예제

# docker-compose.yml
version: '3.8'
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
# 실행
docker compose up
# 백그라운드 실행
docker compose up -d
# 중지 및 삭제
docker compose down

2. 멀티 컨테이너 애플리케이션

실전 예제: 웹 애플리케이션 스택

# docker-compose.yml
version: '3.8'
services:
  # Nginx 웹 서버
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./public:/usr/share/nginx/html:ro
    depends_on:
      - app
    networks:
      - frontend
  # Node.js 애플리케이션
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - frontend
      - backend
  # PostgreSQL 데이터베이스
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend
  # Redis 캐시
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - backend
volumes:
  postgres_data:
  redis_data:
networks:
  frontend:
  backend:

서비스 간 의존성

flowchart LR
    subgraph Frontend[Frontend Network]
        Nginx
        App
    end
    subgraph Backend[Backend Network]
        App2[App]
        DB[PostgreSQL]
        Redis
    end
    Nginx --> App
    App --> App2
    App2 --> DB
    App2 --> Redis

3. 네트워크 구성

기본 네트워크

services:
  web:
    image: nginx
    networks:
      - frontend
  app:
    image: node:18
    networks:
      - frontend
      - backend
  db:
    image: postgres
    networks:
      - backend
networks:
  frontend:
  backend:

커스텀 네트워크

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
  backend:
    driver: bridge
    internal: true  # 외부 접근 차단

외부 네트워크 연결

networks:
  existing_network:
    external: true
    name: my-pre-existing-network

4. 볼륨 관리

Named Volumes

services:
  db:
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
    driver: local

Bind Mounts

services:
  web:
    image: nginx
    volumes:
      # 호스트 경로:컨테이너 경로:옵션
      - ./nginx.conf:/etc/nginx/nginx.conf:ro  # 읽기 전용
      - ./public:/usr/share/nginx/html

tmpfs Mounts (메모리)

services:
  app:
    image: node:18
    tmpfs:
      - /tmp
      - /run:size=100M,mode=1777

볼륨 백업 및 복원

# 백업
docker run --rm -v postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres_backup.tar.gz -C /data .
# 복원
docker run --rm -v postgres_data:/data -v $(pwd):/backup alpine tar xzf /backup/postgres_backup.tar.gz -C /data

5. 환경 변수 및 시크릿

.env 파일

# .env
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret123
POSTGRES_DB=myapp
NODE_ENV=production
API_KEY=your-api-key
# docker-compose.yml
services:
  db:
    image: postgres
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}

환경 파일 분리

services:
  app:
    image: node:18
    env_file:
      - .env.common
      - .env.production

시크릿 관리 (Docker Swarm)

services:
  app:
    image: node:18
    secrets:
      - db_password
      - api_key
secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    external: true

6. 헬스체크 및 재시작 정책

헬스체크

services:
  app:
    image: node:18
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

재시작 정책

services:
  app:
    image: node:18
    restart: unless-stopped  # 수동 중지 전까지 재시작
  worker:
    image: node:18
    restart: on-failure:3  # 실패 시 최대 3회 재시작
  cache:
    image: redis
    restart: always  # 항상 재시작

7. 빌드 및 이미지 관리

Dockerfile과 통합

services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
      args:
        - NODE_VERSION=18
        - BUILD_ENV=production
      target: production  # 멀티스테이지 빌드의 특정 단계
      cache_from:
        - myapp:latest
# app/Dockerfile
ARG NODE_VERSION=18
FROM node:${NODE_VERSION}-alpine AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM base AS development
RUN npm install
FROM base AS production
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]

이미지 빌드 및 푸시

# 빌드
docker compose build
# 특정 서비스만 빌드
docker compose build app
# 빌드 후 실행
docker compose up --build
# 이미지 푸시
docker compose push

8. 프로덕션 배포

프로덕션 설정 분리

# docker-compose.yml (기본)
version: '3.8'
services:
  app:
    image: myapp:latest
    environment:
      - NODE_ENV=development
# docker-compose.prod.yml (프로덕션 오버라이드)
version: '3.8'
services:
  app:
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M
# 프로덕션 실행
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

리소스 제한

services:
  app:
    image: node:18
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
        reservations:
          cpus: '1'
          memory: 512M

로깅 설정

services:
  app:
    image: node:18
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

9. 실전 예제: 풀스택 애플리케이션

프로젝트 구조

myapp/
├── docker-compose.yml
├── docker-compose.prod.yml
├── .env
├── nginx/
│   ├── Dockerfile
│   └── nginx.conf
├── frontend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── backend/
│   ├── Dockerfile
│   ├── package.json
│   └── src/
└── scripts/
    ├── init-db.sql
    └── backup.sh

docker-compose.yml

version: '3.8'
services:
  nginx:
    build: ./nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - frontend
      - backend
    networks:
      - frontend
    restart: unless-stopped
  frontend:
    build:
      context: ./frontend
      target: production
    environment:
      - NEXT_PUBLIC_API_URL=http://backend:3000
    networks:
      - frontend
    restart: unless-stopped
  backend:
    build:
      context: ./backend
      target: production
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:${DB_PASSWORD}@db:5432/myapp
      - REDIS_URL=redis://redis:6379
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - frontend
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    networks:
      - backend
    restart: unless-stopped
  backup:
    image: postgres:15-alpine
    volumes:
      - postgres_data:/data:ro
      - ./backups:/backups
    entrypoint: /bin/sh
    command: -c "while true; do pg_dump -U user -h db myapp > /backups/backup_$$(date +%Y%m%d_%H%M%S).sql; sleep 86400; done"
    depends_on:
      - db
    networks:
      - backend
    restart: unless-stopped
volumes:
  postgres_data:
  redis_data:
networks:
  frontend:
  backend:

Nginx 설정

# nginx/nginx.conf
upstream frontend {
    server frontend:3000;
}
upstream backend {
    server backend:3000;
}
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://frontend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    location /api {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

10. 자주 하는 실수와 해결법

문제 1: 컨테이너 간 통신 안 됨

원인: 같은 네트워크에 있지 않음.

# ❌ 잘못된 코드
services:
  app:
    image: node:18
    # 네트워크 지정 안 함
  db:
    image: postgres
    networks:
      - backend
# ✅ 올바른 코드
services:
  app:
    image: node:18
    networks:
      - backend
  db:
    image: postgres
    networks:
      - backend

문제 2: 볼륨 데이터 손실

원인: docker compose down -v로 볼륨까지 삭제.

# ❌ 볼륨까지 삭제
docker compose down -v
# ✅ 컨테이너만 삭제
docker compose down

문제 3: 환경 변수 인식 안 됨

원인: .env 파일 위치 또는 형식 오류.

# .env 파일은 docker-compose.yml과 같은 디렉터리에
# 공백 없이 작성
DB_PASSWORD=secret123
# ❌ DB_PASSWORD = secret123 (공백 있으면 안 됨)

문제 4: 포트 충돌

원인: 호스트 포트가 이미 사용 중.

# 포트 사용 확인
sudo lsof -i :80
# 다른 포트로 변경
services:
  nginx:
    ports:
      - "8080:80"  # 호스트 8080 포트 사용

11. 모니터링 및 로깅

Docker Compose 상태 확인

# 실행 중인 서비스 확인
docker compose ps
# 로그 확인
docker compose logs
# 특정 서비스 로그
docker compose logs app
# 실시간 로그
docker compose logs -f
# 최근 100줄
docker compose logs --tail=100

리소스 사용량 모니터링

# 실시간 리소스 사용량
docker stats
# Compose 서비스만
docker compose ps -q | xargs docker stats

Prometheus + Grafana 통합

services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"
  grafana:
    image: grafana/grafana
    volumes:
      - grafana_data:/var/lib/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
  prometheus_data:
  grafana_data:

12. CI/CD 통합

GitHub Actions

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Build and push
        run: |
          docker compose build
          docker compose push
      - name: Deploy to server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /app
            docker compose pull
            docker compose up -d

13. Compose V2 내부·네트워킹·프로덕션 패턴

Compose 스펙은 서비스 디스커버리를 위해 기본 브리지 네트워크를 만들고, 서비스 이름이 DNS 이름으로 해석됩니다. 그래서 app 컨테이너에서 postgres:5432로 접속하는 패턴이 가능합니다. 호스트 네트워크 모드는 OS별 차이가 크므로 로컬과 CI에서 동일하게 재현하려면 퍼블리시 포트 방식이 안전합니다.

헬스체크는 오케스트레이션 레벨에서 “준비됐는지”를 판별하는 훅입니다. depends_on만으로는 DB가 준비됐다는 뜻이 아니므로, 애플리케이션 쪽에서 재시도 가능한 연결 루프를 두거나 healthcheck를 맞춥니다.

프로덕션에서 자주 쓰는 옵션

  • deploy.resources: Swarm 모드에서 CPU/메모리 제한(단일 호스트 Compose에서는 mem_limit 등과 혼동 주의).
  • profiles: dev 전용 서비스(PgAdmin 등)를 프로덕션 up에서 제외합니다.
  • 시크릿: .env는 편하지만 권한 오류로 레포에 올라가는 사고가 잦습니다. 서버에서는 Docker secrets나 외부 비밀 저장소를 검토합니다.

14. 트러블슈팅 (심화)

증상흔한 원인점검
컨테이너는 뜨는데 DB만 안 붙는다잘못된 서비스명·포트·네트워크 attachdocker compose exec app ping postgres
볼륨 권한 문제(Linux)UID/GID 불일치named volume 또는 user 매핑
빌드 캐시가 꼬인다베이스 이미지·레이어 재사용--no-cache로 단일 검증 후 Dockerfile 정리
OOM메모리 제한 없음호스트 모니터링 + 컨테이너 limit

정리 및 체크리스트

핵심 요약

  • Docker Compose는 멀티 컨테이너 애플리케이션을 YAML로 정의하고 관리
  • 네트워크로 서비스 간 통신을 격리하고 제어
  • 볼륨으로 데이터를 영구 저장
  • 헬스체크재시작 정책으로 안정성 확보
  • 환경별 설정 분리로 개발/프로덕션 환경 관리

프로덕션 체크리스트

  • 환경 변수를 .env 파일로 분리
  • 시크릿 정보는 .gitignore에 추가
  • 헬스체크 설정
  • 재시작 정책 설정
  • 리소스 제한 설정
  • 로깅 드라이버 설정
  • 백업 전략 수립
  • 모니터링 도구 연동

같이 보면 좋은 글


이 글에서 다루는 키워드

Docker, Docker Compose, 컨테이너, DevOps, 멀티 컨테이너, 네트워크, 볼륨, 배포, CI/CD

내부 동작과 핵심 메커니즘

이 글의 주제는 「Docker Compose 실전 가이드 | 멀티 컨테이너·네트워크·볼륨·프로덕션 배포」입니다. 앞선 튜토리얼을 구현·런타임 관점에서 다시 압축합니다. 구성 요소 간 책임 분리와 관측 가능한 지점을 기준으로 “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)·동시성이 어디서 터지는가”를 한 장면으로 그리면 장애 분석이 빨라집니다.

처리 파이프라인(개념도)

flowchart TD
  A[입력·요청·이벤트] --> B[파싱·검증·디코딩]
  B --> C[핵심 연산·상태 전이]
  C --> D[부작용: I/O·네트워크·동시성]
  D --> E[결과·관측·저장]

경계에서의 지연·실패(시퀀스 관점)

sequenceDiagram
  participant C as 클라이언트/호출자
  participant B as 경계(프로세스·런타임·게이트웨이)
  participant D as 의존성(외부 API·DB·큐)
  C->>B: 요청/이벤트
  B->>D: 조회·쓰기·RPC
  D-->>B: 지연·부분 실패·재시도 가능
  B-->>C: 응답 또는 오류(코드·상관 ID)

알고리즘·프로토콜·리소스 관점 체크포인트

  • 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(버퍼 경계, 프로토콜 상태, 트랜잭션 격리, 파일 디스크립터 상한)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
  • 결정성: 동일 입력에 동일 출력이 보장되는 순수 층과, 시간·네트워크·스레드 스케줄에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
  • 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합, GC·할당, 캐시 미스처럼 누적 비용을 의심 목록에 넣습니다.
  • 백프레셔: 생산자가 소비자보다 빠를 때(소켓 버퍼, 큐 깊이, 스트림) 어디서 어떤 신호로 속도를 줄일지 정의합니다.

프로덕션 운영 패턴

실서비스에서는 기능과 함께 관측·배포·보안·비용·규제가 동시에 요구됩니다.

영역운영 관점 질문
관측성요청 단위 상관 ID, 에러율/지연 분위수(p95/p99), 의존성 타임아웃·재시도가 대시보드에 보이는가
안전성입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가
신뢰성재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가
성능캐시 계층·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가
배포롤백 룬북, 카나리/블루그린, 마이그레이션 호환성·플래그가 문서화되어 있는가
용량피크 트래픽·디스크·파일 디스크립터·스레드 풀 상한을 주기적으로 검증하는가

스테이징은 데이터 양·네트워크 RTT·동시성을 가능한 한 프로덕션에 가깝게 맞추는 것이 재현율을 높입니다.


확장 예시: 엔드투엔드 미니 시나리오

「Docker Compose 실전 가이드 | 멀티 컨테이너·네트워크·볼륨·프로덕션 배포」을 실제 배포·운영 흐름으로 옮긴 체크리스트형 시나리오입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.

  1. 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드 표를 API 또는 이벤트 경계에 둔다.
  2. 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 한 화면(로그+메트릭+트레이스)에서 추적한다.
  3. 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
  4. 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지(또는 피처 플래그) 확인한다.
  5. 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값이 기대 범위인지 본다.

의사코드 스케치(프레임워크 무관)

handle(request):
  ctx = newCorrelationId()
  validated = validateSchema(request)        // 경계에서 거절
  authorize(validated, ctx)                  // 권한·테넌트
  result = domainCore(validated)             // 순수에 가까운 규칙
  persistOrEmit(result, idempotentKey)       // I/O: 멱등·재시도 정책
  recordMetrics(ctx, latency, outcome)
  return result

문제 해결(Troubleshooting)

증상가능 원인조치
간헐적 실패레이스, 타임아웃, 외부 의존성 불안정, DNS최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검
성능 저하N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거
메모리 증가캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납상한·TTL·힙/FD 스냅샷 비교
빌드·배포만 실패환경 변수, 권한, 플랫폼 차이, lockfileCI 로그와 로컬 diff, 런타임·이미지 버전 핀
설정이 로컬과 다름프로필·시크릿·기본값, 지역 리전단일 소스(예: 스키마 검증된 설정)와 배포 매트릭스 표준화
데이터 불일치비멱등 재시도, 부분 쓰기, 캐시 무효화 누락멱등 키·아웃박스·트랜잭션 경계 재검토

권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.

자주 묻는 질문 (FAQ)

Q. Docker Compose vs Kubernetes, 언제 뭘 쓰나요?

A. 소규모 프로젝트, 개발 환경은 Docker Compose를 권장합니다. 대규모, 멀티 클러스터, 자동 스케일링이 필요하면 Kubernetes를 사용하세요.

Q. 프로덕션에서 Docker Compose를 써도 되나요?

A. 단일 서버 배포는 가능합니다. 하지만 고가용성, 자동 스케일링이 필요하면 Kubernetes나 Docker Swarm을 고려하세요.

Q. 볼륨 데이터를 백업하려면?

A. docker run --rm -v volume_name:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz -C /data . 명령으로 백업할 수 있습니다.

Q. 컨테이너 간 통신이 안 되는데요?

A. 같은 네트워크에 있는지 확인하세요. docker compose logs로 네트워크 오류를 확인할 수 있습니다.