Table of contents
Intro.
Docker Compose는 여러 컨테이너를 정의하고 실행할 수 있는 도구로, 사내 프로젝트에서 로컬 통합 테스트 환경을 구축하기 위해 이를 사용하던 중 발생한 문제와 그 해결 방법에 대해 다루고자 한다.
Problem.
docker compose up -d --build
보통 위와 같은 명령어로 docker-compose.yml
이라고 명명된 파일을 실행시킬 것이다. 이 때, 환경 변수 파일을 로드하기 위해서 이 파일의 내용을 아래와 같이 env_file
을 필드로 사용해 지정할 수 있을 것이다.
services:
something:
env_file:
.env.validator
이렇게 하면 서비스로 지정된 컨테이너가 정상적으로 실행될 수 있을까? 실행해 보니 답은 '아니오' 였다.
에러 상황은 아니지만 Docker Compose는 아래와 같이 내게 경고 상황이란 것을 알 수 있는 로그를 출력해 주었다.
WARN[0000] The "NETWORK_ID" variable is not set. Defaulting to a blank string.
WARN[0000] The "ADDRESS_VALIDATOR_1" variable is not set. Defaulting to a blank string.
WARN[0000] The "NETWORK_ID" variable is not set. Defaulting to a blank string.
WARN[0000] The "ADDRESS_VALIDATOR_2" variable is not set. Defaulting to a blank string.
WARN[0000] The "NETWORK_ID" variable is not set. Defaulting to a blank string.
WARN[0000] The "ADDRESS_VALIDATOR_3" variable is not set. Defaulting to a blank string.
WARN[0000] The "NETWORK_ID" variable is not set. Defaulting to a blank string.
WARN[0000] The "ADDRESS_VALIDATOR_0" variable is not set. Defaulting to a blank string.
하지만 이는 단순한 경고 메시지라고 할 수 없었다. 환경 변수들이 세팅되지 않으면 컨테이너가 정상적으로 실행될 리 없기 때문이다.
Solution.
이 문제를 해결하기 위해 몇 가지 시도를 해보았다.
첫 번째로 시도한 것은 .env.validator
파일 내에 환경 변수를 단순히 docker-compose.yml
에 직접 넣는 것이었다. (딱히 무식한 방법이라고 생각하진 않고, 필요에 의한 좋은 방법이라고 생각한다.)
services:
something:
environment:
NETWORKD_ID=1337
ADDRESS_VALIDATOR_1=ab84848973jjdifid2352
(생략..)
위와 같이 설정하고 명령을 실행했으나 실패했다. 여전히 같은 경고 메시지가 출력되었다. 여기서 알게 된 것은 이 문제가 단순히 환경 변수 파일을 읽지 못해서 발생한 경고가 아니라는 것이다.
그래서 공식 문서를 살펴 보니 약간의 힌트를 얻을 수 있었다.
🤔
environment
는.env
나env_file
에 정의된 변수들을 덮어 쓴다.
이 말은 Docker Compose가 우선 순위에 따라 환경 변수를 처리한다는 의미로 해석될 수 있다.
Docker Compose는 설정 파일 내에서는 기본적으로 environment
필드에 높은 우선 순위를 부여하고, 그 다음은 env_file
, .env
파일 순으로 낮아진다.
Docker Compose의 환경 변수가 우선 순위에 따라 처리된다는 것은 .env
같은 환경 변수 파일이 우선 순위가 높은 것에 의해 변경되지 않게 하면 문제를 해결할 수 있단 것을 의미한다.
따라서 아래와 같이 일단 .env
파일을 정의해 사용하기로 했다.
NETWORK_ID=1337
ADDRESS_VALIDATOR_0=0xabcd
ADDRESS_VALIDATOR_1=0xabcd
ADDRESS_VALIDATOR_2=0xabcd
ADDRESS_VALIDATOR_3=0xabcd
GAS_PRICE=0
🤔 환경을 분리해야 하는 상황이 아니라면 간단하게
.env
만 사용해도 될 것 같다.
이러면 .env.validator
를 사용할 때와 어떤 차이가 있을까? .env
는 Docker Compose가 자동으로 로드하도록 하며, .env.validator
와 같이 지정된 파일보다 우선 순위가 높기 때문에 이를 덮어 씌운다는 것이다.
따라서 docker-compose.yml
과 같은 디렉토리 위치에 .env
를 생성해 사용하면 Docker Compose가 이를 인식해 환경 변수를 컨테이너로 주입해 준다는 것이다.
End.
services:
something:
env_file: # 이 필드와
- .env.validator # 이 값을 여기서 제거해 .env 파일이 로드되도록 하자
이제 위 docker-compose.yml
파일에서 환경 변수를 제대로 읽어오게 하려면 env_file
필드와 값을 제거하면 된다. 그러면 동일한 디렉토리 위치에 있는 .env
파일이 로드되어 컨테이너가 비로소 정상적으로 실행된다.
정리해 보자면, 아래와 같다
Docker Compose는 환경 변수를 우선 순위에 따라 처리한다.
.env
환경 변수 파일을 사용하고 있다면, 가장 높은 우선 순위에 해당하는 방법이 덮어 버리지 않게 주의한다.