CICD

GitHub Action & Docker를 사용해서 배포

웅둘 2023. 9. 8. 23:15

프로젝트를 진행하면서 소스 코드의 변경사항이 발생하면 새롭게 배포를 해야합니다.

이때는 수동으로 배포를 진행해서 매번 빌드 후 jar 파일을 서버에 올려서 배포를 했었습니다.

매번 수동으로 배포할 수 없었기 때문에 자동으로 빌드 및 배포되도록 하기 위해서 CI/CD를 적용하기로 했다.

 

이러한 CI/CD를 위한 툴은 대표적으로 Jenkins가 있지만 Jenkins는 회사에서 사용중이였고 다른 CI/CD를 사용해보고 싶었고 간단하게 하기 위해서 Github Action을 선택하게 되었다.

 

간단하게 Github Action에 대해 알아보고 적용해보자

GitHub Action 이란?

  • GitHub에서 제공하는 CI(지속 통합), CD(지속 배포) 플랫폼이다.

Workflow

  • 작업의 흐름으로 특정한 목적을 위한 실행 트리거, 환경, 기능들을 모두 포함하는 파일입니다.
  • 레퍼지토리내의 github/workflows 폴더 아래 YAML 파일로 작성

Job

  • Job은 독립된 환경에서 돌아가는 하나의 처리 단위
  • 모든 작업은 기본적으로 동시에 실행되며 필요 시 작업 간에 의존 관계를 설정하여 실행순서를 제어할 수 있다.
  • 필수적으로 정의해야 할 속성 runs-on → Job을 실행할 환경(윈도우, 리눅스) 정의

Steps

  • Job 내에서 실행되는 개별적인 작업 단위
  • 스크립트, 명령어 또는 외부 액션을 실행하여 특정 작업을 수행합니다.

Actions

  • uses로 action 사용
  • 재사용 가능한 코드 단위, 특정 작업을 수행하는 명령어 또는 스크립트
  • GitHub Marketplace에서 다양한 액션을 제공해줍니다.

 

프로젝트에서 사용

name: Java CI with Gradle

on:
  push:
    branches: [ "main" ]
    
permissions:
  contents: read
  
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'adopt'
        
    - name: Build with Gradle
      run: |
        chmod +x gradlew
        ./gradlew bootJar
        
      ## 웹 이미지 빌드 및 도커허브에 push
    - name: web docker build and push
      run: |
        sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
        sudo docker build -f Dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/omo-be .
        sudo docker push ${{ secrets.DOCKERHUB_USERNAME }}/omo-be
        
    - name: Deploy Front to prod
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.AWS_HOST }}
        username: ${{ secrets.AWS_USERNAME }}
        password: ${{ secrets.AWS_PASSWORD }}
        port: 22
        script: |
          if docker ps -a --format '{{.ID}}' | grep -q .; then
            sudo docker rm -f $(docker ps -qa)
          else
            echo "No Docker containers to remove."
          fi        
          sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/omo-be
          sudo docker run --name omo-be -d -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/omo-be 
          sudo docker run --name redis-server -d -p 6379:6379 redis
          docker image prune -f

 

on:
  push:
    branches: [ "main" ]
  • main bracnh에 push할 때 Workflow 작동

 

permissions:
  contents: read
  • Workflow 실행 환경에서 권한

 

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'adopt'
  • ubuntu 환경 사용
  • action/checkout@v3 : Github 저장소의 코드를 워크플로우 실행 환경으로 체크아웃하여 가져옵니다.
  • actions/setup-java@v3 : Workflow 실행 환경에 JDK 17 설정

 

- name: Build with Gradle
  run: |
    chmod +x gradlew
    ./gradlew bootJar
  • gradlew 실행 권한을 부여하고 프로젝트 빌드

 

- name: web docker build and push
  run: |
    sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
    sudo docker build -f Dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/omo-be .
    sudo docker push ${{ secrets.DOCKERHUB_USERNAME }}/omo-be
  • 웹 이미지 빌드 및 도커허브에 푸시
  • 도커 허브에 로그인, Dockerfile을 사용하여 이미지 빌드 → 도커 허브 push
  • 이때 도커허브에 레퍼지토리를 만들어야 한다. 현재 예시에는 omo-be로 되어있다.

 

uses: appleboy/ssh-action@master
with:
  host: ${{ secrets.AWS_HOST }}
  username: ${{ secrets.AWS_USERNAME }}
  password: ${{ secrets.AWS_PASSWORD }}
  port: 22
  script: |
    if docker ps -a --format '{{.ID}}' | grep -q .; then
      sudo docker rm -f $(docker ps -qa)
    else
      echo "No Docker containers to remove."
    fi        
    sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/omo-be
    sudo docker run --name omo-be -d -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/omo-be 
    sudo docker run --name redis-server -d -p 6379:6379 redis
    docker image prune -f
  • appleboy/ssh-action@master : AWS 호스트로 SSH 연결 수립
  • host : ssh 접속을 위한 ip 
  • username : ssh 접속을 위한 username
  • passwrod : Private Key

script

  • 실행 중인 도커 컨테이너 모두 종료
  • 도커 허브에서 이미지를 가져오고 컨테이너 실행
  • Redis 서버 컨테이너 실행
  • 불필요한 이미지 정리

 

Github Action으로 배포가 성공했지만 한번 배포하는데 3분이 넘게 걸린다...

 

 

도커 허브에 이미지를 만들고 올리는 작업이 오래걸리는 것 같아 도커를 사용하지 않는 방법으로 Github Action을 진행하기로 했다. -> 다음 블로그 글 작성