15 분 소요

전체 흐름 요약

실제 애플리케이션 환경은 단일 컨테이너로 구성되지 않습니다. 웹 서버, 애플리케이션 서버, 데이터베이스, 캐시 서버, 메시지 큐 등 여러 컨테이너가 협력하여 동작합니다. 각 컨테이너를 개별적으로 docker container run 명령어로 실행하고 관리하는 것은 복잡하고 오류가 발생하기 쉽습니다.

Docker Compose는 이러한 멀티 컨테이너 애플리케이션을 YAML 파일 하나로 정의하고, 단일 명령어로 전체 스택을 시작/중지/관리할 수 있게 해주는 도구입니다. docker-compose.yml 파일에 서비스(services), 네트워크(networks), 볼륨(volumes)을 선언적으로 정의하면, Docker Compose가 자동으로 컨테이너를 생성하고 연결합니다.

이 과정에서는 Docker Compose의 설치 방법부터 시작하여, docker-compose.yml 파일의 구조와 작성 방법을 학습합니다. services 섹션에서 각 컨테이너의 이미지, 포트, 환경 변수, 볼륨 등을 정의하고, networks 섹션에서 컨테이너 간 통신을 설정하며, volumes 섹션에서 데이터 영속성을 관리하는 방법을 익힙니다.

또한 docker-compose 명령어(up, down, ps, logs, scale, exec 등)를 통해 전체 애플리케이션 스택을 효율적으로 관리하는 방법을 배웁니다. WordPress + MySQL 조합, Django + PostgreSQL 조합 등 실전 예제를 통해 실무에서 즉시 활용 가능한 멀티 컨테이너 환경 구축 능력을 갖추게 됩니다.

Docker Compose를 마스터하면 개발 환경 구축 시간을 대폭 단축하고, 팀원 간 환경 일관성을 보장하며, 운영 환경으로의 배포를 표준화할 수 있습니다.


1. Docker Compose 개요

1-1. Docker Compose란?

Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 실행하는 도구입니다. YAML 형식의 설정 파일(docker-compose.yml)로 전체 애플리케이션 스택을 선언적으로 관리합니다.

Docker Compose의 핵심 개념:

graph TD
    A[docker-compose.yml] --> B[Services]
    A --> C[Networks]
    A --> D[Volumes]

    B --> B1[웹 서버 컨테이너]
    B --> B2[앱 서버 컨테이너]
    B --> B3[DB 컨테이너]

    C --> C1[사용자 정의 네트워크]
    D --> D1[데이터 영속성 볼륨]
구성 요소 설명
Services 애플리케이션을 구성하는 각 컨테이너 (웹, DB, 캐시 등)
Networks 컨테이너 간 통신 네트워크
Volumes 데이터 영속성을 위한 볼륨

1-2. Docker Compose를 사용하는 이유

Docker Compose 없이 (수동 관리):

# 네트워크 생성
$ docker network create myapp-net

# 볼륨 생성
$ docker volume create myapp-db-data

# 데이터베이스 컨테이너 실행
$ docker container run -d \
  --name db \
  --network myapp-net \
  -v myapp-db-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  mysql:8.0

# 웹 서버 컨테이너 실행
$ docker container run -d \
  --name web \
  --network myapp-net \
  -p 80:80 \
  -e DB_HOST=db \
  -e DB_PASSWORD=secret \
  myapp:latest

Docker Compose 사용:

# docker-compose.yml
version: '3.8'

services:
  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: myapp

  web:
    image: myapp:latest
    ports:
      - "80:80"
    environment:
      DB_HOST: db
      DB_PASSWORD: secret
    depends_on:
      - db

volumes:
  db-data:
# 전체 스택 시작
$ docker-compose up -d

Docker Compose의 장점:

장점 설명
선언적 관리 YAML 파일로 전체 구성 정의
간편한 명령어 up, down 등 단일 명령어로 전체 제어
환경 일관성 개발/테스트/운영 환경 표준화
버전 관리 Git으로 인프라 코드 관리
자동 네트워킹 서비스 간 자동 DNS 해석
의존성 관리 depends_on으로 시작 순서 제어

1-3. Docker Compose 사용 사례

사용 사례 예시
개발 환경 로컬에서 전체 스택 실행
테스트 환경 CI/CD 파이프라인에서 통합 테스트
소규모 운영 단일 호스트에서 운영 (Kubernetes 대안)
데모/프로토타입 빠른 환경 구축

2. Docker Compose 설치

2-1. 설치 확인

Docker Desktop(Windows/Mac)을 사용하는 경우 Docker Compose가 기본 포함되어 있습니다.

$ docker-compose --version
Docker Compose version v2.21.0

2-2. Linux에서 설치

방법 1: Docker Compose V2 (권장)

Docker Compose V2는 Docker CLI 플러그인 형태로 제공됩니다.

# Docker 공식 저장소에서 설치 (Docker Engine과 함께 설치됨)
$ sudo apt-get update
$ sudo apt-get install docker-compose-plugin

# 설치 확인 (docker compose 명령어 사용)
$ docker compose version
Docker Compose version v2.21.0

방법 2: Docker Compose V1 (레거시)

# 바이너리 다운로드
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" \
  -o /usr/local/bin/docker-compose

# 실행 권한 부여
$ sudo chmod +x /usr/local/bin/docker-compose

# 심볼릭 링크 생성 (선택)
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

# 설치 확인 (docker-compose 명령어 사용)
$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c

V1 vs V2 명령어 차이:

버전 명령어 형식 예시
V1 docker-compose docker-compose up -d
V2 docker compose docker compose up -d

참고: 본 문서에서는 V2 문법(docker compose)을 사용하지만, V1 문법(docker-compose)도 동일하게 작동합니다.


3. docker-compose.yml 파일 구조

3-1. 기본 구조

docker-compose.yml은 크게 세 가지 섹션으로 구성됩니다:

version: '3.8'    # Compose 파일 버전

services:         # 컨테이너 정의
  service1:
    # 서비스 설정
  service2:
    # 서비스 설정

networks:         # 네트워크 정의 (선택)
  network1:
    # 네트워크 설정

volumes:          # 볼륨 정의 (선택)
  volume1:
    # 볼륨 설정

3-2. version 지정

Compose 파일 버전:

버전 Docker Engine 특징
3.8 19.03.0+ 최신 권장 버전
3.7 18.06.0+ 널리 사용됨
3.0 1.13.0+ 기본 기능
2.4 17.12.0+ 레거시 (V2 형식)
version: '3.8'

참고: Compose V2부터는 version 필드가 선택 사항이지만, 호환성을 위해 명시하는 것을 권장합니다.


4. Services 정의

4-1. 기본 서비스 정의

services:
  web:
    image: nginx:alpine        # 사용할 이미지
    container_name: my-web     # 컨테이너 이름 (선택)
    ports:                     # 포트 매핑
      - "8080:80"
    environment:               # 환경 변수
      - ENV=production
    volumes:                   # 볼륨 마운트
      - ./html:/usr/share/nginx/html
    restart: always            # 재시작 정책

4-2. 주요 서비스 옵션

📟 image vs build

image: Docker Hub 등에서 이미지를 가져옵니다.

services:
  web:
    image: nginx:1.21-alpine

build: Dockerfile로 이미지를 빌드합니다.

services:
  app:
    build:
      context: ./app            # Dockerfile 경로
      dockerfile: Dockerfile    # Dockerfile 이름 (기본값: Dockerfile)
      args:                     # 빌드 인자
        VERSION: 1.0

혼합 사용:

services:
  app:
    build: ./app
    image: myapp:latest    # 빌드 후 이미지 이름

📟 ports (포트 매핑)

기본 문법:

ports:
  - "HOST_PORT:CONTAINER_PORT"

예제:

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"              # 호스트 8080 → 컨테이너 80
      - "8443:443"             # 호스트 8443 → 컨테이너 443
      - "127.0.0.1:3000:3000"  # 로컬호스트만 접근 가능
      - "3000-3005:3000-3005"  # 범위 지정

포트 노출 (expose):

services:
  app:
    image: myapp:latest
    expose:
      - "8080"    # 다른 서비스에만 노출 (호스트에는 노출 안 됨)

📟 environment (환경 변수)

배열 형식:

services:
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=user
      - MYSQL_PASSWORD=pass

객체 형식:

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: mydb
      MYSQL_USER: user
      MYSQL_PASSWORD: pass

환경 변수 파일 (.env):

# docker-compose.yml
services:
  app:
    image: myapp:latest
    env_file:
      - .env
      - .env.local
# .env 파일
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=user
DB_PASSWORD=secret

📟 volumes (볼륨 마운트)

Bind Mount (호스트 경로 → 컨테이너):

services:
  web:
    image: nginx:alpine
    volumes:
      - ./html:/usr/share/nginx/html          # 상대 경로
      - /var/log/nginx:/var/log/nginx         # 절대 경로
      - ./config/nginx.conf:/etc/nginx/nginx.conf:ro  # 읽기 전용

Named Volume (Docker 관리 볼륨):

services:
  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql    # 최상위 volumes에 정의 필요

volumes:
  db-data:    # 볼륨 정의

tmpfs Mount (임시 파일시스템):

services:
  app:
    image: myapp:latest
    tmpfs:
      - /tmp
      - /run

📟 depends_on (의존성 관리)

기본 사용:

services:
  web:
    image: nginx:alpine
    depends_on:
      - app
      - db    # app, db가 시작된 후 web 시작

  app:
    image: myapp:latest
    depends_on:
      - db    # db가 시작된 후 app 시작

  db:
    image: mysql:8.0

시작 순서:

db → app → web

주의: depends_on은 컨테이너 시작 순서만 제어하며, 애플리케이션이 준비될 때까지 대기하지 않습니다. 예를 들어, DB 컨테이너는 시작되었지만 MySQL이 완전히 초기화되기 전에 app이 접속을 시도할 수 있습니다.

헬스체크 기반 대기 (Compose V3.8+):

services:
  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  app:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy    # db가 healthy 상태가 될 때까지 대기

📟 restart (재시작 정책)

services:
  web:
    image: nginx:alpine
    restart: always
옵션 설명
no 재시작 안 함 (기본값)
always 항상 재시작
on-failure 오류 종료 시에만 재시작
unless-stopped 수동 중지가 아닌 경우 재시작

📟 networks (네트워크 연결)

services:
  web:
    image: nginx:alpine
    networks:
      - frontend

  app:
    image: myapp:latest
    networks:
      - frontend
      - backend

  db:
    image: mysql:8.0
    networks:
      - backend

networks:
  frontend:
  backend:

네트워크 격리:

web (frontend) ←→ app (frontend + backend) ←→ db (backend)
web ←X→ db (직접 통신 불가)

📟 기타 유용한 옵션

command: 컨테이너 시작 명령어 오버라이드

services:
  app:
    image: python:3.9
    command: python app.py --debug

working_dir: 작업 디렉토리 설정

services:
  app:
    image: node:16
    working_dir: /app

user: 실행 사용자 지정

services:
  app:
    image: myapp:latest
    user: "1000:1000"

stdin_open / tty: 인터랙티브 모드

services:
  ubuntu:
    image: ubuntu:20.04
    stdin_open: true    # -i
    tty: true           # -t

labels: 메타데이터 추가

services:
  web:
    image: nginx:alpine
    labels:
      com.example.description: "Web Server"
      com.example.version: "1.0"

5. Networks 정의

5-1. 기본 네트워크

Docker Compose는 기본적으로 프로젝트별 브리지 네트워크를 자동 생성합니다.

version: '3.8'

services:
  web:
    image: nginx:alpine
  db:
    image: mysql:8.0

생성되는 네트워크:

{프로젝트명}_default

서비스 간 통신:

# web 컨테이너에서 db 컨테이너로 접속
$ docker compose exec web ping db
PING db (172.18.0.2): 56 data bytes

자동 DNS 해석: 서비스 이름(db)으로 다른 컨테이너에 접근 가능합니다.

5-2. 사용자 정의 네트워크

version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      - frontend

  app:
    image: myapp:latest
    networks:
      - frontend
      - backend

  db:
    image: mysql:8.0
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.100.0/24

5-3. 외부 네트워크 사용

services:
  web:
    image: nginx:alpine
    networks:
      - existing-network

networks:
  existing-network:
    external: true    # 기존 네트워크 사용

6. Volumes 정의

6-1. Named Volume

version: '3.8'

services:
  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:    # Docker가 관리하는 볼륨

볼륨 확인:

$ docker volume ls
DRIVER    VOLUME NAME
local     myproject_db-data

6-2. 외부 볼륨 사용

volumes:
  db-data:
    external: true    # 기존 볼륨 사용

6-3. 볼륨 드라이버 지정

volumes:
  db-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.100,rw
      device: ":/path/to/dir"

7. Docker Compose 명령어

7-1. 주요 명령어

📟 docker compose up 명령어

목적: 서비스를 생성하고 시작합니다.

기본 문법:

docker compose up [OPTIONS] [SERVICE...]

주요 옵션:

옵션 의미 예시
-d 백그라운드 실행 docker compose up -d
--build 이미지 강제 재빌드 docker compose up --build
--force-recreate 컨테이너 강제 재생성 docker compose up --force-recreate
--scale 서비스 인스턴스 수 지정 docker compose up --scale web=3
--no-deps 연결된 서비스 시작 안 함 docker compose up --no-deps web

실행 예제:

# 전체 서비스 시작 (포그라운드)
$ docker compose up

# 백그라운드 시작
$ docker compose up -d

# 특정 서비스만 시작
$ docker compose up -d web db

# 이미지 재빌드 후 시작
$ docker compose up -d --build

예상 출력:

[+] Running 3/3
 ✔ Network myapp_default    Created
 ✔ Container myapp-db-1     Started
 ✔ Container myapp-web-1    Started

📟 docker compose down 명령어

목적: 서비스를 중지하고 리소스를 제거합니다.

기본 문법:

docker compose down [OPTIONS]

주요 옵션:

옵션 의미 예시
-v 볼륨도 함께 삭제 docker compose down -v
--rmi 이미지도 삭제 (all 또는 local) docker compose down --rmi all
--remove-orphans 고아 컨테이너 제거 docker compose down --remove-orphans

실행 예제:

# 컨테이너, 네트워크 제거
$ docker compose down

# 볼륨도 함께 제거
$ docker compose down -v

# 이미지까지 제거
$ docker compose down --rmi all

예상 출력:

[+] Running 3/3
 ✔ Container myapp-web-1    Removed
 ✔ Container myapp-db-1     Removed
 ✔ Network myapp_default    Removed

📟 docker compose ps 명령어

목적: 실행 중인 서비스 목록을 표시합니다.

실행 예제:

$ docker compose ps

예상 출력:

NAME            IMAGE         COMMAND                  SERVICE   CREATED         STATUS         PORTS
myapp-db-1      mysql:8.0     "docker-entrypoint.s…"   db        2 minutes ago   Up 2 minutes   3306/tcp, 33060/tcp
myapp-web-1     nginx:alpine  "/docker-entrypoint.…"   web       2 minutes ago   Up 2 minutes   0.0.0.0:8080->80/tcp

전체 컨테이너 (중지 포함):

$ docker compose ps -a

📟 docker compose logs 명령어

목적: 서비스 로그를 확인합니다.

기본 문법:

docker compose logs [OPTIONS] [SERVICE...]

주요 옵션:

옵션 의미 예시
-f 실시간 로그 스트림 docker compose logs -f
--tail 마지막 N줄만 표시 docker compose logs --tail=100
-t 타임스탬프 표시 docker compose logs -t

실행 예제:

# 전체 서비스 로그
$ docker compose logs

# 특정 서비스 로그
$ docker compose logs web

# 실시간 로그
$ docker compose logs -f web

# 마지막 50줄 + 실시간
$ docker compose logs -f --tail=50 web

📟 docker compose exec 명령어

목적: 실행 중인 서비스에서 명령어를 실행합니다.

기본 문법:

docker compose exec [OPTIONS] SERVICE COMMAND [ARGS...]

실행 예제:

# web 서비스에서 bash 실행
$ docker compose exec web /bin/bash

# db 서비스에서 MySQL 접속
$ docker compose exec db mysql -u root -p

# 환경 변수 확인
$ docker compose exec web env

📟 docker compose restart 명령어

목적: 서비스를 재시작합니다.

실행 예제:

# 전체 서비스 재시작
$ docker compose restart

# 특정 서비스 재시작
$ docker compose restart web

📟 docker compose stop / start 명령어

목적: 서비스를 중지/시작합니다 (리소스는 유지).

실행 예제:

# 전체 서비스 중지
$ docker compose stop

# 특정 서비스 중지
$ docker compose stop web

# 서비스 시작
$ docker compose start web

📟 docker compose build 명령어

목적: 서비스 이미지를 빌드합니다.

기본 문법:

docker compose build [OPTIONS] [SERVICE...]

주요 옵션:

옵션 의미 예시
--no-cache 캐시 사용 안 함 docker compose build --no-cache
--pull 베이스 이미지 최신 버전 가져오기 docker compose build --pull

실행 예제:

# 전체 서비스 빌드
$ docker compose build

# 특정 서비스 빌드
$ docker compose build app

# 캐시 없이 빌드
$ docker compose build --no-cache app

📟 docker compose pull 명령어

목적: 서비스 이미지를 다운로드합니다.

실행 예제:

# 전체 서비스 이미지 pull
$ docker compose pull

# 특정 서비스 이미지 pull
$ docker compose pull web

📟 docker compose config 명령어

목적: Compose 파일의 설정을 검증하고 출력합니다.

실행 예제:

# 설정 검증 및 출력
$ docker compose config

# 서비스 목록만 출력
$ docker compose config --services

# 볼륨 목록만 출력
$ docker compose config --volumes

8. 실전 예제

8-1. WordPress + MySQL

디렉토리 구조

wordpress-stack/
├── docker-compose.yml
└── .env

docker-compose.yml

version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: wordpress-db
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    networks:
      - backend
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    container_name: wordpress-app
    depends_on:
      - db
    ports:
      - "${WP_PORT:-8080}:80"
    volumes:
      - wp-data:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    networks:
      - backend
      - frontend
    restart: unless-stopped

networks:
  frontend:
  backend:

volumes:
  db-data:
  wp-data:

.env 파일

# .env
DB_ROOT_PASSWORD=rootpass123
DB_NAME=wordpress
DB_USER=wpuser
DB_PASSWORD=wppass123
WP_PORT=8080

실행

# 서비스 시작
$ docker compose up -d

# 상태 확인
$ docker compose ps

# 로그 확인
$ docker compose logs -f wordpress

# 브라우저에서 접속
# http://localhost:8080

중지 및 삭제

# 중지 (볼륨 유지)
$ docker compose down

# 중지 + 볼륨 삭제
$ docker compose down -v

8-2. Django + PostgreSQL + Redis

디렉토리 구조

django-stack/
├── app/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── manage.py
├── docker-compose.yml
└── .env

Dockerfile (app/Dockerfile)

FROM python:3.9-slim

WORKDIR /app

# 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 애플리케이션 코드
COPY . .

# 포트 노출
EXPOSE 8000

# 실행
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "myproject.wsgi:application"]

docker-compose.yml

version: '3.8'

services:
  db:
    image: postgres:14-alpine
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    networks:
      - backend
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: unless-stopped

  web:
    build:
      context: ./app
    command: >
      sh -c "python manage.py migrate &&
             gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application"
    volumes:
      - ./app:/app
      - static-data:/app/static
      - media-data:/app/media
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
      REDIS_URL: redis://redis:6379/0
      DEBUG: ${DEBUG}
    depends_on:
      - db
      - redis
    networks:
      - backend
      - frontend
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - static-data:/app/static:ro
      - media-data:/app/media:ro
    ports:
      - "80:80"
    depends_on:
      - web
    networks:
      - frontend
    restart: unless-stopped

networks:
  frontend:
  backend:

volumes:
  postgres-data:
  redis-data:
  static-data:
  media-data:

.env 파일

# .env
DB_NAME=django_db
DB_USER=django_user
DB_PASSWORD=django_pass123
DEBUG=False

실행

# 이미지 빌드 및 서비스 시작
$ docker compose up -d --build

# 로그 확인
$ docker compose logs -f web

# Django 관리 명령어 실행
$ docker compose exec web python manage.py createsuperuser

# 브라우저에서 접속
# http://localhost

8-3. 마이크로서비스 스택 (Node.js + Python + MongoDB + RabbitMQ)

docker-compose.yml

version: '3.8'

services:
  # 메시지 큐
  rabbitmq:
    image: rabbitmq:3-management-alpine
    ports:
      - "5672:5672"
      - "15672:15672"    # 관리 UI
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin123
    networks:
      - backend
    restart: unless-stopped

  # 데이터베이스
  mongodb:
    image: mongo:5
    volumes:
      - mongo-data:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: rootpass123
    networks:
      - backend
    restart: unless-stopped

  # API Gateway (Node.js)
  api-gateway:
    build: ./api-gateway
    ports:
      - "3000:3000"
    environment:
      RABBITMQ_URL: amqp://admin:admin123@rabbitmq:5672
      MONGODB_URL: mongodb://root:rootpass123@mongodb:27017
    depends_on:
      - rabbitmq
      - mongodb
    networks:
      - frontend
      - backend
    restart: unless-stopped

  # 데이터 처리 서비스 (Python)
  data-processor:
    build: ./data-processor
    environment:
      RABBITMQ_URL: amqp://admin:admin123@rabbitmq:5672
      MONGODB_URL: mongodb://root:rootpass123@mongodb:27017
    depends_on:
      - rabbitmq
      - mongodb
    networks:
      - backend
    restart: unless-stopped
    deploy:
      replicas: 2    # 2개 인스턴스 실행

  # 모니터링 (Prometheus + Grafana)
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    networks:
      - monitoring
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    volumes:
      - grafana-data:/var/lib/grafana
    ports:
      - "3001:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin123
    depends_on:
      - prometheus
    networks:
      - monitoring
    restart: unless-stopped

networks:
  frontend:
  backend:
  monitoring:

volumes:
  mongo-data:
  prometheus-data:
  grafana-data:

9. Docker Compose 고급 기능

9-1. 스케일링 (replicas)

Compose 파일에서:

services:
  worker:
    image: myworker:latest
    deploy:
      replicas: 3    # 3개 인스턴스

명령어로:

$ docker compose up -d --scale worker=5

9-2. 환경별 설정 (override)

기본 설정 (docker-compose.yml):

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"

개발 환경 (docker-compose.override.yml):

version: '3.8'

services:
  web:
    volumes:
      - ./html:/usr/share/nginx/html    # 개발 시 실시간 반영
    environment:
      - DEBUG=true

프로덕션 환경 (docker-compose.prod.yml):

version: '3.8'

services:
  web:
    restart: always
    environment:
      - DEBUG=false

실행:

# 개발 환경 (자동으로 override.yml 병합)
$ docker compose up -d

# 프로덕션 환경
$ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

9-3. 헬스체크

services:
  web:
    image: nginx:alpine
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

9-4. 리소스 제한

services:
  app:
    image: myapp:latest
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

주요 개념 요약표

구분 주요 개념 설명
Compose 구성 services 컨테이너 정의
  networks 네트워크 정의
  volumes 볼륨 정의
서비스 옵션 image / build 이미지 지정 또는 빌드
  ports 포트 매핑 (호스트:컨테이너)
  environment 환경 변수 설정
  volumes 볼륨 마운트 (bind mount / named volume)
  depends_on 의존성 관리 (시작 순서)
  restart 재시작 정책 (always, on-failure 등)
주요 명령어 docker compose up 서비스 생성 및 시작
  docker compose down 서비스 중지 및 리소스 제거
  docker compose ps 서비스 목록 확인
  docker compose logs 로그 확인
  docker compose exec 서비스에서 명령어 실행
  docker compose build 이미지 빌드
  docker compose restart 서비스 재시작
고급 기능 스케일링 replicas 또는 –scale 옵션
  환경별 설정 override 파일 사용
  헬스체크 healthcheck 정의
  리소스 제한 CPU, 메모리 제한 설정

마무리

이번 Part 5에서는 Docker Compose를 이용한 멀티 컨테이너 애플리케이션 관리를 완전히 마스터했습니다. docker-compose.yml 파일의 구조를 이해하고, services, networks, volumes 섹션을 정의하는 방법을 배웠습니다. image, ports, environment, volumes, depends_on 등 핵심 서비스 옵션을 실습하며 각 옵션의 역할과 활용법을 익혔습니다.

docker compose up/down, ps, logs, exec 등 주요 명령어를 통해 전체 애플리케이션 스택을 효율적으로 제어하는 방법을 배웠으며, WordPress + MySQL, Django + PostgreSQL + Redis, 마이크로서비스 스택 등 실전 예제를 통해 실무에서 즉시 활용 가능한 구성 패턴을 익혔습니다.

Docker Compose의 고급 기능(스케일링, 환경별 설정, 헬스체크, 리소스 제한)을 학습하여 개발 환경과 운영 환경을 유연하게 관리할 수 있게 되었습니다. .env 파일을 활용한 환경 변수 관리, override 파일을 이용한 환경별 설정 분리 등 프로덕션 환경에 적합한 베스트 프랙티스도 함께 배웠습니다.

Docker 시리즈 전체(Part 1~5)를 마무리하며:

  • Part 1: Docker 개념, 설치, VM vs Container 비교
  • Part 2: 이미지와 컨테이너 기본 명령어
  • Part 3: 볼륨과 네트워크를 통한 데이터 영속성 및 통신
  • Part 4: Dockerfile을 이용한 사용자 정의 이미지 빌드
  • Part 5: Docker Compose를 통한 멀티 컨테이너 오케스트레이션

Docker를 활용하여 개발 환경 구축, 애플리케이션 배포, 인프라 관리를 효율적으로 수행할 수 있는 역량을 갖추었습니다. Docker Compose로 정의한 애플리케이션 스택은 팀원 간 공유가 용이하고, 환경 간 이동이 간편하며, CI/CD 파이프라인에 통합하기 쉽습니다.

댓글 남기기