Docker
Docker Compose의 env_file과 environment, 뭐가 다른가
두 방식 모두 컨테이너에 환경 변수를 주입하지만 우선순위와 보안 동작이 다르다. 혼용할 때 어떤 값이 이기는지 정리했다.
Docker Compose에서 환경 변수를 주입하는 방법은 크게 두 가지다. env_file로 파일을 통째로 읽히는 방법, environment로 compose.yml 안에서 직접 정의하는 방법. 언뜻 비슷해 보이지만 동작 방식이 다르다.
기본 차이
services:
app:
env_file:
- .env.production
environment:
- DATABASE_URL=postgresql://localhost/prod
- NODE_ENV=production
env_file은 지정한 파일을 읽어서 컨테이너에 주입한다. environment는 compose 파일 안에서 직접 값을 지정한다.
우선순위: environment가 env_file보다 높다. 둘 다 같은 키를 정의하면 environment의 값이 이긴다.
# 실제 주입된 값 확인
docker inspect container-name | jq '.[0].Config.Env'
# 또는
docker exec container-name env
env_file 사용 시 주의할 것
.env 파일은 KEY=VALUE 형식으로 작성한다. Bash 처럼 export를 붙이면 안 된다. 따옴표는 값의 일부로 처리된다.
# 올바른 형식
DATABASE_URL=postgresql://user:pass@host/db
SECRET_KEY=abcdef123
# 틀린 형식 (따옴표가 값에 포함됨)
SECRET_KEY="abcdef123" # 실제 값: "abcdef123"
env_file에 경로를 상대 경로로 쓰면 docker compose 명령을 실행하는 디렉토리 기준으로 해석된다. 프로젝트 루트가 아닌 곳에서 실행하면 파일을 못 찾는다.
environment에서 값을 참조하는 방법
environment에서는 호스트 환경 변수를 그대로 주입할 수 있다.
environment:
- DATABASE_URL # 호스트의 DATABASE_URL 값을 그대로 주입
- SECRET_KEY=${MY_HOST_SECRET} # 호스트 변수 이름이 다를 때
값 없이 키만 쓰면 호스트에서 해당 이름의 환경 변수 값을 가져온다. 호스트에 없으면 빈 값이 된다.
어느 걸 써야 하나
개인적으로 이렇게 구분해서 쓴다.
| 상황 | 권장 방식 |
|---|---|
| 로컬 개발, 여러 서비스가 공통 설정을 공유 | env_file |
| 특정 서비스만 다른 값이 필요할 때 | environment 오버라이드 |
| 시크릿을 버전 관리에 올리지 않을 때 | env_file (파일을 .gitignore에 추가) |
| CI/CD에서 동적으로 값을 주입할 때 | environment + 파이프라인 시크릿 |
.env 파일을 .gitignore에 추가하는 건 기본이다. environment에 직접 값을 쓰면 compose.yml이 버전 관리에 들어가는 순간 시크릿이 노출된다.