이 글은 2022년 10월 기준 기록입니다.
앞서 환경마다 docker-compose.dev.yml, docker-compose.prod.yml을 따로 두는 방식으로 설정을 분리했습니다. 그런데 이 방식은 환경이 늘어날 때마다 거의 같은 내용의 파일이 한 벌씩 늘어납니다. 여러 개의 docker-compose.yml 파일을 사용하지 않고, 하나의 파일에 설정만 다르게 적용하는 방법은 없을까요.
Compose는 이미 .env 파일을 찾고 있다
docker compose 명령은 기본적으로 ".env"라는 이름의 파일을 찾아서 읽습니다. 따로 설정하지 않아도 동작하는 규칙이므로, 별도의 이름을 쓰고 싶을 때만 --env-file 옵션으로 지정하면 됩니다.
Compose 파일에서 값을 비우고 ${}로 남긴다
값을 직접 적는 대신 ${} 표기법으로 자리만 남겨 둡니다.
name: spring-db-test
services:
postgres-db:
image: postgres-iochord
expose:
- "5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ${INIT_LOCAL_CONTEXT}/${INIT_LOCAL_FOLDER_NAME}:/docker-entrypoint-initdb.d
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
spring-crud:
image: test-crud-app:latest
depends_on:
- postgres-db
expose:
- ${INTERNAL_PORT}
environment:
- SPRING_DATASOURCE_URL=${SPRING_DATASOURCE_URL}
- SPRING_DATASOURCE_USERNAME=${SPRING_DATASOURCE_USERNAME}
- SPRING_DATASOURCE_PASSWORD=${SPRING_DATASOURCE_PASSWORD}
- SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}
- JAR_FILE=${JAR_FILE}
load-balancer:
image: nginx
ports:
- ${EXTERNAL_PORT}:${LOAD_BALANCER_APP_PORT}
expose:
- ${LOAD_BALANCER_DB_PORT}
depends_on:
- spring-crud
- postgres-db
volumes:
- ./nginx-docker/load-balancer.conf:/etc/nginx/nginx.conf:ro
volumes:
postgres_data:
driver: local
name : postgres_test
이제 이 파일에는 환경에 따라 달라질 값이 하나도 남아 있지 않습니다. 포트 번호도, DB 이름도, 초기화 스크립트 경로도 전부 변수입니다.
환경의 차이는 .env 파일의 차이로만 남는다
첫 번째 환경(test.env)입니다.
# postgreSQL
POSTGRES_USER=springtest # postgres 슈퍼유저 생성
POSTGRES_PASSWORD=springtest # postgres 슈퍼유저 비밀번호
POSTGRES_DB=postgres # postgres default db
INIT_LOCAL_CONTEXT=.
INIT_LOCAL_FOLDER_NAME=init_db
# spring boot app
SPRING_DATASOURCE_URL=jdbc:postgresql://load-balancer:5432/postgres
SPRING_DATASOURCE_USERNAME=springtest
SPRING_DATASOURCE_PASSWORD=springtest
JAR_FILE=app.jar
HOST_PORT=8080
INTERNAL_PORT=8080 # 내부 스프링 앱이 compose 내부에 노출할 포트 번호
# nginx Load Balancer
EXTERNAL_PORT=80 # 호스트에 노출될 포트 번호
LOAD_BALANCER_APP_PORT=80 # 내부 로드밸런서가 리슨할 웹 포트 번호
LOAD_BALANCER_DB_PORT=5432 # 내부 로드밸런서가 리슨할 디비 포트 번호
두 번째 환경(dev.env)입니다. DB 이름이 postgres1로 바뀌었고, SPRING_PROFILES_ACTIVE=dev가 추가되었으며, 호스트에 노출되는 포트가 81로 달라졌습니다.
# postgreSQL
POSTGRES_USER=springtest # postgres 슈퍼유저 생성
POSTGRES_PASSWORD=springtest # postgres 슈퍼유저 비밀번호
POSTGRES_DB=postgres1 # postgres default db
INIT_LOCAL_CONTEXT=.
INIT_LOCAL_FOLDER_NAME=init_db
# spring boot app
SPRING_DATASOURCE_URL=jdbc:postgresql://load-balancer:5432/postgres1
SPRING_DATASOURCE_USERNAME=springtest
SPRING_DATASOURCE_PASSWORD=springtest
SPRING_PROFILES_ACTIVE=dev # application-dev.properties 선택
JAR_FILE=app.jar
HOST_PORT=8080
INTERNAL_PORT=8080 # 내부 스프링 앱이 compose 내부에 노출할 포트 번호
# nginx Load Balancer
EXTERNAL_PORT=81 # 호스트에 노출될 포트 번호
LOAD_BALANCER_APP_PORT=80 # 내부 로드밸런서가 리슨할 웹 포트 번호
LOAD_BALANCER_DB_PORT=5432 # 내부 로드밸런서가 리슨할 디비 포트 번호
".env" 파일에서 설정된 환경 변수 값을 ${} 표기법으로 docker-compose.yml 파일에서 읽어 오는 구조입니다.
config 명령이 치환된 최종 결과를 보여 준다
변수 치환이 제대로 되었는지는 컨테이너를 띄워 보기 전에 config로 확인할 수 있습니다. 먼저 test.env입니다.
$ docker compose --env-file test.env -f docker-compose.yml config
time="2022-10-07T15:11:45+09:00" level=warning msg="The \"SPRING_PROFILES_ACTIVE\" variable is not set. Defaulting to a blank string."
name: spring-db-test
services:
load-balancer:
depends_on:
postgres-db:
condition: service_started
spring-crud:
condition: service_started
expose:
- "5432"
image: nginx
networks:
default: null
ports:
- mode: ingress
target: 80
published: "80"
protocol: tcp
volumes:
- type: bind
source: C:\Users\사용자명\workspace\test\build\libs\docker_compose\nginx-docker\load-balancer.conf
target: /etc/nginx/nginx.conf
read_only: true
bind:
create_host_path: true
postgres-db:
environment:
POSTGRES_DB: postgres
POSTGRES_PASSWORD: springtest
POSTGRES_USER: springtest
expose:
- "5432"
image: postgres-iochord
networks:
default: null
volumes:
- type: volume
source: postgres_data
target: /var/lib/postgresql/data
volume: {}
- type: bind
source: C:\Users\사용자명\workspace\test\build\libs\docker_compose\init_db
target: /docker-entrypoint-initdb.d
bind:
create_host_path: true
spring-crud:
depends_on:
postgres-db:
condition: service_started
environment:
JAR_FILE: app.jar
SPRING_DATASOURCE_PASSWORD: springtest
SPRING_DATASOURCE_URL: jdbc:postgresql://load-balancer:5432/postgres
SPRING_DATASOURCE_USERNAME: springtest
SPRING_PROFILES_ACTIVE: ""
expose:
- "8080"
image: test-crud-app:latest
networks:
default: null
networks:
default:
name: spring-db-test_default
volumes:
postgres_data:
name: postgres_test
driver: local
test.env에는 SPRING_PROFILES_ACTIVE가 없으므로 경고가 뜨고, 값은 빈 문자열로 치환되었습니다. 정의하지 않은 변수가 있으면 조용히 넘어가지 않고 이렇게 알려 줍니다.
같은 Compose 파일에 dev.env를 물리면 결과가 달라집니다.
$ docker compose --env-file dev.env -f docker-compose.yml config
name: spring-db-test
services:
load-balancer:
depends_on:
postgres-db:
condition: service_started
spring-crud:
condition: service_started
expose:
- "5432"
image: nginx
networks:
default: null
ports:
- mode: ingress
target: 80
# =====================================================================================
published: "81"
# =====================================================================================
protocol: tcp
volumes:
- type: bind
source: C:\Users\사용자명\workspace\test\build\libs\docker_compose\nginx-docker\load-balancer.conf
target: /etc/nginx/nginx.conf
read_only: true
bind:
create_host_path: true
postgres-db:
environment:
POSTGRES_DB: postgres1
POSTGRES_PASSWORD: springtest
POSTGRES_USER: springtest
expose:
- "5432"
image: postgres-iochord
networks:
default: null
volumes:
- type: volume
source: postgres_data
target: /var/lib/postgresql/data
volume: {}
- type: bind
source: C:\Users\사용자명\workspace\test\build\libs\docker_compose\init_db
target: /docker-entrypoint-initdb.d
bind:
create_host_path: true
spring-crud:
depends_on:
postgres-db:
condition: service_started
environment:
JAR_FILE: app.jar
SPRING_DATASOURCE_PASSWORD: springtest
SPRING_DATASOURCE_URL: jdbc:postgresql://load-balancer:5432/postgres1
SPRING_DATASOURCE_USERNAME: springtest
# =====================================================================================
SPRING_PROFILES_ACTIVE: dev
# =====================================================================================
expose:
- "8080"
image: test-crud-app:latest
networks:
default: null
networks:
default:
name: spring-db-test_default
volumes:
postgres_data:
name: postgres_test
driver: local
노출 포트는 81이 되었고 SPRING_PROFILES_ACTIVE는 dev로 채워졌습니다. Compose 파일은 한 글자도 건드리지 않았습니다.
'IT·테크 > 인프라' 카테고리의 다른 글
| 컨테이너 오케스트레이션과 쿠버네티스 — Docker와 무엇이 다른가 (0) | 2026.07.29 |
|---|---|
| Docker Compose scale과 nginx 로드 밸런싱으로 부하 나누기 (0) | 2026.07.28 |
| Docker External Config — 환경 변수로 이미지 밖에서 설정 주입하기 (0) | 2026.07.28 |
| Docker Compose — 여러 컨테이너를 한 덩어리로 묶어 관리하기 (0) | 2026.07.26 |
| Docker 이미지와 컨테이너 — Spring Boot 앱으로 직접 만들어 보기 (2) | 2026.07.25 |