Docker 컨테이너를 실행할 때 데이터베이스 주소, 포트 번호, 애플리케이션 실행 모드, API 주소처럼 환경마다 달라지는 설정이 필요합니다.
이러한 값을 Docker 이미지 안에 직접 작성하면 개발 서버와 운영 서버마다 이미지를 새로 만들어야 하며, 비밀번호나 인증 정보가 이미지에 포함될 위험도 있습니다.
이 문제를 해결하기 위해 Docker에서는 환경 변수(Environment Variable)를 사용합니다.
이번 글에서는 Docker 환경 변수의 개념부터 Dockerfile의 ENV, docker run -e, --env-file, Docker Compose의 environment, .env 파일 사용법과 주의사항까지 자세히 알아보겠습니다.
Docker 환경 변수란?
환경 변수는 애플리케이션이 실행될 때 참조할 수 있는 이름과 값의 조합입니다.
예를 들어 다음과 같은 설정을 환경 변수로 관리할 수 있습니다.
APP_ENV=production
APP_PORT=8080
DB_HOST=mysql
DB_PORT=3306
애플리케이션은 설정 파일에 값을 고정하지 않고 환경 변수를 읽어 실행 환경을 결정합니다.
전체 구조는 다음과 같습니다.
Docker Host
↓
환경 변수 전달
↓
Docker Container
↓
Application에서 환경 변수 사용
환경 변수를 사용하면 같은 Docker 이미지를 개발, 테스트, 운영 환경에서 재사용할 수 있습니다.
환경 변수가 필요한 이유
환경 변수를 사용하면 다음과 같은 장점이 있습니다.
- 환경별 설정 분리
- 동일한 이미지 재사용
- 설정 변경 간소화
- Docker Compose 연동
- CI/CD 자동화
- 설정값을 코드와 분리
- 데이터베이스 주소와 포트 관리
예를 들어 개발 환경에서는 다음 값을 사용할 수 있습니다.
APP_ENV=development
DB_HOST=localhost
운영 환경에서는 다음처럼 변경할 수 있습니다.
APP_ENV=production
DB_HOST=production-db
Docker 이미지는 변경하지 않고 실행할 때 전달하는 값만 바꾸면 됩니다.
Dockerfile ENV 명령어
Dockerfile에서는 ENV 명령어로 기본 환경 변수를 설정할 수 있습니다.
FROM node:22
ENV NODE_ENV=production
ENV PORT=8080
WORKDIR /app
COPY . .
CMD ["node", "server.js"]
이미지를 빌드한 뒤 컨테이너를 실행하면 NODE_ENV와 PORT 환경 변수가 기본으로 설정됩니다.
환경 변수를 확인하려면 다음 명령을 사용합니다.
docker run --rm myapp env
특정 환경 변수만 확인할 수도 있습니다.
docker run --rm myapp printenv NODE_ENV
출력 결과는 다음과 같습니다.
production
ENV 여러 개 작성하기
환경 변수를 각각 작성할 수 있습니다.
ENV APP_ENV=production
ENV APP_PORT=8080
ENV LOG_LEVEL=info
한 줄로 작성하는 것도 가능합니다.
ENV APP_ENV=production \
APP_PORT=8080 \
LOG_LEVEL=info
가독성을 고려해 관련 있는 값끼리 묶어 작성하면 관리하기 편리합니다.
docker run -e 옵션 사용법
컨테이너 실행 시 -e 또는 --env 옵션을 사용하면 환경 변수를 직접 전달할 수 있습니다.
docker run -d \
--name web \
-e APP_ENV=production \
-e APP_PORT=8080 \
myapp
컨테이너 내부에서 값을 확인합니다.
docker exec web printenv APP_ENV
출력 결과는 다음과 같습니다.
production
Dockerfile ENV 값 덮어쓰기
Dockerfile에 기본값이 있어도 컨테이너 실행 시 -e 옵션으로 값을 변경할 수 있습니다.
Dockerfile 설정은 다음과 같습니다.
ENV APP_ENV=development
실행할 때 운영 환경으로 변경합니다.
docker run --rm \
-e APP_ENV=production \
myapp \
printenv APP_ENV
출력 결과는 다음과 같습니다.
production
일반적으로 실행 시 전달한 환경 변수가 Dockerfile에 정의된 기본값보다 우선합니다.
호스트 환경 변수 전달하기
호스트에 이미 설정된 환경 변수를 컨테이너에 전달할 수도 있습니다.
호스트에서 값을 설정합니다.
export APP_ENV=production
변수 이름만 지정하여 컨테이너에 전달합니다.
docker run --rm \
-e APP_ENV \
ubuntu \
printenv APP_ENV
출력 결과는 다음과 같습니다.
production
값을 명령어에 직접 작성하지 않고 현재 셸의 환경 변수를 사용할 때 편리합니다.
–env-file 사용법
환경 변수가 많아지면 -e 옵션을 반복해서 작성하기 불편합니다.
이때 환경 변수 파일을 사용할 수 있습니다.
app.env 파일을 생성합니다.
APP_ENV=production
APP_PORT=8080
DB_HOST=mysql
DB_PORT=3306
컨테이너 실행 시 파일을 지정합니다.
docker run -d \
--name web \
--env-file app.env \
myapp
파일에 작성된 모든 환경 변수가 컨테이너에 전달됩니다.
env 파일 작성 시 주의사항
일반적인 환경 변수 파일은 다음 형식으로 작성합니다.
KEY=value
예시는 다음과 같습니다.
APP_NAME=myapp
APP_PORT=8080
LOG_LEVEL=info
등호 앞뒤에 불필요한 공백을 넣지 않는 것이 좋습니다.
APP_PORT = 8080
위와 같은 형식은 예상하지 못한 값으로 처리되거나 오류 원인이 될 수 있습니다.
다음과 같이 작성하는 것이 안전합니다.
APP_PORT=8080
Docker Compose environment 사용법
Docker Compose에서는 environment 항목으로 환경 변수를 전달할 수 있습니다.
services:
web:
image: myapp
environment:
APP_ENV: production
APP_PORT: 8080
DB_HOST: mysql
목록 형식으로도 작성할 수 있습니다.
services:
web:
image: myapp
environment:
- APP_ENV=production
- APP_PORT=8080
- DB_HOST=mysql
두 방식 모두 사용할 수 있지만, 키와 값을 구분하는 형식이 읽기 편한 경우가 많습니다.
Docker Compose env_file 사용법
환경 변수를 별도 파일로 관리하려면 env_file을 사용합니다.
services:
web:
image: myapp
env_file:
- app.env
app.env 파일은 다음과 같습니다.
APP_ENV=production
APP_PORT=8080
DB_HOST=mysql
Compose를 실행합니다.
docker compose up -d
app.env 파일의 값이 컨테이너 환경 변수로 전달됩니다.
.env 파일이란?
Docker Compose는 프로젝트 디렉터리의 .env 파일을 변수 치환에 사용할 수 있습니다.
.env 파일을 작성합니다.
APP_IMAGE=myapp
APP_PORT=8080
DB_PASSWORD=example-password
compose.yaml에서 다음처럼 참조합니다.
services:
web:
image: ${APP_IMAGE}
ports:
- "${APP_PORT}:8080"
mysql:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
Compose 실행 시 ${변수명} 부분이 .env 파일 값으로 변경됩니다.
.env와 env_file의 차이
.env와 env_file은 비슷해 보이지만 용도가 다릅니다.
| 구분 | 주요 용도 |
|---|---|
.env | Compose 설정 파일의 변수 치환 |
env_file | 컨테이너 내부에 환경 변수 전달 |
environment | Compose 파일에서 컨테이너 환경 변수 직접 지정 |
docker run -e | 명령줄에서 환경 변수 전달 |
예를 들어 .env 파일의 WEB_PORT 값을 Compose 포트 설정에 사용할 수 있습니다.
WEB_PORT=8080
services:
web:
image: nginx
ports:
- "${WEB_PORT}:80"
반면 컨테이너 내부에서 직접 사용해야 하는 값은 environment 또는 env_file로 전달합니다.
환경 변수 우선순위 이해하기
같은 환경 변수가 여러 위치에 설정되어 있으면 나중에 전달되는 값이나 실행 시 지정한 값이 우선하는 경우가 많습니다.
예를 들어 Dockerfile에는 다음 값이 있습니다.
ENV APP_ENV=development
Compose 파일에는 다음 값이 있습니다.
environment:
APP_ENV: staging
실행 시 명령줄에서 값을 다시 전달합니다.
docker compose run \
-e APP_ENV=production \
web \
printenv APP_ENV
출력 결과는 다음과 같습니다.
production
실무에서는 같은 변수의 정의 위치가 너무 많아지지 않도록 관리 기준을 정하는 것이 중요합니다.
컨테이너 환경 변수 확인 방법
실행 중인 컨테이너의 전체 환경 변수를 확인합니다.
docker exec web env
특정 변수만 확인합니다.
docker exec web printenv DB_HOST
또는 Shell을 통해 확인할 수 있습니다.
docker exec web sh -c 'echo $DB_HOST'
Docker Inspect를 사용해 설정된 환경 변수를 확인할 수도 있습니다.
docker inspect web
출력 내용이 많다면 다음처럼 필요한 부분만 조회합니다.
docker inspect \
--format='{{range .Config.Env}}{{println .}}{{end}}' \
web
애플리케이션에서 환경 변수 읽기
Node.js에서는 다음과 같이 읽습니다.
const port = process.env.APP_PORT || 8080;
const environment = process.env.APP_ENV || "development";
Python에서는 다음과 같이 사용합니다.
import os
app_env = os.getenv("APP_ENV", "development")
app_port = os.getenv("APP_PORT", "8080")
Java Spring Boot에서는 다음 형식으로 참조할 수 있습니다.
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
애플리케이션 코드에 값을 고정하지 않고 환경 변수로 외부에서 전달하는 것이 핵심입니다.
환경 변수와 비밀번호 보안
환경 변수는 설정값을 분리하는 데 유용하지만 완전한 비밀 저장소는 아닙니다.
다음 명령을 통해 환경 변수가 노출될 수 있습니다.
docker inspect web
또는 컨테이너 내부에서 확인할 수 있습니다.
docker exec web env
따라서 중요한 운영 비밀번호와 API 키는 다음과 같은 방식으로 관리하는 것이 좋습니다.
- 환경 변수 파일을 Git에 올리지 않기
.gitignore에.env추가- 운영 서버의 접근 권한 제한
- CI/CD Secret 기능 사용
- Docker Secrets 또는 외부 비밀 관리 도구 사용
- 이미 빌드된 이미지에 비밀번호 포함하지 않기
.gitignore 예시는 다음과 같습니다.
.env
*.env
secrets/
Dockerfile에 비밀번호를 넣으면 안 되는 이유
다음과 같은 Dockerfile 작성은 피해야 합니다.
ENV DB_PASSWORD=my-secret-password
이 값은 이미지 설정과 빌드 기록에 남을 수 있으며, 이미지를 공유하면 다른 사용자에게 노출될 수 있습니다.
민감한 값은 이미지 빌드 단계가 아니라 컨테이너 실행 단계에서 전달하는 것이 좋습니다.
docker run -d \
-e DB_PASSWORD="$DB_PASSWORD" \
myapp
환경 변수가 적용되지 않을 때 확인할 사항
환경 변수가 정상적으로 적용되지 않는다면 다음 순서로 확인합니다.
1. 컨테이너 내부 값 확인
docker exec web printenv APP_ENV
2. Compose 설정 검증
docker compose config
변수 치환이 완료된 최종 설정을 확인할 수 있습니다.
3. 컨테이너 재생성
Compose 파일이나 환경 변수를 수정한 뒤 단순 재시작만 하면 새로운 설정이 적용되지 않을 수 있습니다.
docker compose up -d --force-recreate
또는 다음 명령으로 컨테이너를 다시 생성합니다.
docker compose down
docker compose up -d
4. 변수 이름 확인
다음처럼 변수 이름의 오타를 점검합니다.
DB_HOST
DBHOST
DATABASE_HOST
애플리케이션이 기대하는 변수 이름과 Docker에서 전달한 이름이 같아야 합니다.
5. 따옴표와 공백 확인
환경 변수 값에 공백이나 특수문자가 포함되면 따옴표 처리가 필요할 수 있습니다.
environment:
APP_MESSAGE: "hello docker"
실무에서 자주 사용하는 명령어
환경 변수 직접 전달
docker run -d \
-e APP_ENV=production \
myapp
여러 환경 변수 전달
docker run -d \
-e APP_ENV=production \
-e APP_PORT=8080 \
-e DB_HOST=mysql \
myapp
환경 변수 파일 사용
docker run -d \
--env-file app.env \
myapp
환경 변수 확인
docker exec web env
특정 변수 확인
docker exec web printenv APP_ENV
Compose 설정 확인
docker compose config
Compose에서 특정 환경 변수 전달
docker compose run \
-e APP_ENV=production \
web
실무 사례
온라인 쇼핑몰 애플리케이션을 Docker로 운영한다고 가정해 보겠습니다.
개발 환경에서는 다음 값을 사용합니다.
APP_ENV=development
DB_HOST=mysql-dev
DB_NAME=shop_dev
운영 환경에서는 다음 값을 사용합니다.
APP_ENV=production
DB_HOST=mysql-prod
DB_NAME=shop
애플리케이션 이미지는 동일하게 사용하고 환경 변수 파일만 구분합니다.
.env.development
.env.production
개발 환경 실행 명령은 다음과 같습니다.
docker run -d \
--env-file .env.development \
myapp
운영 환경은 다음처럼 실행합니다.
docker run -d \
--env-file .env.production \
myapp
이렇게 구성하면 환경별로 이미지를 다시 빌드하지 않아도 되며, 배포 과정도 단순해집니다.
자주 묻는 질문
Dockerfile의 ENV와 docker run의 -e는 무엇이 다른가요?
ENV는 이미지에 기본 환경 변수를 설정하고, docker run -e는 컨테이너를 실행할 때 값을 전달하거나 기본값을 변경합니다.
.env 파일은 자동으로 컨테이너에 전달되나요?
항상 그런 것은 아닙니다. Docker Compose의 .env 파일은 주로 Compose 설정의 변수 치환에 사용됩니다. 컨테이너에 값을 전달하려면 environment나 env_file 설정을 사용해야 합니다.
환경 변수에 비밀번호를 저장해도 되나요?
가능하지만 환경 변수는 docker inspect나 컨테이너 내부에서 확인될 수 있습니다. 중요한 비밀번호는 전용 Secret 관리 기능을 사용하는 것이 더 안전합니다.
환경 변수를 수정했는데 적용되지 않는 이유는 무엇인가요?
이미 실행 중인 컨테이너의 환경 변수는 자동으로 변경되지 않습니다. 컨테이너를 재생성해야 새로운 값이 적용됩니다.
Docker 환경 변수는 컨테이너 삭제 후 유지되나요?
환경 변수 자체는 컨테이너 설정에 포함됩니다. 컨테이너를 삭제하고 새로 생성하면 실행 명령이나 Compose 설정에 따라 다시 전달해야 합니다.
마무리
Docker 환경 변수는 애플리케이션 설정과 Docker 이미지를 분리하는 핵심 기능입니다.
Dockerfile의 ENV로 기본값을 설정하고, 실행 시 -e 또는 --env-file을 사용하면 환경에 따라 다른 값을 전달할 수 있습니다.
Docker Compose에서는 environment, env_file, .env 파일을 적절히 구분해 사용해야 합니다.
다만 비밀번호와 API 키 같은 민감한 정보는 이미지에 직접 포함하지 말고, 접근 권한이 제한된 환경 변수 파일이나 Secret 관리 기능을 사용하는 것이 좋습니다.