Docker Compose는 YAML 파일로 여러 컨테이너 애플리케이션을 정의하고 실행하는 도구예요. 핵심은 services, networks, volumes를 한 파일에 선언하고, docker compose up으로 실행 흐름을 다루는 것이에요. 여기에 restart, .env, depends_on, healthcheck, 볼륨 설정을 더하면 개발·테스트 구성을 더 일관되게 관리하는 데 도움을 줄 수 있어요.
Docker Compose는 여러 컨테이너 애플리케이션을 YAML로 정의하고 실행하는 도구예요.
Docker 공식 문서는 Compose를 “multi-container Docker applications”를 정의하고 실행하는 도구로 설명해요. 이때 핵심 형식은 YAML 파일이며, 그 안에 services, networks, volumes 같은 구성을 담아요 [78][79]. 즉, 웹 서버 1개와 데이터베이스 1개처럼 최소 2개 이상의 컨테이너를 함께 다루는 상황에서 Compose의 가치가 분명해져요.
중요한 점은 Compose가 컨테이너를 “자동으로 최적화”하거나 “모든 운영 문제를 해결”하는 도구는 아니라는 점이에요. 공식 근거가 말해 주는 범위는 애플리케이션 구성을 파일로 정의하고, 그 정의를 바탕으로 실행·중지·재빌드 흐름을 다룰 수 있다는 수준이에요 [78][80]. 그래서 소개할 때도 만능 도구처럼 포장하기보다, 반복 가능한 구성 정의 도구로 이해하는 편이 정확해요.
Compose 파일의 기본 뼈대는 services, networks, volumes 세 축으로 이해하면 돼요.
Compose file reference는 최상위 키로 services, networks, volumes를 제시해요 [79]. 실무에서 가장 먼저 보는 항목은 보통 services인데, 여기에는 web, db, worker처럼 실제로 실행할 컨테이너 단위를 적어요. networks는 서비스 간 통신 경로를, volumes는 컨테이너가 재시작되어도 남겨 둘 데이터 저장소를 맡아요.
| 구성 요소 | 역할 | 대표 예시 |
|---|---|---|
services | 실행할 컨테이너 정의 | web, db, redis |
networks | 서비스 간 통신 네트워크 | frontend, backend |
volumes | 영속 데이터 저장 | db-data, uploads |
다만 개념 설명만 보고 서비스 정의를 지나치게 축약하면 오해가 생길 수 있어요. 예를 들어 서비스는 실제 이미지 이름을 지정하는 image나, Dockerfile 빌드 지시를 담는 build 중 최소 1개가 사실상 필요해요. 따라서 “최소 구성”이라고 소개할 때는 완전한 실행 예시인지, 개념 설명용 일부 예시인지 분리해서 보여주는 편이 안전해요.
완전한 Compose 예시는 image 또는 build를 포함해야 실제 실행 맥락이 분명해져요.
아래 예시는 web 1개와 db 1개, 총 2개 서비스를 포함한 개념 설명용이면서도 실제 실행 가능한 형태예요. web은 nginx:alpine 이미지를, db는 postgres:16 이미지를 사용해요. 여기에 이름 있는 볼륨 1개인 db-data를 붙여서 데이터 영속성도 함께 보여 줄 수 있어요 [79][83].
services:
web:
image: nginx:alpine
ports:
- "8080:80"
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:이 예시는 모든 Compose 옵션을 담은 정답 템플릿은 아니에요. 대신 services, volumes, depends_on, healthcheck, 환경 변수 치환처럼 공식 문서가 설명하는 핵심 요소를 한 번에 읽게 해 주는 부분 예시예요 [79][82][84][85]. 초보자라면 먼저 이런 2서비스 구조를 이해한 뒤, 실제 프로젝트에 맞게 build, 추가 네트워크, 더 많은 서비스로 확장하는 순서가 무난해요.
`docker compose up`은 Compose 구성을 바탕으로 서비스 실행 흐름을 다루는 기본 명령이에요.
공식 CLI 문서는 docker compose up이 서비스 시작, 중지, 재빌드 흐름을 한 명령 계열로 다룰 수 있다고 설명해요 [80]. 여기서 -d는 detached mode, 즉 터미널을 점유하지 않는 백그라운드 실행을 뜻해요. 따라서 up -d를 “실행과 중지 모두를 의미하는 옵션”처럼 설명하면 부정확하고, 정확히는 실행 방식을 바꾸는 플래그라고 보는 편이 맞아요.
docker compose up: 현재 디렉터리의 Compose 파일을 기준으로 서비스를 시작해요.docker compose up -d: 같은 시작 동작이지만 detached mode로 백그라운드 실행해요 [80].구성이 바뀌면 같은 명령 흐름에서 재빌드·재생성 상황을 다룰 수 있어요 [80].
실무에서는 로컬 개발 환경에서 up -d를 자주 쓰지만, 로그를 바로 보고 싶을 때는 -d 없이 실행하는 편이 더 나을 수 있어요. 어떤 방식이 “최선”이라고 단정하기보다, 디버깅 단계인지 안정 실행 단계인지에 따라 다르게 선택하면 돼요. 공식 문서가 보장하는 사실은 시작·중지·재빌드 흐름과 detached 실행 지원이에요 [80].
`restart` 정책은 서비스가 종료되었을 때 재시작 동작을 제어하는 옵션이에요.
Compose는 서비스 단위 restart 정책을 지원하고, 공식 문서에는 no, always, on-failure, unless-stopped 같은 값이 나와 있어요 [81]. 예를 들어 작업 실패 시에만 다시 띄우고 싶다면 on-failure, 사용자가 명시적으로 멈출 때까지 계속 유지하고 싶다면 unless-stopped를 고려할 수 있어요. 선택지는 4개 이상이지만, 어느 값이 맞는지는 서비스 성격에 따라 달라져요.
| 값 | 의미 요약 | 어울리는 예 |
|---|---|---|
no | 자동 재시작 안 함 | 1회성 테스트 컨테이너 |
always | 종료 시 계속 재시작 시도 | 상시 유지가 필요한 서비스 |
on-failure | 실패 종료일 때 재시작 | 배치·워커 |
unless-stopped | 사용자가 멈추기 전까지 유지 | 로컬 개발용 기본 서비스 |
다만 restart가 장애 원인을 해결해 주는 것은 아니에요. 예를 들어 설정 오타나 잘못된 이미지 태그처럼 근본 원인이 남아 있으면, 재시작만 반복될 수 있어요. 그래서 restart는 복구 보조 수단이지, 운영 안정성을 보장하는 만능 장치로 이해하면 곤란해요 [81].
`.env`와 환경 변수 치환은 설정값을 코드와 분리하는 데 쓰이는 기능이에요.
Docker 문서는 Compose가 환경 변수와 .env 파일을 지원하며, 이를 통해 설정을 코드와 분리하는 데 흔히 사용된다고 설명해요 [82]. 예를 들어 포트 번호, 데이터베이스 비밀번호, 이미지 태그 같은 값을 ${PORT}, ${POSTGRES_PASSWORD}, ${TAG} 형태로 치환할 수 있어요. 이런 방식은 개발·테스트·스테이징처럼 환경별 값이 다른 경우 특히 유용해요.
POSTGRES_PASSWORD=example123
APP_PORT=8080
TAG=latest여기서 꼭 붙여야 할 주의가 있어요. 공식 근거는 .env가 설정 분리에 쓰인다고 말할 뿐, 비밀 정보 관리나 보안성을 보장한다고 말하지 않아요 [82]. 따라서 .env는 환경별 설정값을 다루는 도구로 이해하고, 민감한 비밀 관리 도구라고 단정하지 않는 편이 정확해요.
볼륨은 컨테이너 생명주기와 분리된 데이터를 유지하기 위한 저장 수단이에요.
Compose의 볼륨 문서는 named volume과 bind mount를 모두 다뤄요 [83]. named volume은 db-data처럼 Docker가 관리하는 저장소를 뜻하고, bind mount는 호스트의 특정 경로를 컨테이너에 연결하는 방식이에요. 데이터베이스처럼 데이터가 남아야 하는 서비스에는 named volume이 자주 쓰이고, 소스 코드를 즉시 반영해야 하는 개발 환경에는 bind mount가 자주 쓰여요.
| 방식 | 저장 위치 | 장점 | 자주 쓰는 경우 |
|---|---|---|---|
| Named volume | Docker 관리 영역 | 관리가 단순해요 | PostgreSQL, MySQL |
| Bind mount | 호스트 파일시스템 | 파일 수정 반영이 쉬워요 | 웹 앱 개발 소스 연결 |
예를 들어 PostgreSQL 1개를 실행할 때 /var/lib/postgresql/data에 볼륨을 붙이지 않으면 컨테이너 재생성 시 데이터가 사라질 수 있어요. 반대로 정적 웹 서버처럼 상태를 남기지 않는 서비스는 볼륨이 꼭 필요하지 않을 수 있어요. 즉, 모든 서비스에 볼륨을 일괄 적용하기보다 데이터 영속성 요구가 있는지 먼저 판단하는 편이 좋아요 [83].
`depends_on`과 `healthcheck`는 서비스 시작 순서와 준비 상태를 더 명시적으로 다루는 기능이에요.
Compose는 depends_on으로 서비스 의존성을 표현할 수 있고, 현대 Compose 구현에서는 조건과 결합해 시작 순서를 제어할 수 있어요 [85]. 또 healthcheck는 서비스가 실제로 정상 상태인지 점검하는 정의를 제공해요 [84]. 두 기능을 함께 쓰면, 예를 들어 web이 db 컨테이너가 “실행 중”인 시점이 아니라 “건강함” 상태가 된 뒤 시작되도록 유도할 수 있어요.
이 조합은 특히 데이터베이스 초기화 시간이 5초에서 30초 이상 걸릴 수 있는 환경에서 도움이 될 수 있어요. 다만 이것이 애플리케이션 수준 재시도 로직을 완전히 대체하는 것은 아니에요. 네트워크 지연이나 스키마 마이그레이션 같은 변수는 여전히 앱 코드 또는 배포 절차에서 따로 고려해야 해요 [84][85].
depends_on만 사용: 순서 표현은 가능하지만 준비 완료까지 보장한다고 과신하면 안 돼요 [85].healthcheck추가: 실제 응답 가능 상태를 기준으로 판단할 수 있어요 [84].둘을 함께 사용: 시작 순서와 준비 상태를 더 명시적으로 다룰 수 있어요 [84][85].
Compose의 장점과 한계는 반복 가능한 구성 관리와 세밀한 운영 제어 사이의 균형으로 이해해야 해요.
Compose의 큰 장점은 YAML 1개 또는 소수의 파일에 구성을 모아 두고, docker compose up 같은 명령으로 같은 실행 흐름을 재현하기 쉬운 점이에요 [78][80]. 이런 특성은 팀 협업, 로컬 개발, 테스트 자동화에서 반복성을 높이는 데 도움이 될 수 있어요. 다만 이 평가는 공식 문서에 직접 적힌 문장이라기보다, 문서가 제공하는 기능적 성격에서 합리적으로 도출되는 실무적 해석이에요.
반대로 한계도 분명해요. .env는 비밀 관리 도구로 간주하면 안 되고 [82], restart는 오류를 고치지 않으며 [81], depends_on과 healthcheck도 애플리케이션 자체의 견고함을 대신하지 않아요 [84][85]. 결국 Compose는 구성을 더 선명하게 표현하고 실행 흐름을 단순화하는 도구이지, 설계 품질을 자동 보장하는 도구는 아니에요.
처음 적용할 때는 2개 서비스 예제에서 시작해 4단계로 확장하는 접근이 실용적이에요.
1단계:
web과db처럼 서비스 2개만 둔 Compose 파일을 만들고image를 명시해요.2단계: 데이터베이스에 named volume 1개를 연결해 데이터 유지 여부를 확인해요 [83].
3단계: 포트·태그·암호처럼 바뀌는 값은
.env치환으로 분리해요 [82].4단계: 시작 타이밍 이슈가 있으면
healthcheck와depends_on조건을 추가해요 [84][85].
이 순서는 학습 부담을 낮춰 줘요. 처음부터 네트워크 세분화, 5개 이상 서비스, 복잡한 재시작 정책을 한 번에 넣으면 Compose 문법보다 운영 판단이 더 어려워질 수 있어요. 반대로 2개 서비스 예시를 기준으로 하나씩 늘리면 어떤 옵션이 어떤 문제를 해결하려는 것인지 더 선명하게 파악할 수 있어요.
FAQ
Compose 파일에서 services만 있으면 충분한가요?
간단한 예시는 가능하지만, 실제 다중 컨테이너 앱에서는 volumes나 networks가 함께 필요한 경우가 많아요. 공식 참조는 services, networks, volumes를 대표 최상위 키로 설명해요 [79].
`.env`에 비밀번호를 넣어도 안전한가요?
공식 근거는 .env를 설정 분리 용도로 설명할 뿐 보안 도구라고 말하지 않아요 [82]. 그래서 환경별 설정 관리에는 쓸 수 있지만, 비밀 관리 자체를 보장한다고 이해하면 과해요.
`depends_on`만 쓰면 DB 준비가 끝날 때까지 기다리나요?
항상 그렇게 단정하면 안 돼요. 공식 문서는 depends_on과 조건, 그리고 healthcheck를 함께 활용해 시작 순서와 준비 상태를 더 세밀하게 다룰 수 있다고 설명해요 [84][85].
`docker compose up -d`는 중지 명령인가요?
아니에요. up은 시작 흐름의 기본 명령이고, -d는 detached mode를 뜻해요 [80]. 즉 백그라운드 실행 옵션이지 중지 의미는 아니에요.