이 글은 2022년 10월 기준 기록입니다.
동일한 서비스를 여러 개 작동시켜 각 컨테이너에게 전달되는 부하를 줄여 봅니다.
--scale 옵션이 같은 서비스를 여러 개 띄운다
Docker Compose를 실행할 때 --scale 옵션을 사용하면 동일한 서비스를 여러 개 작동시킬 수 있습니다.
$ docker compose --env-file test.env up -d --scale spring-crud=3 --scale postgres-db=2 --no-recreate
--scale에는 서비스 이름에 대한 개수를 지정하면 되고, 지정하지 않은 서비스는 자동으로 1로 지정됩니다. 함께 붙인 --no-recreate 옵션은 변경이 필요한 컨테이너만 조작하도록 해 줍니다. 이미 잘 돌고 있는 컨테이너까지 다시 만들 이유는 없기 때문입니다.
호스트 포트는 중복 할당할 수 없다
여기서 곧바로 걸리는 제약이 있습니다. 호스트 포트를 중복으로 할당할 수 없다는 점입니다. 같은 서비스를 세 개 띄웠는데 셋 다 호스트의 8080을 쓸 수는 없습니다.
해법은 두 갈래입니다. 호스트 포트의 범위를 주거나, 부하 분산을 담당하는 컨테이너를 활용하는 것입니다.
첫 번째 해법 — 호스트 포트를 범위로 준다
.env 파일에서 해당 서비스가 사용할 호스트 포트를 범위로 지정합니다.
# 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-8085
# ==================================================================
INTERNAL_PORT=8080 # 내부 스프링 앱이 compose 내부에 노출할 포트 번호
# nginx Load Balancer
EXTERNAL_PORT=81 # 호스트에 노출될 포트 번호
LOAD_BALANCER_APP_PORT=80 # 내부 로드밸런서가 리슨할 웹 포트 번호
LOAD_BALANCER_DB_PORT=5432 # 내부 로드밸런서가 리슨할 디비 포트 번호
이렇게 하면 호스트로 노출되는 포트를 여러 개 사용하여 각각 해당하는 컨테이너로 접근할 수 있습니다. 다만 접근하는 쪽이 포트 번호를 골라야 한다는 점은 그대로 남습니다.
두 번째 해법 — nginx를 앞에 세운다
부하 분산을 컨테이너 하나에 맡기면 바깥에서는 진입점 하나만 알면 됩니다. nginx를 이용해 구현합니다.
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.template
environment:
- INTERNAL_PORT=${INTERNAL_PORT}
# ================= nginx 설정 파일에서 환경 변수를 사용하기 위해 envsubst를 사용한다.
command: /bin/bash -c "envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"
volumes를 이용해 nginx 설정 파일을 적용합니다. 다만 설정 파일 안에서도 환경 변수를 쓰고 싶으므로, 파일을 곧바로 nginx.conf로 넣지 않고 nginx.conf.template으로 넣은 뒤 envsubst로 치환한 결과를 nginx.conf로 만들어 nginx를 기동합니다.
설정 파일은 다음과 같습니다.
user nginx;
events {
worker_connections 1000;
}
stream {
upstream postgres {
server postgres-db:5432;
}
server {
listen 5432;
proxy_pass postgres;
}
}
http {
server {
listen 80;
location / {
proxy_pass http://spring-crud:${INTERNAL_PORT};
}
}
}
DB는 stream 블록에서 TCP 수준으로, 웹은 http 블록에서 proxy_pass로 넘깁니다. 두 경우 모두 대상이 개별 컨테이너가 아니라 Compose의 서비스 이름(postgres-db, spring-crud)이라는 점이 핵심입니다. 서비스 이름으로 보내면 스케일된 컨테이너들로 요청이 흩어집니다.

전체 구조는 이렇게 됩니다. 호스트의 80 포트로 들어온 요청은 Compose 안의 NGINX 로드 밸런서에 도착하고, 로드 밸런서는 8080 포트로 동작하는 세 개의 Spring Boot App과 5432 포트로 동작하는 두 개의 PostgreSQL로 요청을 나눠 보냅니다. 어떤 .env를 물릴지는 --env-file 옵션으로, 스프링이 읽을 프로필은 application*.properties로 각각 고릅니다.
'IT·테크 > 인프라' 카테고리의 다른 글
| 컨테이너 오케스트레이션과 쿠버네티스 — Docker와 무엇이 다른가 (0) | 2026.07.29 |
|---|---|
| Docker Compose에서 .env 파일 하나만 바꿔 끼우기 (0) | 2026.07.28 |
| Docker External Config — 환경 변수로 이미지 밖에서 설정 주입하기 (0) | 2026.07.28 |
| Docker Compose — 여러 컨테이너를 한 덩어리로 묶어 관리하기 (0) | 2026.07.26 |
| Docker 이미지와 컨테이너 — Spring Boot 앱으로 직접 만들어 보기 (2) | 2026.07.25 |