Spring Boot 애플리케이션 Docker 라이징: 개발부터 배포까지 한 번에 끝내기
1. 서론: “내 로컬에서는 잘 되는데요?“의 종말
개발 환경에서는 잘 돌아가던 코드가 운영 서버에만 올라가면 OS 환경 차이, 라이브러리 버전 문제로 죽어버리는 경우가 많습니다. Docker는 애플리케이션과 그에 필요한 모든 라이브러리, 설정을 하나의 ‘컨테이너’로 묶어 어디서든 동일하게 실행되도록 보장합니다.
현대적인 개발자라면 반드시 마스터해야 할 Spring Boot의 Dockerizing 기법을 상세히 알아보겠습니다.
2. 효율적인 Dockerfile 작성을 위한 멀티 스테이지 빌드
단순히 JAR 파일을 통째로 복사하는 방식은 이미지 용량이 너무 커집니다. 빌드 단계와 실행 단계를 나누는 **멀티 스테이지 빌드(Multi-stage Build)**를 사용하면 보안과 성능을 모두 챙길 수 있습니다.
최적화된 Dockerfile 예시
# 1단계: 빌드 스테이지
FROM eclipse-temurin:21-jdk-jammy AS build
WORKDIR /app
COPY . .
# 권한 부여 및 빌드 (테스트 제외)
RUN chmod +x ./gradlew
RUN ./gradlew clean bootJar -x test
# 2단계: 실행 스테이지 (최소 용량 이미지 사용)
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
# 빌드 스테이지에서 생성된 JAR만 복사
COPY --from=build /app/build/libs/*.jar app.jar
# 보안을 위해 비루트(Non-root) 사용자 생성 및 실행
RUN useradd -m myuser
USER myuser
ENTRYPOINT ["java", "-jar", "app.jar"]
EXPOSE 8080
3. 실무 사례: 컨테이너 기반의 무중단 배포 환경 구축
상황: 새로운 기능을 배포할 때마다 서버를 잠시 꺼야 하는 상황입니다.
해결책: Docker를 활용하면 신규 버전의 컨테이너를 먼저 띄우고, Nginx의 리버스 프록시 설정을 변경하여 트래픽을 넘기는 방식으로 무중단 배포(Blue-Green Deployment)를 손쉽게 구현할 수 있습니다.
# 1. 신규 버전 이미지 빌드
docker build -t chanyeols-app:v2.0 .
# 2. 신규 컨테이너 실행 (8081 포트)
docker run -d --name app-v2 -p 8081:8080 chanyeols-app:v2.0
# 3. Nginx 설정 변경 (8080 -> 8081) 및 Reload
# 4. 기존 v1.0 컨테이너 종료
docker stop app-v1 && docker rm app-v1
4. Dockerize 시 주의할 점 (Best Practices)
- 레이어 캐싱 활용: 자주 바뀌지 않는 의존성(gradle, pom.xml)을 먼저 복사하고 빌드하면, 다음 빌드 속도가 비약적으로 빨라집니다.
- 최소 권한 원칙: 컨테이너 내부에서
root권한으로 프로세스를 실행하는 것은 보안에 취약합니다. 위 예시처럼 전용 사용자를 생성하세요. - 환경 변수 활용: DB 접속 정보와 같은 민감 정보는 Dockerfile에 적지 말고,
docker run -e옵션이나env파일을 통해 주입해야 합니다.
5. 마치며: 컨테이너 환경으로의 초대
Docker를 도입하는 것은 단순히 배포 방식을 바꾸는 것을 넘어, 전체 개발 워크플로우를 표준화하는 일입니다. 오늘 만든 Docker 이미지는 나중에 쿠버네티스(Kubernetes) 환경으로 확장할 때도 그대로 사용할 수 있습니다.
애드센스 승인을 위한 블로그 운영도 중요하지만, 이렇게 자동화된 배포 환경을 구축해보는 경험은 여러분을 더 높은 수준의 엔지니어로 만들어줄 것입니다.