[CI/CD] Github Action 을 이용하여 EC2에 무료로 Spring Boot 프로젝트 빌드, 배포하기
개인 Spring Boot 프로젝트를 하면서 최저 비용으로 개발 서버를 구성하기 위한 방법을 모색중에 처음으로 Github Action을 사용해보았다. 나와 비슷한 상황의 분들도 아래 방법을 고려해보면 좋을 것 같아서 기록으로 남겨본다.
1. AWS Freetier 를 이용하여 EC2 t2.micro 를 생성한다. (이미 Freetier 기간이 지난 계정은 t2.micro 생성 시 과금이 되므로 새로 AWS 계정을 생성한다.)
2. Spring Boot 소스 코드를 Commit 할 때 마다 빌드, 배포를 자동화하고 싶은데 이 때 사용되는 Tool 에는 Jenkins, AWS Code Series 등이 있다. Jenkins의 경우에는 무료 오픈 소스이나, Jenkins web을 띄울 서버가 필요하며 이는 관리포인트가 하나 더 늘어남을 의미한다. AWS Code Series 는 Git 저장소인 Code Commit 와 Build 툴인 Code Build, Deploy 툴인 Code Deploy 삼총사를 일컫는 서비스이다. 세 서비스 모두 Freetier 경우에는 과금이 되지 않는 것으로 나와있는데, Code Build 할 때 Build Artifact를 S3 에 저장하고, 데이터 전송이 일어나기 때문에 이 때 과금이 될 수 있다. 정확히 어느 포인트에서 과금이 발생하는지 알 수 없는 부분이 있어서 나는 무료인 Github Action 을 알아보게 되었다.
3. Github Action 의 경우에는 Github Web Console 의 해당 소스코드 Repository 에서 쉽게 integration 할 수 있다.
4. 나는 AWS EC2 에 Docker Daemon 을 띄워 Spring Boot 소스를 Docker Image로 만들어 구동하고 있다. 그래서 해당 EC2 에 Java를 깔 필요가 없다. 하나 주의할 점은 Docker Image의 경우에는 Image 를 만드는 서버 종류와 해당 Image 를 실행하는 서버의 종류가 같아야 한다. Mac 에서 만든 docker image를 aws linux 2 (ec2) 에서 돌릴려니까 안되더라...!!!
5. 그래서 Github Action 의 gradle.yml 에 job build run on 을 내가 배포할 EC2 종류와 동일하게 맞춰준다.
6. 배포할 서버의 IP 와 Pem key 의 경우에는 기밀이므로, 반드시 Repository > Setting > Secret 에 등록하여, gradle.yml 에 기밀이 누출되지 않도록 주의한다.
아래는 내가 사용중인 gradle.yml 이다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Gradle
run: ./gradlew bootJar
- name: Build Docker image and Push it to ECR
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run : |
aws ecr get-login-password --region ap-northeast-2 | sudo docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REPO_URL }}
sudo docker build -t hooonk-api -f Dockerfile .
sudo docker tag hooonk-api:latest ${{ secrets.AWS_ECR_REPO_URL }}:latest
aws ecr batch-delete-image --region ap-northeast-2 --repository-name hooonk-api-dev --image-ids imageTag=latest
sudo docker push ${{ secrets.AWS_ECR_REPO_URL }}:latest
- name : Pull docker image and Deploy it
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ubuntu
key: ${{ secrets.KEY }}
script: |
cd ~
echo `pwd`
sh ./dockerStop.sh
docker rmi `docker images|awk '$1 ~/hooonk-api/{print$3}'`
sh ./dockerPull.sh
sh ./dockerRun.sh
docker system prune
AWS private ECR 은 Freetier 계정에 500MB 용량만큼은 무료이다. 그래서 ECR 에 있던 latest image 를 삭제하는 Command 가 있다.
상용에 적용할 때는 비용 보다는 안정성이므로 추구하는 목표를 고려하여 gradle.yml 을 구성하면 되겠다.
How to 는 아래 포스팅을 참고하여 진행하였다.
https://velog.io/@rmswjdtn/Spring-Docker-Github-Action-Spring-Boot-자동배포환경-만들기