GitHub Actions를 활용해 CI/CD를 구축하는 프로세스를 알아보자
Spring Boot / Java 프로젝트를 기반으로 Docker를 활용해 Build하여 Docker Image를 생성하고, 이를 AWS EC2 상에서 컨테이너화하는 작업을 GitHub Actions로 자동화할 것임
Your-Repository
-Settings
-Secrets and variables
-Actions
DOCKERHUB_USERNAME
, DOCKERHUB_PASSWORD
APPLICATION_YML
(선택)Java with Gradle
을 베이스로 스크립트 생성
gradle.yml
파일 수정
(아래는 예시이며, 링크를 참고하여 스크립트를 이해하고 Customize 해보자)
name: Java CI with Gradle
# 동작 조건 설정: develop 브랜치에 push or pull request가 발생할 경우 동작
on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
permissions:
contents: read
jobs:
# Spring Boot 애플리케이션을 빌드하여 Docker Hub에 Push하는 과정
build-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 0. 외부 설정 파일 세팅 (application-db.yml)
- name: 외부 설정 파일 세팅
run: echo "${{ secrets.APPLICATION_DB_YML }}" > ./src/main/resources/application-db.yml
# 1. Java 21 세팅
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'corretto'
# 2. gradlew 권한 부여
- name: Run chmod to make gradlew executable
run: chmod +x gradlew
# 3. Spring Boot 애플리케이션 빌드
- name: Build with Gradle
run: ./gradlew build
# 4. Docker 이미지 빌드 & Push
- name: Docker Image Build & Push
run: |
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/project-name .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/project-name
※ 참고 사항
- 위 Secrets에서 등록한
APPLICATION.YML
변수를 활용하여# 0. 외부 설정 파일 세팅
부분에서 파일로 만들어주었음 (민감한 DBMS 정보 등을 담고 있음)- Docker Build & Push는 애플리케이션 코드 변경이 있을 때마다 Gradle Build와 함께 자동으로 수행되도록 CI 단계에 포함하였음
위의 스크립트를 적용하면,
develop
브랜치에 Push or Pull Request 발생 시에 Workflow가 실행되면서 Gradle Build와 Docker Build & Push까지 수행됨
이제 Docker Hub에 업로드된 Docker Image를 AWS EC2에서 컨테이너화(run) 하는 작업까지 추가해보자
: GitHub가 관리하는 인스턴스가 아닌, 사용자가 원하는 서버에서 Github Actions Application을 실행할 수 있는 기능
AWS EC2에 SSH 접속을 하기 위한 Access Key, GitHub Actions Secrets 등이 필요 없이 해당 서버에서 명령을 실행할 수 있음!!!
원하는 서버에서 GitHub Actions Runner를 1. 다운로드, 2. 설정, 3. 실행 과정을 거쳐야 한다.
Your-Repository
-Settings
-Actions
-Runners
클릭
New self-hosted runner
클릭
EC2에서 아래 명령어를 실행하여 Download & Configure
(./config.sh 까지만 실행함)
※ 위 과정 중 발생하는 오류 해결 방법 (Amazon Linux 사용 시 발생하는 오류)
- shasum 관련 오류
echo "64a47e18119f0c5d70e21b6050472c2af3f582633c9678d40cb5bcb852bcc18f actions-runner-linux-x64-2.316.0.tar.gz" | shasum -a 256 -c
-bash: shasum: command not found
오류 메시지 발생
(shasum: SHA 메시지 다이제스트, 암호화 체크섬, 암호화 해시코드를 계산하는 데 사용)따라서 아래 명령어를 실행해 shasum 설치
yum install perl-Digest-SHA
2. Libicu 종속성 오류./config.sh --url https://github.com/xxx --token xxx
Libicu's dependencies is missing for Dotnet Core 6.0 Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.
위 오류 메시지대로
sudo ./bin/installdependencies.sh
명령어를 입력해도 fedora linux인 관계로 종속성 설치가 이루어지지 않음따라서 아래 명령어를 통해 libicu 설치
sudo yum install libicu
이후 self-hosted runner aapplication을 서비스로 설정할 것임 (항상 자동 실행)
(Configuring the self-hosted runner application as a service 참고함)
아래 명령어를 입력해 서비스를 설치 및 시작함
sudo ./svc.sh install
sudo ./svc.sh start
이제 Github Actions를 수신할 준비가 완료됨
# 1.2 스크립트에 이어서...
# 위 build-docker-image 작업에서 Push한 이미지를 EC2에서 Pull & Run시키는 과정
run-docker-image-on-ec2:
# build-docker-image 작업이 완료되어야 실행됨
needs: build-docker-image
# self-hosted-runner에서 동작
runs-on: self-hosted
steps:
# 1. 최신 이미지 Pull
- name: docker pull
run: |
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/project-name
# 2. 기존 컨테이너 중지
- name: docker stop container
run: docker stop $(docker ps -q) 2>/dev/null || true
# 3. 최신 이미지 컨테이너화하여 실행시
- name: docker run new container
run: docker run --rm -d -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/project-name
# 4. 기존 이미지 정리
- name: delete old docker image
run: docker system prune -f
※ 참고 사항
docker pull
수행 전에 로그인을 해준 이유는 해당 이미지를 private 설정하였기 때문임docker run
에서--rm
옵션은 컨테이너가 종료될 때 컨테이너와 관련된 리소스 제거4. 기존 이미지 정리
부분에서 컨테이너 중지 후 삭제해 주어도 되지만 해당 부분을 뒤로 뺀 이유는 기존 이미지에서 공유하여 사용하던 레이어 부분을 다시 다운로드하도록 하지 않기 위해서임 (ex. demo 이미지가 a, b, c 레이어로 구성되어 있을 때, 최신 버전에서 a만 변경되었을 경우 a만 새로 다운로드함)
👍