빠른 흐름
services:
web:
image: "webapp:${TAG:-latest}"
ports:
- "${WEB_PORT:-8080}:80"
environment:
- DEBUG=${DEBUG:-false}cat .env
# TAG=v1.5
# WEB_PORT=3000
docker compose config
docker compose --env-file ./config/.env.dev config치환 구조
interpolation은 Compose 파일을 실행 전 렌더링하는 단계다
Compose의 ${VAR} 치환은 컨테이너 내부 환경 변수를 직접 설정하는 기능이 아니라 Compose 파일 값을 실행 전에 바꾸는 기능입니다. 예를 들어 image: "webapp:${TAG}"에서 ${TAG}는 Compose가 YAML을 해석하는 시점에 실제 문자열로 바뀝니다. 치환 결과가 잘못되면 컨테이너가 뜨기 전에 이미지 이름, 포트, 볼륨 경로부터 잘못 만들어질 수 있습니다.
services:
db:
image: "postgres:${POSTGRES_VERSION:-16}"변수가 없고 기본값도 없으면 Compose는 경고를 내고 빈 문자열로 대체할 수 있습니다. postgres:처럼 유효하지 않은 이미지 참조가 만들어지는 문제가 여기서 발생합니다. 배포에 필요한 값은 ${VAR:?error message} 형태로 필수값을 강제하는 편이 안전합니다.
.env와 env_file은 역할이 다르다
프로젝트 루트의 .env 또는 --env-file로 전달한 파일은 Compose 파일의 interpolation에 쓰입니다. 반면 service의 env_file:은 컨테이너 안으로 환경 변수를 주입하는 설정입니다. 이름이 비슷하지만 적용 시점과 목적이 다릅니다.
services:
app:
image: "my-app:${IMAGE_TAG}"
env_file:
- app.env
environment:
- APP_ENV=${APP_ENV:-development}여기서 IMAGE_TAG와 APP_ENV는 Compose 파일 치환에 쓰이고, app.env는 컨테이너 프로세스가 실행될 때의 환경 변수로 들어갑니다. app.env에 값을 적었다고 해서 반드시 Compose 파일의 ${IMAGE_TAG} 치환에 쓰이는 것은 아닙니다.
운영 기준
| 상황 | 적합한 선택 |
|---|---|
| 이미지 태그, 포트, 경로를 환경별로 바꾸기 | ${VAR} interpolation |
| 기본값 제공 | ${VAR:-default} |
| 필수값 누락 시 실패 | ${VAR:?message} |
literal $가 필요 | $$ |
기본 .env 대신 다른 파일 사용 | docker compose --env-file <file> |
| 컨테이너 내부 환경 변수 주입 | service의 environment 또는 env_file |
| 최종 렌더링 결과 확인 | docker compose config |
여러 --env-file을 지정하면 Compose는 순서대로 읽고, 뒤의 파일이 앞의 값을 덮을 수 있습니다. 개발·스테이징·운영 환경을 나눌 때는 docker compose config 결과를 CI나 리뷰에서 확인할 수 있게 만들어야 실제로 어떤 값이 들어갔는지 추적하기 쉽습니다.
주의할 점
Compose interpolation과 컨테이너 환경 변수 주입을 같은 것으로 보면 설정이 누락됩니다. .env는 기본적으로 Compose 파일 치환에 쓰이고,
컨테이너 내부 값은 environment나 env_file에서 별도로 확인해야 합니다.
실패 예시
- app.env에 IMAGE_TAG를 넣고 image: my-app:${IMAGE_TAG}가 치환될 것이라 기대함
- 필수 DB_PASSWORD에 기본값이나 :? 검사를 두지 않아 빈 문자열로 실행됨
- docker compose config를 보지 않고 운영 compose를 바로 up 함참고 링크
2 sources