먼저 CI/CD가 무엇인지 모른다면 간단하게 알아보는 CI/CD를 참고바란다.
많은 프로젝트에서 Jenkins 또는 github action 등을 사용하지만 이번 프로젝트에 적용한 CI/CD 툴은 github action이다.
github action을 적용하게 된 배경은 다음과 같다.
1. CI/CD를 위한 툴을 다운받을 필요 없이 github과 동일한 환경에서 사용 가능
2. yml 파일로 손쉽게 파이프라인 구성 가능
즉, 처음 CI/CD를 접하는 개발자의 입장에서 좀 더 다가가기 쉬운 툴이라고 생각되어 선정했다.
프로젝트 내에 .github/workflows 폴더를 생성 후 .yml 파일을 생성한다.
(github에서 여러 개발자들이 공유하는 기본 템플릿들도 활용 가능)
이번 프로젝트에서 작성한 .yml은 아래와 같다. (환경에 맞는 step 구성이 필요)
해당 파일을 작성한 후 원격 repo의 해당하는 브랜치로 push / pull request 한다면 workflow가 자동적으로 실행된다.
# workflow 이름
name: OWLS CI-CD
# workflow가 작동할 trigger 설정 ( dev 브랜치에 push, pull_request가 발생할 때 작동)
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
#job은 여러 단계의 step으로 구성, 가상 환경의 인스턴스에서 실행
jobs:
# CI를 위한 workflow
build:
# OS 환경 설정
runs-on: ubuntu-latest
steps:
# uses는 어떠한 액션을 할지 설정(기존에 만들어진 액션을 적용할 때 사용)
- name: Checkout
uses: actions/checkout@v3
# .env 파일 업로드 없이 환경 변수 설정 (github repo 내에서 등록 가능하며 secrets로 불러옴)
- name: Generate Environment Variables File
run: |
echo "DATABASE_URL = $DATABASE_URL" >> .env
echo "KAKAO_CLIENT_ID = $KAKAO_CLIENT_ID" >> .env
echo "KAKAO_CLIENT_SECRET = $KAKAO_CLIENT_SECRET" >> .env
echo "KAKAO_CALLBACK_URL = $KAKAO_CALLBACK_URL" >> .env
echo "GOOGLE_CLIENT_ID = $GOOGLE_CLIENT_ID" >> .env
echo "GOOGLE_SECRET = $GOOGLE_SECRET" >> .env
echo "GOOGLE_CALLBACK_URL = $GOOGLE_CALLBACK_URL" >> .env
echo "ACCESS_TOKEN_SECRET = $ACCESS_TOKEN_SECRET" >> .env
echo "REFRESH_TOKEN_SECRET = $REFRESH_TOKEN_SECRET" >> .env
echo "AWS_REGION = $AWS_REGION" >> .env
echo "BUCKET_NAME = $BUCKET_NAME" >> .env
echo "AWS_ACCESSKEY = $AWS_ACCESSKEY" >> .env
echo "AWS_SECRETKEY = $AWS_SECRETKEY" >> .env
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }}
KAKAO_CLIENT_SECRET: ${{ secrets.KAKAO_CLIENT_SECRET }}
KAKAO_CALLBACK_URL: ${{ secrets.KAKAO_CALLBACK_URL }}
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
GOOGLE_SECRET: ${{ secrets.GOOGLE_SECRET }}
GOOGLE_CALLBACK_URL: ${{ secrets.GOOGLE_CALLBACK_URL }}
ACCESS_TOKEN_SECRET: ${{ secrets.ACCESS_TOKEN_SECRET }}
REFRESH_TOKEN_SECRET: ${{ secrets.REFRESH_TOKEN_SECRET }}
AWS_REGION: ${{ secrets.AWS_REGION }}
BUCKET_NAME: ${{ secrets.BUCKET_NAME }}
AWS_ACCESSKEY: ${{ secrets.AWS_ACCESSKEY }}
AWS_SECRETKEY: ${{ secrets.AWS_SECRETKEY }}
# 멀티 플랫폼 이미지를 빌드하기 위해 필요한 Buildx를 설치
- name: Set up docker buildx
uses: docker/setup-buildx-action@v2
# docker hub 연결
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
# docker image를 build하고 container Registry에 push
- name: Build and Push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest
# CD를 위한 workflow
deploy:
# CI가 성공적으로 완료되어야 CD workflow 실행
needs: build
runs-on: ubuntu-latest
steps:
# 서버 원격 접속 및 배포
- name: ssh connect & production
uses: appleboy/ssh-action@master
# 서버 원격 접속을 위한 환경변수
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
port: ${{ secrets.PORT }}
# 원격 접속 성공 이후 배포를 위한 CLI
script: |
cd server
docker login -u &{{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
docker stop $(docker ps -aq)
docker system prune -a --volumes -f
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/{{ secrets.DOCKERHUB_IMAGE_NAME }}
docker-compose up -d
docker image prune -f
이러한 코드를 작성하기까지 몇가지 가벼운 이슈(오타, 환경변수 설정 등)들이 발생하기는 했지만 github repo에서 actions 탭을 활용하면 어떤 문제로 인해 제대로 CI/CD가 이루어지지 않았는지 로그를 찍어주기 때문에 이를 참고한다면 쉽게 해결할 수 있다.
이외에도 각 step들이 어떻게 실행되었는지 자세히 살펴볼 수도 있다.
적용 전에는 막연한 두려움같은 것들이 있었지만 막상 적용을 해보니 생각한 것만큼 어렵지 않게 적용에 성공할 수 있었던 것 같다.
적용 이후에 몇번 push를 해서 CI/CD가 정상 작동하는 것을 보면 매우 편하기도 하고 여러 작업 시간들을 단축할 수 있는게 가장 큰 장점으로 보인다.
당연히 지금 작성한 workflow는 기본적인 것(?)이기에 다음에는 더 깊은 공부를 통해 고도화하여 지금보다 깔끔하고 정돈된 workflow 작성해야할 것이다.