본문 바로가기
소프트웨어개발

Docker Compose .env와 env_file 차이: 환경변수가 적용되지 않을 때 확인할 것

by 아빠띠띠뽀 2026. 9. 8.

.env 파일에 값을 적었는데 컨테이너 안에서는 보이지 않거나, 파일을 수정했는데 프로그램이 계속 이전 설정을 사용하는 경우가 있습니다. 파일 이름보다 중요한 것은 그 값이 “Compose 설정을 만드는 데 쓰이는지”, “컨테이너의 환경변수로 전달되는지”입니다.

앞서 헬스체크와 시작 순서 글에서 변수로 DB 설정을 표현했습니다. 이번에는 민감한 정보 없이 APP_MODE, LOG_LEVEL 같은 가상 설정으로 값이 전달되는 경로를 살펴봅니다.

1. .env에 적으면 자동으로 컨테이너에 들어갈까?

기본 .env 파일은 Compose 파일의 변수 치환에 사용할 값을 제공하는 역할을 합니다. 예를 들어 image: "myapp:${TAG}"의 TAG 부분을 채우는 데 쓸 수 있습니다. .env에 있는 모든 항목이 자동으로 컨테이너에 전달되는 것은 아닙니다. Docker의 변수 치환 문서에서 이 단계를 확인할 수 있습니다.

컨테이너에 값을 전달하려면 서비스의 environment에 지정하거나 env_file로 파일을 연결하는 등 명시적인 구성이 필요합니다. 두 방식은 컨테이너 환경변수 공식 안내에서 설명합니다.

설정 주요 역할 확인할 위치
.env / --env-file Compose 변수 치환에 값 제공 해석된 Compose 설정
environment 서비스에 전달할 변수 지정 컨테이너 환경
서비스의 env_file 파일의 변수를 서비스에 전달 컨테이너 환경

--env-file이라는 명령줄 옵션과 YAML의 env_file이라는 항목은 이름이 비슷하지만 쓰이는 위치가 다릅니다. 문제를 확인할 때는 둘을 “환경 파일”이라는 말 하나로 부르기보다, 실행 명령과 서비스 설정 중 어디에 적었는지 함께 설명하는 것이 좋습니다.

직접 제작한 환경변수 흐름도. Compose 파일을 해석하는 단계와 컨테이너에 값을 전달하는 단계를 나누어 표시했습니다.

2. 세 파일로 값의 흐름 따라가기

다음은 한 폴더에 compose.yaml, .env, app.env를 두는 설명용 예시입니다. 프로그램의 실제 설정 변경을 대신하는 코드는 아니며, probe라는 작은 컨테이너에서 값이 어떻게 전달되는지 비교하기 위한 구성입니다.

먼저 .env에는 Compose가 사용할 값을 적습니다.

APP_MODE=development
ONLY_FOR_COMPOSE=preview

app.env에는 컨테이너에 전달할 기본 로그 수준을 적습니다.

LOG_LEVEL=info

compose.yaml에서 두 입력을 연결합니다.

services:
  probe:
    image: alpine:3.23
    command: ["sleep", "infinity"]
    env_file:
      - ./app.env
    environment:
      APP_MODE: "${APP_MODE:-development}"

이 예시에서 APP_MODE는 .env의 값을 environment를 통해 전달합니다. LOG_LEVEL은 app.env에서 env_file을 통해 전달됩니다. ONLY_FOR_COMPOSE는 컨테이너 전달 항목에 연결하지 않았으므로, 이 구성만으로는 컨테이너 환경에 추가되지 않는 것이 기대 결과입니다.

이미지와 실행 셸에 같은 이름의 별도 설정이 없다는 가정에서 흐름을 비교한 것입니다. 실제 프로젝트에서는 여러 Compose 파일과 실행 옵션이 결합될 수 있으므로, 예시의 결론을 모든 환경에 그대로 적용하지 말고 최종 구성을 확인해야 합니다.

3. 파일에 쓴 값과 결과가 다른 이유

Compose 변수 치환에서는 실행 셸의 환경변수가 파일에 적힌 값보다 우선할 수 있습니다. 파일의 APP_MODE가 development여도 실행한 셸에서 같은 이름이 production으로 설정되어 있다면 그 값이 선택될 수 있다는 뜻입니다. “파일을 수정했는데 왜 바뀌지 않지?”라는 상황에서는 실행 위치와 셸 설정을 함께 봅니다.

컨테이너에 전달하는 단계에서는 같은 변수를 environment와 env_file에 중복 선언했는지 확인합니다. environment가 env_file보다 우선합니다. 전체 우선순위는 Docker 환경변수 우선순위 문서를 참고하세요. 처음부터 우선순위 표를 모두 외우기보다 변수 하나가 선언된 위치를 나란히 적는 편이 진단에 도움이 됩니다.

${APP_MODE:-development}는 값이 없거나 비어 있을 때 기본값을 사용한다는 표현입니다. 기본값으로 조용히 실행되면 곤란한 항목에는 ${VAR:?설명}처럼 필수값 검사를 검토할 수 있습니다. 개발용 기본값과 반드시 지정해야 할 값을 구분해 두면 설정 누락을 일찍 발견하기 쉽습니다.

4. 해석된 설정과 컨테이너를 따로 확인하기

아래 첫 명령은 해석된 설정을 출력하고, 나머지는 예시 서비스를 시작한 뒤 두 변수만 확인하는 방법입니다. 별도 시험 폴더에서 사용하며, 실제 프로젝트의 config 출력에는 비밀번호 등 민감한 값이 포함될 수 있으므로 결과 전체를 그대로 공유하지 않습니다.

docker compose config

docker compose up -d probe
docker compose exec probe printenv APP_MODE LOG_LEVEL

ONLY_FOR_COMPOSE 전달 여부를 별도로 살펴보려면 다음처럼 해당 이름만 조회할 수 있습니다. 위 예시에서는 정의된 값을 출력하지 않는 것이 기대 결과입니다. 이 글에서는 컨테이너를 실제로 실행한 결과로 제시하지 않습니다.

docker compose exec probe printenv ONLY_FOR_COMPOSE

Compose 설정에 원하는 값이 나타나는지, 생성된 컨테이너에 그 값이 있는지, 프로그램이 실제로 그 변수 이름을 읽는지를 차례로 확인합니다. 임의의 APP_MODE 변수를 추가했다고 모든 프로그램의 실행 모드가 바뀌지는 않습니다. 프로그램이 지원하는 설정 이름과 읽는 시점도 확인해야 합니다.

5. restart만 했는데 값이 안 바뀌는 경우

docker compose restart는 Compose 설정 변경을 새로 반영하는 명령이 아닙니다. 환경변수를 바꾼 뒤 기존 컨테이너만 재시작하면 이전 생성 설정이 유지될 수 있습니다. 이 차이는 restart 공식 문서에 명시되어 있습니다.

설정 변경 후에는 변경된 구성으로 컨테이너를 재생성하는 절차와 서비스 영향을 검토해야 합니다. 저장 데이터가 있다면 먼저 볼륨과 바인드 마운트 구조를 확인합니다. 환경변수 문제를 해결하려고 데이터 볼륨까지 삭제할 이유는 없습니다.

마지막으로 .env는 암호화 저장소가 아닙니다. 민감한 값은 저장소나 로그에 노출하지 않도록 관리하고, Docker 공식 안내에서 권하는 secrets 같은 전달 방식도 애플리케이션 지원 범위와 함께 검토합니다. 일반 설정값과 비밀값을 구분하면 예제 공유도 쉬워집니다.

자료 확인일: 2026년 9월 8일. 공식 문서에 기반한 설명용 구성입니다. 기대 결과와 실제 컨테이너 실행 결과를 구분했으며, 운영 환경의 설정값은 사용하지 않았습니다.