# [Docker Compose 실습] Compose 파일 1차 정리하기
- Compose 파일 1차 정리하기 ← 현재 문서
이번 실습의 목표는 현재 Compose 파일을 "돌아가는 파일"에서 "읽고 관리할 수 있는 파일"로 바꾸는 것이다. 여기서는 앱 코드나 Dockerfile은 아직 고치지 않고, Compose 파일의 책임만 먼저 정리한다.
정리 기준은 단순하다. 각 서비스에는 그 서비스가 필요한 값만 넣는다.
1차 정리 방향
| 정리 항목 | 처리 |
|---|---|
version: '3.8' | 제거 |
| 프로젝트 이름 | name: discodeit 추가 |
container_name | 제거 권장 |
db.env_file | 제거하고 POSTGRES_*만 명시 |
app.env_file | 제거하고 앱에 필요한 변수만 명시 |
| DB 포트 | 로컬 DB 클라이언트가 필요하면 유지 |
| named volume | 유지 |
| healthcheck | 유지 |
container_name은 꼭 필요한 경우가 아니면 제거하는 편이 낫다. Compose는 기본적으로 프로젝트명-서비스명-번호 형태로 컨테이너 이름을 만든다. 이 기본 네이밍을 쓰면 같은 Compose 파일을 다른 프로젝트 이름으로 여러 벌 실행하기 쉽다.
정리된 Compose 예시
아래 예시는 현재 프로젝트 기준의 1차 정리안이다. 실제 값은 .env에 두고, Compose 파일에서는 필요한 변수만 골라 각 서비스에 전달한다.
name: discodeit
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "${APP_PORT:-8081}:80"
environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/${POSTGRES_DB}
SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER}
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD}
SPRING_JPA_HIBERNATE_DDL_AUTO: ${SPRING_JPA_HIBERNATE_DDL_AUTO:-update}
SPRING_JPA_SHOW_SQL: ${SPRING_JPA_SHOW_SQL:-false}
AWS_S3_ACCESS_KEY: ${AWS_S3_ACCESS_KEY}
AWS_S3_SECRET_KEY: ${AWS_S3_SECRET_KEY}
AWS_S3_REGION: ${AWS_S3_REGION}
AWS_S3_BUCKET: ${AWS_S3_BUCKET}
AWS_S3_PRESIGNED_URL_EXPIRATION: ${AWS_S3_PRESIGNED_URL_EXPIRATION:-600}
ADMIN_EMAIL: ${ADMIN_EMAIL}
ADMIN_USERNAME: ${ADMIN_USERNAME}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
JVM_OPTS: ${JVM_OPTS:-}
volumes:
- app_storage:/app/storage
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:15-alpine
ports:
- "${POSTGRES_HOST_PORT:-5432}:5432"
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
volumes:
- postgres_data:/var/lib/postgresql/data
- ./schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
restart: unless-stopped
volumes:
postgres_data:
app_storage:
healthcheck.test에서 $${POSTGRES_USER}처럼 달러를 두 번 쓴 점이 중요하다. Compose가 파일을 읽는 시점에 값을 먼저 치환하지 않고, 컨테이너 안에서 실행될 때 환경 변수를 읽게 하려는 의도다. 단순히 ${POSTGRES_USER}를 써도 현재는 동작할 수 있지만, healthcheck 명령을 컨테이너 환경 기준으로 읽히게 하려면 이 방식이 더 명확하다.
왜 env_file을 빼는가
env_file은 편하지만 경계를 흐린다.
env_file:
- .env
이 한 줄은 파일 안의 모든 변수를 해당 컨테이너에 넣는다. 작은 프로젝트에서는 편해 보이지만, 시간이 지나면 어떤 컨테이너가 어떤 비밀값을 알고 있는지 추적하기 어려워진다.
정리된 예시에서는 .env가 여전히 필요하다. 다만 .env는 Compose 파일의 ${...} 값을 채우는 저장소로 쓰고, 컨테이너에 들어가는 값은 environment에서 서비스별로 고른다.
APP_PORT와 POSTGRES_HOST_PORT를 추가하는 이유
현재 파일은 포트가 고정되어 있다.
ports:
- "8081:80"
- "5432:5432"
로컬에서 이미 5432를 쓰고 있으면 DB 컨테이너가 뜨지 않는다. 포트를 .env로 뺄 수 있게 하면 충돌을 피하기 쉽다.
APP_PORT=8081
POSTGRES_HOST_PORT=5433
이렇게 하면 앱은 localhost:8081, DB는 호스트에서 localhost:5433으로 접근한다. 컨테이너 내부의 DB 포트는 여전히 5432다. 앱의 JDBC URL은 db:5432 그대로 유지된다.
정리 후 확인
파일을 수정한 뒤에는 바로 실행하지 말고 먼저 구문과 해석 결과를 본다.
docker compose config
확인할 포인트는 다음과 같다.
version경고가 사라졌는가.db.environment에POSTGRES_*만 있는가.app.environment에 앱이 필요한 값만 있는가.ports가 원하는 호스트 포트로 풀렸는가.healthcheck가 유지되었는가.
env_file을 제거해도 environment에 secret을 넘기면 docker compose config에는 실제 값이 출력된다. 출력 공유 금지 원칙은 그대로 유지한다.
여기까지의 결과
이 단계가 끝나면 Compose 파일은 다음 상태가 된다.
- 최신 Compose에서 불필요한
version이 없다. - 프로젝트 이름이 명시되어 리소스 이름이 예측 가능하다.
- DB 컨테이너가 앱 secret을 받지 않는다.
- 앱 컨테이너가 필요한 Spring, AWS, JWT, Admin 값만 받는다.
- DB healthcheck와 named volume은 유지된다.
다음 실습에서는 앱 이미지와 Spring Boot 설정을 맞춘다. 특히 Dockerfile의 JAR 파일명 문제를 정리해야 한다.