Docker Compose는 여러 컨테이너를 하나의 파일로 묶어 관리할 수 있게 해준다. 그 핵심은 docker-compose.yml의 services 블록이며, 여기서 각 컨테이너의 동작 방식을 선언적으로 정의한다. 컨테이너를 어떤 이미지로 실행할지, 이름은 무엇인지, 실패 시 어떻게 재시작할지를 모두 이 블록 안에서 결정한다.
services 아래에 키 이름을 붙이면 그것이 곧 서비스 이름이 된다. 하나의 서비스는 하나의 컨테이너 인스턴스를 나타낸다.
services:
web:
image: nginx:alpine
db:
image: postgres:16
service: Compose가 관리하는 컨테이너 단위. 이름은 내부 DNS 이름으로도 사용된다.
컨테이너를 띄우는 방법은 두 가지다. 레지스트리에서 이미지를 그대로 가져오거나, 로컬 Dockerfile을 빌드해서 사용하거나.
| 옵션 | 설명 | 예시 |
|---|---|---|
image | 기존 이미지를 그대로 사용 | image: node:20-alpine |
build | Dockerfile을 빌드해서 사용 | build: ./app |
build.context + build.dockerfile | 빌드 경로와 파일 명시 | 아래 예시 참고 |
services:
api:
build:
context: ./backend
dockerfile: Dockerfile.prod
build context: Docker 빌드 시 파일을 탐색하는 기준 디렉터리.
서비스 이름과 실제 컨테이너 이름은 별개다. container_name으로 컨테이너 이름을 고정할 수 있다.
services:
worker:
image: python:3.12-slim
container_name: my_worker
working_dir: /app
command: python main.py
CMD를 덮어쓴다. 쉘 형식과 배열 형식 모두 가능하다.컨테이너가 예기치 않게 종료될 때 Compose가 어떻게 대응할지 restart로 제어한다.
| 값 | 동작 |
|---|---|
no | 재시작 안 함 (기본값) |
always | 항상 재시작 |
on-failure | 비정상 종료 시에만 재시작 |
unless-stopped | 수동으로 멈추지 않는 한 항상 재시작 |
아래는 웹 서버, API 서버, 데이터베이스를 함께 정의한 현실적인 예시다.
browser
|
[web: nginx]
|
[api: node]
|
[db: postgres]
services:
web:
image: nginx:alpine
container_name: compose_web
restart: always
api:
build: ./api
container_name: compose_api
working_dir: /app
command: node server.js
restart: on-failure
db:
image: postgres:16
container_name: compose_db
restart: unless-stopped
각 서비스는 기본적으로 같은 네트워크에 속하며, 서비스 이름(web, api, db)으로 서로를 호출할 수 있다.
image와 build 중 어느 것을 쓸지는 이미지를 직접 제어할 필요가 있는지에 달려 있다. 외부 의존성(DB, 캐시)은 image로, 직접 개발 중인 서비스는 build로 분리하는 것이 일반적인 패턴이다.