PR-Deliver 사이드 프로젝트를 하면서, 무료이고, 간단하게 인프라를 구성하고 싶었다. 특히 CI/CD 를 좀 편하게 하고 싶어서 (Code-deploy 등 다른거 없이 순수 GIthub-Actions로만) 이 방식으로 진행 해 보았다.
장점으로는 빌드, 컨테이너 이미지 생성 등 프리티어 환경에서는 다소 무거울 수 있는(사실 그렇게 무겁지도 않지만, t2-micro 라는 귀여운 사이즈 때문에...무겁다) 작업을 Github-Actions 로 해결해서, EC2 메모리가 터져버리는 상황을 막을 수 있을 것이다. (메모리 가상화 등도 필요가 없다)
FROM openjdk:17
# JDK17 사용
ARG JAR_FILE_PATH=./build/libs/*.jar
# gradle build 후 생성되는 jar 파일
COPY ${JAR_FILE_PATH} app.jar
# jar 파일을 app.jar 파일로 카피
ENV JASYPT_ENCRYPTOR_PASSWORD=""
#JASYPT 패스워드를 명시적으로 "" 선언함으로써, 변수가 주입되지 않으면 빈 문자열이 주입
ENTRYPOINT ["java", "-Djasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD}","-jar", "/app.jar"]
# "-Djasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD}" Jasypt 패스워드 주입 (Github Actions)
나의 경우엔 Jasypt 를 통해 application.yml 파일을 암호화하여 관리하고 있기 때문에, Docker run 시에 Jasypt 비밀번호를 환경변수로 주입하는 형식으로 관리했다.
비밀번호는 Github 시크릿으로 관리되며, Github-Actions 워크플로우로 트리거 되어 변수 주입된다.
name: Java CI with Gradle and Docker
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. GitHub 저장소에서 코드 체크아웃
- name: Checkout repository
uses: actions/checkout@v4
# 2. JDK 17 설치
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
# 3. Gradle 빌드
- name: Build with Gradle
run: ./gradlew build
# 4. Docker 이미지 빌드
- name: Build Docker image
run: docker build -f Dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/pr-deliver .
# 5. Docker Hub 로그인
- name: DockerHub login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
# 6. Docker Hub에 이미지 푸시
- name: Push Docker image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/pr-deliver
# 7. SSH를 통해 EC2 인스턴스에 접속하여 애플리케이션 배포
- name: Deploy to EC2 via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
# Docker Hub에서 최신 이미지 풀
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/pr-deliver
# 기존 컨테이너가 실행 중이면 중지
docker stop pr-deliver || true
# 기존 컨테이너 삭제
docker rm pr-deliver || true
# 새로운 컨테이너 실행
docker run --name pr-deliver --rm -d -p 8080:8080 \
-e JASYPT_ENCRYPTOR_PASSWORD=${{ secrets.JASYPT_PASSWORD }} \
${{ secrets.DOCKERHUB_USERNAME }}/pr-deliver
시퀀스는 아래와 같다
위까지가 CI 과정이며,
잘 배포되는 모습!
--
TODO LIST