[CI/CD] Github Actions로 CI/CD 파이프라인 구축하기 with Docker hub
환경 세팅
1. Dockerfile에 아래 스크립트가 포함되어 있는지 확인 (COPY 명령어는 호스트 머신의 파일이나 디렉토리를 도커 이미지의 파일 시스템에 복사함. 이 명령어를 사용하여 애플리케이션 파일, 설정 파일, 기타 필요한 파일을 도커 이미지에 포함시킨다.)
// 도커파일이 프로젝트 루트 디렉토리에 있다고 가정
COPY ./build/libs/<프로젝트명>-<버전>-SNAPSHOT.jar app.jar
2. 깃허브에서 개발용 브랜치와 배포용 브랜치 나누기 (생략해도 됨)
3. 도커 허브 회원가입
4. EC2 인스턴스 ssh 접속
1. Github Actions 생성
1. 깃허브에서 자신의 레포지토리의 Actions로 진입
2. workflow 작성하기 (Java with Gradle 을 선택하거나 set up a workflow yourself 선택 후 진행)
3. yml 파일 이름을 설정하고 아래 스크립트를 넣는다. workflow 이름, 브랜치명, jdk 버전 등은 자신의 환경에 맞춰 수정한다.
# Workflow 이름
name: Spring Boot & AWS CI/CD
on:
# master 브랜치에 push나 pull request 발생 시 workflow 실행
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
# 실행될 작업들
jobs:
build:
# VM의 실행 환경을 최신 우분투로 지정
runs-on: ubuntu-latest
steps:
- name: Checkout
# GitHub 저장소의 소스 코드를 체크아웃
uses: actions/checkout@v4
- name: Set up JDK 17
# JDK 17을 설치하고 설정
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
# `gradlew` 파일에 실행 권한 부여
run: chmod +x gradlew
- name: Build with Gradle
# Gradle을 사용하여 프로젝트를 빌드 (테스트 제외)
run: ./gradlew clean build --exclude-task test
- name: DockerHub Login
# DockerHub에 로그인하여 이미지를 푸시할 수 있도록 인증
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Docker Image Build
# Dockerfile을 사용하여 Docker 이미지를 빌드
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }} .
- name: DockerHub Push
# 빌드한 Docker 이미지를 DockerHub에 푸시
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }}
- name: Application Run
# EC2 인스턴스에 접속하여 Docker 컨테이너를 관리하고 애플리케이션 실행
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_KEY }}
script: |
# 기존에 실행 중인 컨테이너를 중지 및 제거
sudo docker kill ${{ secrets.PROJECT_NAME }}
sudo docker rm -f ${{ secrets.PROJECT_NAME }}
# 기존 Docker 이미지 제거
sudo docker rmi ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }}
# DockerHub에서 최신 이미지를 풀
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }}
# 최신 이미지를 사용하여 새로운 컨테이너 실행
sudo docker run -p ${{ secrets.PORT }}:${{ secrets.PORT }} \
--name ${{ secrets.PROJECT_NAME }} \
-d ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.PROJECT_NAME }}
이 스크립트에서 secret 변수들은 이후에 따로 설정할 예정이다. 일종의 환경변수 등록, 민감한 정보를 노출시키지 않기 위함이다.
4. workflow 작성이 끝났다면 commit을 진행하고 레포지토리에서 yml 파일이 추가되었는지 확인한다.
브랜치를 하나로 설정하여 진행했다면 그 브랜치에 yml파일이 추가됨으로써 Actions가 실행되었을 수 있는데 아직 변수를 등록하지 않아서 실패했을 것이다. 배포용 브랜치가 따로 존재한다면 아직 Actions가 실행이 안되었을 것이다. 어쨋든 빨리 환경 변수를 등록해보자.
5. secret 변수 추가하기 (Settings > Secrets and variables > Actions)
yml 파일에서 사용한 변수 설명은 다음과 같다.
DOCKERHUB_USERNAME : 도커 허브 유저네임
DOCKERHUB_PASSWORD : 도커 허브 패스워드 (필자는 이전에 ec2 접속 후 도커허브에 로그인 할 때 패스워드 대신 토큰을 요구한 기억이 있어서 도커허브에서 받은 토큰을 입력했다. 일단 패스워드로 해보고 문제가 생긴다면 토큰으로 수정해보면 될 것 같다.)
PROJECT_NAME : 프로젝트 이름 (도커 허브에 컨테이너 이름이 이 이름으로 설정된다.)
PORT : 도커를 실행시킬 포트 (ex. 8080)
EC2_HOST : EC2 인스턴스의 퍼블릭 IPv4 주소 (DNS)
EC2_USERNAME : 인스턴스를 생성할 때 os에 따라 Username이 다를 수 있다. (우분투라면 ubuntu, Amazon Linux라면 ec2-user)
EC2_KEY : EC2 인스터스를 생성할 때 사용한 pem 키 (pem 파일 안에 있는 내용을 복사 붙여넣기 하면 된다. -----BEGIN or END RSA PRIVATEKEY----- 문구까지 포함)
6. 변수 세팅이 끝났다면 다시 workflow를 재실행 시켜서 성공하는지 확인한다. 성공했다면 앞으로 개발을 진행하고 main 브랜치로 push 또는 PR을 진행했을 때 자동적으로 배포할 수 있다.