Docker Compose
YAML 하나로 다중 컨테이너 정의 및 관리
📚 시리즈 네비게이션
| 이전 | 현재 | 다음 |
|---|---|---|
| Volume & Network | Docker Compose | Docker vs Podman |
→ 시리즈 목차
🎯 Docker Compose란?
다중 컨테이너 애플리케이션을 정의하고 실행하는 도구.
docker run 여러 번 vs docker compose up
─────────────────────────────────────────────────────────────────────
docker network create mynet compose.yaml 하나로
docker run -d --name db ... 전체 환경 정의
docker run -d --name app ...
docker run -d --name web ...
📦 설치
Docker Desktop에는 기본 포함. Linux 서버는 별도 설치.
# Docker Compose v2 (플러그인 방식)
# Docker 설치 시 함께 설치됨
# 확인
docker compose version
# Docker Compose version v2.x.xNote:
docker-compose(하이픈) →docker compose(스페이스)로 변경됨.
📝 compose.yaml 기본 구조
# compose.yaml (또는 docker-compose.yml)
services:
web:
image: nginx:alpine
ports:
- "8080:80"
app:
build: ./app
environment:
- DB_HOST=db
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
networks:
default:
driver: bridge최상위 요소
| 요소 | 설명 |
|---|---|
services | 컨테이너 정의 |
volumes | 볼륨 정의 |
networks | 네트워크 정의 |
configs | 설정 파일 (Swarm) |
secrets | 비밀 데이터 (Swarm) |
🔧 services 상세
image vs build
services:
# 이미지 사용
web:
image: nginx:alpine
# Dockerfile로 빌드
app:
build: ./app
# 또는 상세 설정
build:
context: ./app
dockerfile: Dockerfile.prod
args:
- VERSION=1.0.0ports
services:
web:
ports:
- "8080:80" # 호스트:컨테이너
- "8443:443"
- "127.0.0.1:8080:80" # 특정 IP
- "3000" # 랜덤 호스트 포트environment
services:
app:
environment:
# 리스트 형식
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=3306
# 또는 맵 형식
environment:
NODE_ENV: production
DB_HOST: db
DB_PORT: 3306env_file
services:
app:
env_file:
- .env
- .env.local# .env
DB_HOST=db
DB_PORT=3306
DB_PASSWORD=secretvolumes
services:
app:
volumes:
# Named volume
- app-data:/data
# Bind mount
- ./src:/app/src
- ./config:/app/config:ro # 읽기 전용
# Anonymous volume
- /app/node_modules
volumes:
app-data:networks
services:
web:
networks:
- frontend
app:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:depends_on
services:
app:
depends_on:
- db
- redis
# 시작 순서만 보장, 준비 완료는 보장 안 함
# 조건부 (healthcheck 필요)
app:
depends_on:
db:
condition: service_healthyhealthcheck
services:
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30srestart
services:
app:
restart: always
# no (기본), always, on-failure, unless-stopped| 값 | 설명 |
|---|---|
no | 재시작 안 함 (기본) |
always | 항상 재시작 |
on-failure | 실패 시 재시작 |
unless-stopped | 수동 중지 전까지 재시작 |
리소스 제한
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M🚀 주요 명령어
기본 명령어
# 시작 (백그라운드)
docker compose up -d
# 중지
docker compose down
# 중지 + 볼륨 삭제
docker compose down -v
# 로그
docker compose logs
docker compose logs -f # 실시간
docker compose logs app # 특정 서비스
# 상태 확인
docker compose ps
# 실행 중인 서비스에 명령어 실행
docker compose exec app sh
docker compose exec db mysql -u root -p빌드 관련
# 빌드
docker compose build
# 빌드 후 시작
docker compose up -d --build
# 특정 서비스만 빌드
docker compose build app
# 캐시 없이 빌드
docker compose build --no-cache스케일링
# 특정 서비스 여러 개 실행
docker compose up -d --scale app=3
# 확인
docker compose ps기타
# 설정 확인 (문법 검증)
docker compose config
# 이미지 pull
docker compose pull
# 서비스 재시작
docker compose restart
docker compose restart app
# 특정 서비스만 시작
docker compose up -d db🎯 실습: WordPress + MySQL
compose.yaml
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress-data:/var/www/html
depends_on:
- db
restart: always
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- db-data:/var/lib/mysql
restart: always
volumes:
wordpress-data:
db-data:실행
# 시작
docker compose up -d
# 확인
docker compose ps
docker compose logs -f
# 브라우저에서 http://localhost:8080 접속
# 중지
docker compose down
# 볼륨까지 삭제 (데이터 삭제)
docker compose down -v🎯 실습: Node.js + Redis + Nginx
프로젝트 구조
myapp/
├── compose.yaml
├── app/
│ ├── Dockerfile
│ ├── package.json
│ └── index.js
└── nginx/
└── nginx.conf
compose.yaml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
restart: always
app:
build: ./app
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
depends_on:
- redis
restart: always
deploy:
replicas: 2
redis:
image: redis:alpine
volumes:
- redis-data:/data
restart: always
volumes:
redis-data:app/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]app/package.json
{
"name": "myapp",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"express": "^4.18.2",
"redis": "^4.6.0"
}
}app/index.js
const express = require('express');
const redis = require('redis');
const app = express();
const client = redis.createClient({
url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`
});
client.connect();
app.get('/', async (req, res) => {
const visits = await client.incr('visits');
res.json({
message: 'Hello Docker Compose!',
visits: visits,
hostname: require('os').hostname()
});
});
app.listen(3000, () => console.log('App running on port 3000'));nginx/nginx.conf
events {
worker_connections 1024;
}
http {
upstream app {
server app:3000;
}
server {
listen 80;
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}실행
# 빌드 + 시작
docker compose up -d --build
# 테스트
curl http://localhost
curl http://localhost
curl http://localhost
# visits 증가 확인
# 스케일 아웃
docker compose up -d --scale app=3
# 로그
docker compose logs -f app
# 정리
docker compose down -v🎯 실습: 개발 환경 (Hot Reload)
compose.yaml
services:
app:
build: .
ports:
- "3000:3000"
volumes:
# 소스 코드 마운트 (실시간 반영)
- ./src:/app/src
# node_modules는 컨테이너 것 사용
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run devcompose.override.yaml
개발 환경 전용 설정 (자동으로 병합됨).
# compose.override.yaml
services:
app:
volumes:
- ./src:/app/src
environment:
- DEBUG=true프로덕션 설정
# compose.prod.yaml
services:
app:
build:
context: .
dockerfile: Dockerfile.prod
environment:
- NODE_ENV=production
restart: always# 개발 환경 (기본)
docker compose up
# 프로덕션 환경
docker compose -f compose.yaml -f compose.prod.yaml up -d📋 compose.yaml 팁
변수 사용
# .env 파일
MYSQL_VERSION=8.0
DB_PASSWORD=secret
# compose.yaml
services:
db:
image: mysql:${MYSQL_VERSION}
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}프로필
services:
app:
image: myapp
debug:
image: debug-tools
profiles:
- debug
# 기본 실행
docker compose up -d
# debug 프로필 포함
docker compose --profile debug up -d확장 (extends)
# common.yaml
services:
base:
image: myapp
environment:
- LOG_LEVEL=info
# compose.yaml
services:
app:
extends:
file: common.yaml
service: base
ports:
- "3000:3000"📋 명령어 요약
# 라이프사이클
docker compose up -d # 시작
docker compose down # 중지
docker compose down -v # 중지 + 볼륨 삭제
docker compose restart # 재시작
# 빌드
docker compose build # 빌드
docker compose up -d --build # 빌드 + 시작
# 상태/로그
docker compose ps # 상태
docker compose logs -f # 로그
# 실행
docker compose exec <svc> sh # 접속
docker compose run <svc> <cmd> # 일회성 명령
# 스케일
docker compose up -d --scale app=3