spring boot 프로젝트를 github actions, docker를 활용하여 EC2에 배포하는 과정을 담았다. AWS EC2 인스턴스 생성(Ubuntu 22.04), EC2에 docker설치, Docker hub 계정이 있다는 가정하에 진행한다.
기존 배포 방법의 문제점
기존에 CI/CD 를 구축하지 않고 배포를 진행할 때, 우리는 spring boot 프로젝트를 직접 build 해서 jar 파일을 EC2에 Filezila 등으로 옮기고, java -jar 명령어를 실행하여 프로젝트를 실행했다. 프로젝트를 진행하면서 코드의 수정이 빈번하게 일어날 텐데, 매번 이런 과정을 거치는 것은 매우 비효율 적이다. CI/CD를 구축해 두면 이 과정을 자동화할 수 있어 개발 생산성을 높일 수 있다.
Github Actions vs Jenkins
Github Actions는 Jenkins와 비교하면 CI 서버가 따로 필요하지 않다. Github 자체의 서버 인프라를 CI 서버로 활용할 수 있어서 따로 서버 설정을 해주지 않아도 되어 매우 편리하다.
CI / CD 구축하기
개발 환경은 spring boot v3.2.4, Java17 이다. 잘 배포가 되었는지 확인하기 위해 TestController를 하나 작성했다. 버전을 변경하고 배포를 진행하여 배포가 잘 되었는지 확인하기 위함이다.
Dockerfile 작성
도커 이미지로 빌드할 도커 파일을 작성한다.
FROM bellsoft/liberica-openjdk-alpine:17
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
# 도커 컨테이너를 시작할 때 실행할 명령어
ENTRYPOINT ["java","-jar","/app.jar"]
Github Actions workflow 파일 작성
workflow를 작성하기 위해, 레포지토리를 하나 만들고 Actions 탭에 들어가서 파일을 작성한다. workflow의 순서는 다음과 같다.
- main 브랜치 이벤트 발생시 작성한 workflow 실행
- spring boot 프로젝트 build
- workflow에 따라 docker 이미지 빌드
- docker hub에 이미지 push
- EC2에서 docker hub의 이미지 pull
- 이미지 실행
name: CI/CD using github actions & docker
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
# Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- name: Build with Gradle Wrapper
run: ./gradlew build
# Docker build & Push
- name: Docker build & push to Docker hub
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/docker-test .
docker push ${{ secrets.DOCKER_USERNAME }}/docker-test
# EC2 배포
- name: Docker image pull & Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }} # EC2 인스턴스 퍼블릭 DNS
username: ubuntu
key: ${{ secrets.EC2_PRIVATE_KEY }} # pem 키
# 도커 작업
script: |
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/docker-test:latest
sudo docker stop $(sudo docker ps -a -q)
sudo docker run -d --log-driver=syslog -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/docker-test:latest
sudo docker rm $(sudo docker ps --filter 'status=exited' -a -q)
sudo docker image prune -a -f
workflows 디렉토리에 방금 작성한 파일이 저장된다.
Github secrets 변수 설정
workflow에서 사용할 민감한 정보들을 Secrets 환경 변수로 등록하여 사용할 수 있다. EC2 퍼블릭 IP와 생성 시 얻은 pem 키를 등록한다. pem 키는 '-----BEGIN RSA PRIVATE KEY-----' 와 '-----END RSA PRIVATE KEY-----' 부분까지 포함해서 넣으면 된다.
테스트
controller의 version을 수정하고 github 레포지토리 main에 push 해본다.
성공한 모습을 볼 수 있다. 배포한 EC2 퍼블릭 ip로 접속해보자.
배포 성공!