docker compose up 했더니 컨테이너 안에서 환경변수가 비어 있거나 엉뚱한 값이 들어가 있다면, Compose의 환경변수 경로가 세 갈래라는 걸 모르고 섞어 쓴 경우가 많습니다. .env 파일, env_file, environment 세 가지는 적용되는 위치도 우선순위도 다릅니다. 여기서 한 번에 정리합니다.
셋은 역할이 다르다
| 항목 | 적용 위치 | 용도 |
|---|---|---|
.env (루트) | Compose 파일 자체의 ${VAR} 치환 | compose.yml 안의 변수 채우기 |
env_file: | 컨테이너 내부 환경변수 | 변수 묶음을 컨테이너에 주입 |
environment: | 컨테이너 내부 환경변수 | 개별 값 직접 지정(최우선) |
핵심 오해는 이것입니다. 루트의 .env는 컨테이너 안으로 자동 주입되지 않습니다. 오직 compose.yml 안의 ${VAR} 자리를 채울 뿐입니다. 컨테이너에 넣으려면 environment나 env_file로 다시 전달해야 합니다.
우선순위
같은 변수가 여러 곳에 있으면 다음 순서로 이깁니다(위가 강함).
TEXT
1. docker compose run -e VAR=... (CLI)
2. environment: (compose.yml)
3. env_file: (파일)
4. 셸 환경변수 / 루트 .env (치환용)
올바른 구성 예시
.env로 compose 안 이미지 태그를 채우고, 컨테이너에는 env_file로 앱 설정을 넣습니다.
YAML
services:
api:
image: myapp:${TAG} # 루트 .env 의 TAG 로 치환
env_file:
- ./app.env # 컨테이너 내부로 주입
environment:
- LOG_LEVEL=debug # 개별 값은 여기서 최우선
로컬 터미널
# .env (compose 치환용)
TAG=1.4.0
흔한 함정
값에 따옴표를 붙이면 env_file에서는 따옴표까지 값으로 들어갑니다. PASS="secret"는 컨테이너 안에서 "secret"이 됩니다. env_file에는 따옴표 없이 PASS=secret로 적습니다. 또 $가 들어간 값은 Compose가 변수 치환으로 오해하니, 리터럴 $는 $$로 이스케이프합니다.
점검 체크리스트
Docker
docker compose config # 치환·병합된 최종 설정 미리보기
docker compose run --rm api env # 컨테이너에 실제 들어간 환경변수
docker compose config | grep -i tag # 변수 치환이 됐는지 확인
docker compose config는 실행 전에 모든 치환과 병합을 펼쳐 보여줘서, 값이 비거나 따옴표가 섞인 문제를 띄우기 전에 잡아낼 수 있습니다.
.env·env_file·environment를 바꿔가며 어디서 값이 이기는지 직접 확인하는 실습은 도커 트랙에서 회원가입 없이 무료로 해볼 수 있습니다.