Spring Boot 애플리케이션 AWS 배포 - 1 🐳

Lzhtk·2025년 7월 8일

Spring Boot에서 개발한 백엔드 어플리 케이션을 Docker로 컨테이너화하고, AWS에 배포하며, Github Actions로 자동화하는 실제 서비스 수준의 백엔드 구축 흐름을 단계별로 정리해볼 것이다.

이번 글에서는 1,2단계로 애플리케이션 컨테이너화와 Docker Compose 구성을 알아보자.


1단계 - 애플리케이션 컨테이너화 (Dockerfile) 📦


  • why? 🤔
    • 로컬 개발 환경과 운영 환경을 완전히 동일하게 유지하기 위해 필요하다.
    • Sprin Boot appication을 이식 가능한 실행 환경인 Docker 이미지로 패키징하기 위하여 필요하다.
    • 나중에 AWS ECS에서 해당 Docker 이미지 기반으로 배포하게 되기에 필요하다.
  • Dockerfile 예시 ✅
# --------------------------
# 1단계: Build Stage
# FROM gradle:8.2.1-jdk17 AS build : Gradle이 설치된 이미지를 사용하여 환경 일관성 유지
# WORKDIR /app :  컨테이너 내 작업 디렉토리 설정 ( cd /app 같은 효과 )
# COPY . . : 로컬 프로젝트 소스를 컨테이너로 복사
# --------------------------
FROM gradle:8.2.1-jdk17 AS build
WORKDIR /app
COPY . .
RUN ./gradlew clean bootJar

# --------------------------
# 2단계: Runtime Stage
# COPY --from=build ... : 빌드 단계에서 만든 JAR만 복사
# COPY entrypoint.sh . : 실행 스크립트 추가
# RUN chmod +x entrypoint.sh : 실행 권한 부여
# --------------------------
FROM amazoncorretto:17
WORKDIR /app
COPY --from=build /app/build/libs/*.jar app.jar
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh

# 실행에 필요한 환경 변수들
ENV PROJECT_NAME=discodeit
ENV PROJECT_VERSION=1.2-M8
ENV JVM_OPTS=""

EXPOSE 80
ENTRYPOINT ["./entrypoint.sh"]
  • 왜 멀티 스테이지로? 🤔

    • Gradle, 소스코드 등은 런타임에 필요없기에 불필요한 파일을 제거하여 최종 이미지를 슬림하게 만들기 위함이다.
  • entrypoint.sh

#!/bin/sh
exec java $JVM_OPTS -jar app.jar
  • entrypoint.sh를 사용해서 얻는 장점 ❗

    • JVM 옵션은 AWS ECS에서 환경 변수로 주입 가능
    • jar 이름을 하드코딩하지 않고 자동 복사를 하여 유연성을 향상 시킬 수 있다.
  • .dockeringnor활용

    • .dockerignore을 활용하여 불필요한 파일을 제외해서 빌드 속도 향상 + 보안 강화를 할 수 있도록 하자❕

2단계 - Docker Compose 구성 🐳

  • why? 🧐
    • 기존 로컬 개발방식의 문제점이 있다.
      • DB 설치/설정을 따로 해줘야함
      • 애플리케이션 실행 순서 신경 써야함 ( ex - EB 먼저 실행 )
      • 파일 경로, 환경변수 관리 어려움
    • 이러한 문제점은 Docker Compose로 해결 가능
      • 앱 + DB 동시 실행
      • .env 파일로 환경변수 통합 관리
      • 볼륨을 이용한 데이터 보존
      • 초기 schema.sql 자동 실행 가능
  • docker-compose.yml 구성 예시 ✅
version: "3.8"

services:
  app:
    build: .
    ports:
      - "8081:80"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      STORAGE_TYPE: local
      DATABASE_URL: jdbc:postgresql://postgres:5432/discodeit
      DATABASE_USERNAME: discodeit_user
      DATABASE_PASSWORD: discodeit1234
    volumes:
      - .discodeit/storage:/app/.discodeit/storage
    depends_on:
      - postgres

  postgres:
    image: postgres:17
    environment:
      POSTGRES_DB: discodeit
      POSTGRES_USER: discodeit_user
      POSTGRES_PASSWORD: discodeit1234
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./schema.sql:/docker-entrypoint-initdb.d/schema.sql

volumes:
  pgdata:

서비스별 상세 설명 🔍

  • app 서비스 ( Spring Boot 애플리케이션 ) 🌱

    • build: .
      • Dockerfile을 사용해 로컬에서 이미지 빌드
    • ports
      • 8081:80 -> 로컬 8081 -> 컨테이너의 80 포트 연결
      • Dockerfile에서 EXPOSE 80했으므로 컨테이너 내부 포트는 80
      • 개발중에 포트 충돌을 피하기 위하여 8081로 매핑
    • environment
      • Spring 환경변수 전달 ( prod, DB 설정 등 )
    • voulumes
      • 로컬 경로 -> 컨테이너 내 데이터 경로 바인딩
    • depends_on
      • postgres 서비스보다 나중에 실행되도록 지정
  • postgres 서비스 ( PostgreSQL DB ) 🐘

    • image
      • 공식 POSTGRESQL 17 사용
    • environment
      • DB 이름, 유저, 비밀번호 설정
    • ports
      • 5432:5432 -> 로컬에서 DB 접속 가능
    • volumes
      • 데이터 지속성 및 초기 schema 실행을 위해 두 가지 마운트
      • 위에 말한 docker-compose의 장점 중 하나로 컨테이너가 재시작되거나 삭제되어도
        파일이나 DB 데이터가 유지되도록하는 저장소 역할을 한다
    • ./schema.sql:/docker-entrypoint-initdb.d/schema.sql
  • .env 파일 예시

SPRING_PROFILES_ACTIVE=prod
STORAGE_TYPE=local
DATABASE_URL=jdbc:postgresql://postgres:5432/discodeit
DATABASE_USERNAME=discodeit_user
DATABASE_PASSWORD=discodeit1234
  • 위와 같은 예시의 형태로 .env 파일을 만들어서 변수화 가능
  • 해당 파일은 굉장히 민감한 정보이기에 반드시 .gitignore에 등록해야한다.
  • 아래와 같은 형태로 참조 가능하다.
environment:
  - SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}

정리

  • 1단계의 Dockerfile이 잘 구성되어 있어야 하는 이유
    • Docker Compose에서 Dockerfile을 사용해 로컬에서 이미지를 빌드하기에 Dockerfile이 잘 구성되어야 한다.
    • 나중에 AWS ECS에서 해당 Docker 이미지 기반으로 배포하게 되기에 Dockerfile이 잘 구성되어 있으면 ECS에서도 손쉽게 배포가 가능하다.
    • 추후에 Github Actions에서도 그대로 빌드/배포가 가능하기에 잘 구성하여야하낟.
  • 2단계의 Docker Compose가 잘 구성되어 있어야 하는 이유
    • 해당 설정을 기반으로 AWS S3 저장소 고도화를 진행하기 때문에 잘 구성해두어야 한다.
    • 추후에 Github Actions에서도 docker-compose를 로컬 테스트용으로 활용 가능하다.

0개의 댓글