2025. 4. 3. 13:54ㆍAWS
이번에는 스프링부트의 배포를 자동화해볼 예정이다!
여러 방법이 있지만 나는 이미 리액트 앱을 GibHub Actions를 이용해서 배포해봤기 때문에 익숙한 이 방법으로 백엔드도 구축해볼거다.
하지만 나중에 젠킨스를 이용한 CI/CD 구축하는 방법도 꼭 공부해볼거다.
기존에 백엔드 배포를 하면서 EC2와 ECR은 세팅해두었기 때문에 이 부분은 건너뛰겠다.
모르는 분들은 제 이전 글들에 자세히 나와있으니 참고하면 좋을 듯 하다.
1. deploy.yml 파일 작성
.github/workflows 경로에 deploy.yml 파일을 생성한다. 리액트 앱 배포할 때 봐서 익숙하겠지만 해당 경로의 파일을 실행해서 자동화를 진행한다.
반드시 해당 경로에 deploy.yml 파일이 존재해야한다.
name: CI/CD to EC2 # 워크 플로우 이름, GitHub Actions에서 보여지는 이름
on:
push:
branches:
- dev # main 브랜치에 push될 때 실행
jobs:
spring-build:
runs-on: ubuntu-latest # ubuntu-latest 환경에서 실행
env:
IMAGE_URI: ${{ secrets.AWS_ECR_URI }}
REGION: ap-northeast-2
steps:
- name: Checkout source
uses: actions/checkout@v3 # GitHub 저장소 코드를 현재 실행 환경에 복사
- name: Set up Docker
uses: docker/setup-buildx-action@v3 # 고급 빌드 기능을 활성화 - 멀티 플랫폼 빌드나 캐시 최적화
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3 # AWS 사용자 인증
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
region: ${{ env.REGION }}
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2 # ECR 로그인
- name: Build and Push Docker image # 빌드하고 ECR에 도커 이미지 푸시
run: |
echo "Using image URI: $IMAGE_URI"
docker build --platform linux/amd64 -t $IMAGE_URI .
docker push $IMAGE_URI
- name: SSH to EC2 and Deploy
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.EC2_HOST }}
username: ec2-user
key: ${{ secrets.EC2_KEY }}
script: |
IMAGE_URI=${{ secrets.AWS_ECR_URI }}
REGION=${{ env.REGION }}
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $IMAGE_URI
docker stop spring-app || true
docker rm spring-app || true
docker pull $IMAGE_URI
docker run -d --name petlog -p 8080:8080 $IMAGE_URI
이렇게 deploy.yml 이 작성됐으면 중간에 환경변수들로 설정된 값들을 GitHub Secrets에 해준다.
만약 EC2에 해당 권한이 없다면 권한을 부여해준다.
에러 발생 application-dev.yml 파일을 찾을 수가 없다고..
나는 엥 분명 내 application-dev.yml을 COPY 하라고 했는데 왜 없다고 하는거지 의문이 들어 찾아보았다.
문제는 바로 GitHub Actions가 실행될 때 application-dev.yml이 존재하지 않기 때문이다.
GitHub Actions는 GitHub에 있는 파일들만 접근가능한데 나는 .gitignore 에 추가해놨기 때문에 올라가지 않는 것.
그래서 application.yml 파일이 작성되도록 추가해줘야한다.
name: CI/CD to EC2 # 워크 플로우 이름, GitHub Actions에서 보여지는 이름
on:
push:
branches:
- temp # dev 브랜치에 push될 때 실행
jobs:
spring-build:
runs-on: ubuntu-latest # ubuntu-latest 환경에서 실행
env:
IMAGE_URI: ${{ secrets.AWS_ECR_URI }}
REGION: ap-northeast-2
steps:
- name: Checkout source
uses: actions/checkout@v3 # GitHub 저장소 코드를 현재 실행 환경에 복사
- name: Set up Docker
uses: docker/setup-buildx-action@v3 # 고급 빌드 기능을 활성화 - 멀티 플랫폼 빌드나 캐시 최적화
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3 # AWS 사용자 인증
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.REGION }}
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2 # ECR 로그인
- name: Create application-dev.yml
run: |
echo "spring:
datasource:
url: ${{ secrets.SPRING_DATASOURCE_URL }}
username: ${{ secrets.SPRING_DATASOURCE_USERNAME }}
password: ${{ secrets.SPRING_DATASOURCE_PASSWORD }}
driver-class-name: com.mysql.cj.jdbc.Driver
servlet:
multipart:
max-file-size: 10MB
max-request-size: 30MB
mybatis:
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mappers/*.xml
type-aliases-package: com.petlog.userService.domain
jwt:
secret:
key: ${{ secrets.JWT_SECRET_KEY }}
aws:
s3:
bucket: ${{ secrets.AWS_S3_BUCKET }}
credentials:
accessKey: ${{ secrets.AWS_ACCESS_KEY_ID }}
secretKey: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
region: ap-northeast-2" > src/main/resources/application-dev.yml
- name: Build and Push Docker image # 빌드하고 ECR에 도커 이미지 푸시
run: |
echo "Using image URI: $IMAGE_URI"
docker build --platform linux/amd64 -t $IMAGE_URI .
docker push $IMAGE_URI
- name: SSH to EC2 and Deploy
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_KEY }}
script: |
IMAGE_URI=${{ secrets.AWS_ECR_URI }}
REGION=${{ env.REGION }}
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $IMAGE_URI
docker stop petlog || true
docker rm petlog || true
docker pull $IMAGE_URI
docker run -d --name petlog -p 8080:8080 $IMAGE_URI
그래서 이렇게 코드를 바꾸고 깃헙시크릿에 환경변수도 더 추가해주었다.
그리고 10번만에 성공 🥳
글은 간략하게 썼지만 잔잔한 오류들이 계속 떴었다,, 하지만 해결해나가는 거 너무 재밌고요,,~
하지만 여기서 끝이 아니였다.
제대로 실행되는지 EC2에 가서 확인해보기로 했다. 원래라면 docker ps 명령어를 입력했을 때 컨터이너가 실행중이여야한다.
실패!
키자마자 바로 꺼져버린 내 컨테이너,, 로그를 봐보자
Config data resource 'file [/app/application.yml]' via location 'file:/app/application.yml' does not exist
Action:
Check that the value 'file:/app/application.yml' is correct, or prefix it with 'optional:'
이 에러는 application.yml이 Docker 컨테이너 안에 없기 때문에 발생한 오류다.
# 빌드 과정
FROM openjdk:17-jdk-slim AS builder
WORKDIR /app
# xargs가 필요하므로 필수 유틸 설치
RUN apt-get update && apt-get install -y findutils
COPY . .
RUN ./gradlew build -x test --no-daemon
# 이미지 생성 과정
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=builder /app/build/libs/*SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=file:/app/application.yml"]
내 도커파일을 보면 ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=file:/app/application.yml"] 이부분에서 컨테이너 내부의 /app/application.yml 파일을 Spring Boot가 찾으려고 하는데 없어서 오류가 나는 것이다.
왜그러냐면 deploy.yml에서 echo "spring: ..." > src/main/resources/application-dev.yml 로 application-dev.yml 파일을 생성했지만 이걸 도커파일로 복사를 안해서 그런것
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.profiles.active=dev"]
그래서 Spring Boot가 기본으로 application.yml, application-dev.yml을 병합해주도록 위와 같은 코드로 바꿔주었다.
그리고 다시 EC2 인스턴스를 확인해주었더니 아주 잘 떠있다!
지난번 리액트앱 CI/CD 구축했을 때랑 같은 Github Actions를 이용해서 그런지 이번에는 나름 수월했다.
이래서 경력직 경력직 하는구나,,~
'AWS' 카테고리의 다른 글
스프링부트 배포 HTTPS로 변경하기 (0) | 2025.04.02 |
---|---|
SpringBoot 프로젝트 Doker로 배포하기 (0) | 2025.04.01 |
리액트 앱 Github Actions를 이용하여 CI/CD 구축하기 (0) | 2025.04.01 |
리액트 AWS S3 + CloudFront로 배포하기 - 2. 도메인 구매 + Route 53 + ACM 설정 (0) | 2025.03.31 |
리액트 AWS S3 + CloudFront로 배포하기 - 1. S3, CloudFront 설정 (0) | 2025.03.31 |