Docker Compose로 서비스를 운영하다 보면 개발 환경과 프로덕션 환경의 설정이 조금씩 달라지는 지점이 생긴다. 볼륨 마운트, 포트 노출, 환경 변수 — 이런 차이를 하나의 파일에 if/else처럼 관리하면 금방 복잡해진다. Compose Override 파일은 베이스 설정을 건드리지 않고 환경별 레이어를 덧씌우는 방법을 제공한다.
docker compose up을 실행하면 Compose는 같은 디렉터리에서 두 파일을 자동으로 찾는다.
프로젝트 루트/
├── docker-compose.yml # 베이스 (공통 설정)
└── docker-compose.override.yml # 자동으로 병합되는 오버라이드
별도 플래그 없이 docker compose up만 입력해도 두 파일이 합쳐진다. docker-compose.override.yml은 개발 전용 설정을 담기에 가장 적합한 위치다. 이 파일은 보통 .gitignore에 추가하지 않고 팀 전체가 공유한다.
병합(merge): 같은 키가 존재하면 override 파일의 값이 이긴다. 배열(ports, volumes 등)은 두 파일의 항목이 합산된다.
자동 병합 대신 파일을 직접 지정하고 싶을 때는 -f 플래그를 사용한다.
# 프로덕션 배포 시
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# 로컬 개발 시
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
-f를 여러 번 쓰면 왼쪽에서 오른쪽 순서로 병합된다. 마지막에 오는 파일의 설정이 우선한다.
-f 플래그: --file의 단축 옵션. 두 개 이상 지정하면 순서대로 deep merge된다.
파일 구조를 명시적으로 나누면 각 환경의 의도가 코드에 드러난다.
docker-compose.yml # 공통: 서비스 정의, 네트워크, 이미지
docker-compose.dev.yml # 개발: 볼륨 마운트, 디버그 포트, hot-reload
docker-compose.prod.yml # 프로덕션: 리소스 제한, restart 정책, 시크릿
아래는 각 파일의 역할을 보여주는 예시다.
# docker-compose.yml (베이스)
services:
api:
image: myapp:latest
environment:
- NODE_ENV=production
# docker-compose.dev.yml
services:
api:
build: . # 이미지 대신 빌드
volumes:
- .:/app # 소스 코드 마운트
environment:
- NODE_ENV=development
ports:
- "9229:9229" # 디버그 포트 추가
# docker-compose.prod.yml
services:
api:
restart: always
deploy:
resources:
limits:
memory: 512m
| 항목 | 병합 방식 | 예시 |
|---|---|---|
image, command | override가 덮어씀 | prod 이미지로 교체 |
environment | 키 단위 병합 | 개발 변수 추가 |
ports, volumes | 배열 합산 | 포트 누적 |
labels | 키 단위 병합 | 라벨 추가 |
배열 항목은 중복 제거 없이 합산되므로 ports에 같은 포트를 두 파일에 모두 적으면 충돌이 난다. 베이스 파일에는 프로덕션에 필요한 포트만 남기고, 개발 전용 포트는 override에만 두는 것이 안전하다.
환경마다 긴 -f 체인을 타이핑하는 번거로움은 Makefile로 감출 수 있다.
dev:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
prod:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
down:
docker compose down
make dev 한 줄로 개발 환경이 뜨고, make prod로 프로덕션 스택이 올라간다. 파일 조합 실수를 방지하는 가장 단순한 방법이다.