Docker Compose YAML 파일 내부 구조
전체 구조 개요
version: '3.8' # Compose 파일 포맷 버전
# 최상위 섹션들
services: # 컨테이너 서비스 정의 (필수)
service_name:
# 서비스 설정
volumes: # 볼륨 정의 (선택)
volume_name:
# 볼륨 설정
networks: # 네트워크 정의 (선택)
network_name:
# 네트워크 설정
configs: # 설정 파일 정의 (선택)
config_name:
# 설정 파일
secrets: # 시크릿 정의 (선택)
secret_name:
# 시크릿 설정
# YAML 확장 기능
x-custom: # 커스텀 확장 (재사용)
&anchor: value
include: # 다른 파일 포함 (Compose 2.20+)
- path/to/other.yml
1. version (버전 지정)
version: '3.8' # 권장 버전
# version: '3.9' # 최신 기능 사용시
# version: '2.4' # 레거시 지원
주요 버전:
3.8
: 가장 널리 사용, 안정적3.9
: 최신 기능 포함2.x
: 레거시 (비추천)
2. services (서비스 정의) - 핵심!
2-1. 기본 서비스 구조
services:
service_name: # 서비스 이름 (자유롭게 정의)
# 이미지 관련
image: nginx:latest # Docker Hub 이미지
build: # 또는 Dockerfile로 빌드
context: .
dockerfile: Dockerfile
# 컨테이너 설정
container_name: my-nginx # 컨테이너 이름
hostname: web-server # 호스트명
# 포트 매핑
ports:
- "80:80" # 호스트:컨테이너
- "443:443"
# 볼륨 마운트
volumes:
- ./data:/app/data # Bind mount
- app_data:/app/storage # Named volume
# 환경변수
environment:
- NODE_ENV=production
- API_KEY=secret
env_file:
- .env
# 네트워크
networks:
- frontend
- backend
# 의존성
depends_on:
- database
- redis
# 재시작 정책
restart: unless-stopped
# 실행 명령어
command: npm start
entrypoint: /docker-entrypoint.sh
# 작업 디렉토리
working_dir: /app
# 사용자
user: "1000:1000"
# 리소스 제한
deploy:
resources:
limits:
memory: 512M
cpus: "0.5"
# 헬스체크
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
# 기타
labels:
- "com.example.description=Web server"
privileged: false
stdin_open: true # -i 옵션
tty: true # -t 옵션
2-2. 이미지 관련 옵션
services:
# 방법 1: 기존 이미지 사용
app1:
image: nginx:1.21-alpine # 이미지:태그
# 방법 2: Dockerfile로 빌드
app2:
build: . # 현재 디렉토리의 Dockerfile
# 방법 3: 상세 빌드 설정
app3:
build:
context: ./app # 빌드 컨텍스트
dockerfile: Dockerfile.prod # Dockerfile 경로
target: production # 멀티스테이지 빌드 타겟
args: # 빌드 인수
- NODE_ENV=production
- VERSION=1.0.0
cache_from: # 캐시 소스
- alpine:latest
labels: # 이미지 라벨
version: "1.0"
2-3. 포트 매핑 옵션
services:
web:
ports:
- "80:80" # 호스트:컨테이너
- "127.0.0.1:8080:80" # IP:호스트포트:컨테이너포트
- "3000" # 컨테이너 포트만 (랜덤 호스트 포트)
- "3000-3005:3000-3005" # 포트 범위
expose: # 다른 서비스에만 노출 (호스트 노출 안함)
- "8080"
- "9000"
2-4. 볼륨 마운트 옵션
services:
app:
volumes:
# Bind Mount
- ./data:/app/data # 호스트경로:컨테이너경로
- ./config:/app/config:ro # 읽기 전용
- ${HOME}/logs:/app/logs # 환경변수 사용
# Named Volume
- app_data:/app/data # 볼륨명:컨테이너경로
- app_cache:/app/cache:rw # 읽기/쓰기 (기본값)
# Anonymous Volume
- /app/node_modules # 컨테이너 경로만
# tmpfs (메모리)
- type: tmpfs
target: /app/tmp
tmpfs:
size: 100M
# 상세 마운트 설정
- type: bind
source: ./data
target: /app/data
read_only: true
2-5. 환경변수 설정
services:
app:
environment:
# 방법 1: 키=값
- NODE_ENV=production
- DEBUG=true
- PORT=3000
# 방법 2: 맵 형태
NODE_ENV: production
DEBUG: "true" # YAML에서 문자열로 처리
API_URL: "https://api.example.com"
env_file: # 환경변수 파일
- .env # 기본 파일
- .env.local # 추가 파일
- ./config/app.env # 경로 지정
2-6. 네트워크 설정
services:
web:
networks:
- frontend # 네트워크 이름만
- backend
api:
networks:
frontend: # 상세 설정
aliases:
- api-server
ipv4_address: 172.20.0.5
backend:
priority: 1000
2-7. 의존성 관리
services:
web:
depends_on:
- database # 기본 의존성
- redis
api:
depends_on: # 상세 의존성 (Compose 3.8+)
database:
condition: service_healthy
redis:
condition: service_started
restart: true
2-8. 헬스체크
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s # 검사 간격
timeout: 10s # 타임아웃
retries: 3 # 재시도 횟수
start_period: 30s # 시작 대기 시간
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
app:
healthcheck:
disable: true # 헬스체크 비활성화
2-9. 리소스 제한
services:
app:
deploy:
resources:
limits:
cpus: '0.50' # CPU 제한
memory: 512M # 메모리 제한
reservations:
cpus: '0.25' # CPU 예약
memory: 256M # 메모리 예약
# 또는 간단한 메모리 제한
mem_limit: 512m
memswap_limit: 1g
# CPU 제한
cpus: 0.5
cpu_shares: 512
2-10. 프로파일 사용
services:
# 항상 실행되는 서비스
app:
image: myapp:latest
# 개발환경에서만 실행
redis:
profiles: ["dev", "test"]
image: redis:6
# 모니터링 프로파일
prometheus:
profiles: ["monitoring"]
image: prom/prometheus
grafana:
profiles: ["monitoring"]
image: grafana/grafana
3. volumes (볼륨 정의)
volumes:
# 기본 Named Volume
app_data:
# 상세 설정
postgres_data:
driver: local # 볼륨 드라이버
driver_opts:
type: none
o: bind
device: /path/to/data
# 외부 볼륨 (이미 존재하는 볼륨)
existing_volume:
external: true
name: my-existing-volume
# 라벨 추가
app_cache:
labels:
- "com.example.description=Application cache"
- "com.example.team=backend"
4. networks (네트워크 정의)
networks:
# 기본 네트워크
frontend:
# 상세 설정
backend:
driver: bridge # 네트워크 드라이버
ipam: # IP 관리
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
driver_opts:
com.docker.network.bridge.name: backend-bridge
# 외부 네트워크 (이미 존재)
existing_network:
external: true
name: my-existing-network
# 호스트 네트워크
host_network:
external: true
name: host
5. configs (설정 파일)
configs:
# 파일에서 설정 로드
nginx_config:
file: ./nginx/nginx.conf
# 외부 설정
app_config:
external: true
name: production_config
services:
web:
configs:
- source: nginx_config
target: /etc/nginx/nginx.conf
mode: 0644
6. secrets (시크릿)
secrets:
# 파일에서 시크릿 로드
db_password:
file: ./secrets/db_password.txt
# 외부 시크릿
api_key:
external: true
name: production_api_key
services:
app:
secrets:
- db_password
- source: api_key
target: /run/secrets/api_key
mode: 0400
7. YAML 확장 기능
7-1. Anchors & Aliases (재사용)
# 공통 설정 정의
x-common-config: &common
restart: unless-stopped
networks:
- app-network
environment:
- TZ=Asia/Seoul
x-database-config: &db-config
<<: *common # 공통 설정 상속
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=myapp
services:
web:
<<: *common # 공통 설정 적용
image: nginx
db:
<<: *db-config # DB 설정 적용
image: postgres:13
7-2. Extension Fields (확장 필드)
# x-로 시작하는 필드는 Docker에서 무시됨 (사용자 정의용)
x-logging: &default-logging
driver: json-file
options:
max-size: 10m
max-file: 3
x-healthcheck: &default-healthcheck
interval: 30s
timeout: 10s
retries: 3
services:
web:
image: nginx
logging: *default-logging
healthcheck:
<<: *default-healthcheck
test: ["CMD", "nginx", "-t"]
8. 완전한 예시
version: '3.8'
# 재사용 가능한 설정들
x-common: &common-config
restart: unless-stopped
networks:
- app-network
environment:
- TZ=Asia/Seoul
logging:
driver: json-file
options:
max-size: 10m
max-file: 3
services:
# 웹 서버
nginx:
<<: *common-config
image: nginx:1.21-alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- static_files:/var/www/html
depends_on:
- app
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 30s
timeout: 10s
retries: 3
# 애플리케이션
app:
<<: *common-config
build:
context: .
dockerfile: Dockerfile
target: production
args:
- NODE_ENV=production
container_name: node-app
environment:
- NODE_ENV=production
- DB_HOST=postgres
- REDIS_HOST=redis
env_file:
- .env
volumes:
- app_data:/app/data
- static_files:/app/public
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
# 데이터베이스
postgres:
<<: *common-config
image: postgres:13-alpine
container_name: postgres-db
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 5s
timeout: 5s
retries: 5
# 캐시
redis:
<<: *common-config
image: redis:6-alpine
container_name: redis-cache
volumes:
- redis_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
command: redis-server /usr/local/etc/redis/redis.conf
# 모니터링 (프로파일 사용)
prometheus:
profiles: ["monitoring"]
<<: *common-config
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
volumes:
app_data:
labels:
- "com.example.description=Application data"
postgres_data:
driver: local
redis_data:
static_files:
prometheus_data:
external: true # 외부에서 관리되는 볼륨
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
configs:
nginx_config:
file: ./nginx/nginx.conf
secrets:
db_password:
file: ./secrets/db_password.txt
이것이 Docker Compose YAML 파일에서 정의할 수 있는 모든 구조와 옵션들입니다! 🚀