컨테이너는 이미지와 설정을 분리해야 한다는 원칙 위에 서 있다. DB 접속 주소나 API 키처럼 환경마다 달라지는 값을 이미지에 하드코딩하면, 개발·스테이징·프로덕션마다 이미지를 따로 빌드해야 하는 문제가 생긴다. Docker는 환경 변수를 통해 이 문제를 깔끔하게 해결한다.
ENV 명령어는 Dockerfile 안에서 환경 변수의 기본값을 선언한다. 컨테이너가 실행될 때 별도로 값을 넘기지 않으면 이 기본값이 사용된다.
FROM node:20-alpine
ENV NODE_ENV=production
ENV PORT=3000
WORKDIR /app
COPY . .
RUN npm ci --omit=dev
CMD ["node", "server.js"]
ENV: Dockerfile 레이어에 환경 변수를 고정하는 명령어. 이미지에 포함되므로 민감한 값은 절대 넣지 않는다.
docker run의 -e 플래그로 컨테이너 실행 시점에 값을 덮어쓸 수 있다. ENV로 선언된 기본값보다 우선한다.
docker run -d \
-e NODE_ENV=staging \
-e DATABASE_URL=postgres://user:pass@db:5432/mydb \
-p 3000:3000 \
my-app:latest
값이 여러 개라면 -e를 반복해서 붙인다. 셸 변수를 그대로 넘기려면 = 뒤를 생략한다.
export DATABASE_URL=postgres://...
docker run -e DATABASE_URL my-app:latest
변수가 많아지면 --env-file 옵션으로 파일을 통째로 넘기는 편이 낫다.
# .env.staging
NODE_ENV=staging
DATABASE_URL=postgres://user:pass@db:5432/mydb
REDIS_URL=redis://cache:6379
JWT_SECRET=supersecret
docker run -d \
--env-file .env.staging \
-p 3000:3000 \
my-app:latest
.env 파일: KEY=VALUE 형식의 텍스트 파일. #으로 시작하는 줄은 주석으로 처리된다.
| 방법 | 선언 위치 | 주입 시점 | 적합한 용도 |
|---|---|---|---|
ENV | Dockerfile | 이미지 빌드 | 변하지 않는 기본값 |
-e 플래그 | CLI | 컨테이너 실행 | 일시적 오버라이드, 테스트 |
--env-file | 파일 | 컨테이너 실행 | 다수 변수, 환경별 설정 |
Dockerfile (ENV)
|
v
이미지 레이어
|
v
docker run -e KEY=VAL --env-file .env
|
v
컨테이너 프로세스 환경 (process.env / os.environ)
환경 변수는 docker inspect 명령어로 평문 그대로 노출된다.
docker inspect <container_id> | grep -A 20 '"Env"'
# DATABASE_URL=postgres://user:pass@db:5432/mydb ← 평문 노출
API 키, 비밀번호, 인증서처럼 민감한 값은 Docker Secrets 또는 외부 시크릿 관리 도구(Vault, AWS Secrets Manager 등)를 사용해야 한다. .env 파일은 반드시 .gitignore에 추가하고, 이미지 레이어에 포함되지 않도록 COPY .env . 구문을 피해야 한다.
| 데이터 종류 | 권장 방식 |
|---|---|
| 포트, 로그 레벨 등 비민감 설정 | ENV 또는 --env-file |
| DB 비밀번호, API 키 | Docker Secrets / Vault |
| TLS 인증서 | Docker Secrets / 볼륨 마운트 |