Github Actions를 이용한 CI/CD 구축기
기존 수동 배포 과정
이전의 프로젝트 아키텍처를 보자.
빌드와 배포 모두 수동으로 진행했었다.
테스트 코드도 돌려보고 빌드하고 이미지로 만들어서 EC2에서 구동시키는 방법이였다.
이제 이 과정들을 자동화해보고자 한다.
목표
Github Push -> 테스트 코드 실행 -> Docker 이미지 build, push -> EC2에서 pull -> 이미지 동작
구축
깃허브 리포지토리에 Actions 탭이 있다.
현재 프로젝트는 Gradle로 빌드한다. Configure를 누르자.
.github/workflows 경로에 Actions를 위한 스크립트를 작성해야한다.
필자는 다음과 같이 구축했다.
name: CI/CD
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
services:
mysql:
image: mysql:8.0.33
ports:
- 3306:3306
env:
MYSQL_DATABASE: bucket_list
MYSQL_ROOT_PASSWORD: ${{secrets.MYSQL_ROOT_PASSWORD}}
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- name: Make application.properties
run: |
cd ./src/main/resources
touch ./application.properties
echo "${{secrets.APPLICATION_PROPERTEIS}}" >> ./application.properties
shell: bash
- name: MySQL Init
run: |
sudo mysql -h 127.0.0.1 -P 3306 -uroot -p${{secrets.MYSQL_ROOT_PASSWORD}} < ./init-tables/init-table.sql
- name: Build with Gradle Wrapper
run: ./gradlew build
- name: Login DockerHub
uses: docker/login-action@v1
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_TOKEN}}
- name: Docker Build & Push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{secrets.DOCKERHUB_TAG}}
dependency-submission:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{secrets.AWS_HOST}}
port: 22
key: ${{secrets.AWS_SSH_KEY}}
username: ubuntu
script: |
docker pull ${{secrets.DOCKERHUB_TAG}}
docker stop bucket_list_server
docker rm bucket_list_server
docker image prune -f
docker run -d \
--name bucket_list_server \
-p 8080:8080 \
-e SPRING_DATASOURCE_URL=${{secrets.SPRING_DATASOURCE_URL}} \
-e SPRING_DATASOURCE_PASSWORD=${{secrets.MYSQL_ROOT_PASSWORD}} \
${{secrets.DOCKERHUB_TAG}}
${{secrets.키}}는 중요한 정보는 따로 Key, Value로 관리하여 변환한다. 추가 방법은 나중에~
스크립트에 대한 설명은 생략하고 대략적인 설명 및 동작은 다음과 같다.
- Make application.properties
- 현재 프로젝트의 .gitignore에 application.properties가 추가되어 있다.
- 그래서 프로젝트를 빌드할때 properties 파일을 생성해줄 필요가 있다.
- MySQL Init : 테스트 코드를 동작하기위해 테이블을 생성하고 세팅한다.
- Login DockerHub : 이미지 build, push를 위한 로그인
- Docker Build & Push : 도커 이미지 빌드 & 푸쉬
- Deploy to server : EC2 서버에 접속하여 도커 컨테이너 실행
테이블 세팅을 위한 .sql 파일의 위치는 위와 같다.
CREATE DATABASE IF NOT EXISTS bucket_list;
USE bucket_list;
CREATE TABLE IF NOT EXISTS member (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
login_id VARCHAR(255),
login_pwd VARCHAR(255)
);
위와 같이 테이블 세팅에 필요한 스크립트를 작성해주자.
${{secrets}} 설정
프로젝트의 Settings 탭에 들어가보자.
Actions를 누르고
New repository secret를 누르면
위와 같이 Name은 Key로 Secret는 Value로 사용할 값을 설정할 수 있다.
Name에 Hello를 쓰면 gradle.yml에서 ${{secrets.Hello}}로 값을 사용할 수 있다.
결과
main 브랜치에 push가 발생할 경우
스크립트를 동작하며
Actions 탭에서 Workflow의 결과를 볼 수 있다.
이제 내 리포지토리에 push함으로써 빌드와 테스트, 배포까지 자동화할 수 있다.!!
너무 편하다.