GitHub Actions CI/CD 구현

Yi suho·2023년 9월 28일
0
post-thumbnail

이번 프로젝트에 Docker와 GitHub Action을 사용하여 CI/CD를 구현 해 보았다.

CI/CD 란?

CI/CD는 Continuous Integration(CI) 및 Continuous Delivery(CD)의 약어 이다.

1.Continuous Integration(CI)
CI는 개발자들이 자주 자신의 코드 변경사항을 Git과 같은 중앙 저장소에 통합하는 프로세스를 말한다.각 통합은 자동화된 빌드 및 테스트를 통해 검증되므로,문제점을 조기에 발견하고 수정할 수 있게 된다.
이는 버그를 빠르게 찾아 해결하고,품질을 높이는 데 도움을 준다.

2.Continuous Delivery(CD)
CD는 CI의 자연스러운 연장선상에 있어, 소프트웨어 변경사항을 안전하고 신속하게 프로덕션 환경에 배포하는 프로세스를 의미한다.Continuous Deployment와 헷갈리기 쉬운,Deployment는 자동화된 배포를 의미하고,Delivery는 수동 배포를 포함할 수 있다.

Continuous Delivery (CD) 와 Continuous Deployment (CD) 차이

  • Continuous Delivery (CD)
    CI의 프로세스에 이어서,코드 변경사항을 프로덕션과 같은 환경에 배포 준비 상태로 만드는 것을 말한다.
    그러나 실제로 프로덕션에 자동으로 배포하는 것은 아니다. 마지막 단계는 수동으로 수행될 수 있다.
    즉,필요할때 실제 프로덕션 배포를 클릭 한 번 이나 명령어 한 줄로 할 수 있다.
  • Continuous Deployment (CD)
    Continuous Delivery의 확장 개념으로, 코드 변경사항을 자동으로 프로덕션 환경에 배포하는 것을 말한다. 이 경우,수동 단계 없이 코드가 자동으로 프로덕션에 배포 된다.

따라서 CI/CD라는 용어는 전체적으로 Continuous Intergration 및 Continuous Delivery 또는 Continuous Deployment를 포괄하는 개념으로 사용된다.

이번에 구현한 CI/CD의 CD는 'Continuous Deployment (CD)'에 해당한다.
main 브랜치에 해당 이벤트가 발생하면 Docker에 로그인하여 변경사항이 반영된 이미지를 생성해 Docker Hub에 Push 해주도록 설정해 주었다.
여기서 사용하는 변수들은 Repository secret 변수에 등록해주어야 사용이 가능하다.

name: CI/CD with Node.js and Docker

on:
  push:
    branches:
      - main # 원하는 브랜치로 변경 가능

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          token: ${{ secrets.GH_DOTCOM_TOKEN }}
          node-version: '18' # 사용할 Node.js 버전을 선택합니다

      - name: Cache yarn dependencies
        uses: actions/cache@v2
        with:
          path: .yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install dependencies
        run: yarn install --immutable --immutable-cache --check-cache

      - name: Build Node.js app
        run: yarn run build

      - name: Build Docker image
        run: docker buildx build .

      - name: Log in to Docker Hub
        run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest

  deploy:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - name: SSH connect to production server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          script: |
            cd project_dir
            docker-compose down 
            docker-compose pull 
            docker-compose up --force-recreate --build -d

builld 작업

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          token: ${{ secrets.GH_DOTCOM_TOKEN }}
          node-version: '18' # 사용할 Node.js 버전을 선택합니다

      - name: Cache yarn dependencies
        uses: actions/cache@v2
        with:
          path: .yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install dependencies
        run: yarn install --immutable --immutable-cache --check-cache

      - name: Build Node.js app
        run: yarn run build

      - name: Build Docker image
        run: docker buildx build .

      - name: Log in to Docker Hub
        run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKER_IMAGE_NAME }}:latest
  • Checkout repository : 현재 저장소의 코드를 GitHub runner 환경에서 가져온다.
  • Set up Node.js : Node.js 를 설정하며,v18을 사용하도록 지정.(각자 사용할 버전을 선택하여 적어주면 된다.)
  • Cache yarn dependencies : 의존성들을 캐싱하여 빌드 속도를 향상시키는데 도움을 준다.
    이 후의 실행에서 변경되지 않은 의존서들은 캐시에서 빠르게 가져올 수 있다.
  • Install dependencies : 프로젝트의 의존성들을 'yarn'을 사용하여 설치.
  • Build Node.js app : Node.js 어플리케이션을 빌드한다.
  • Build Docker image : Docker 이미지를 빌드한다. 이 이미지는 어플리케이션과 그 의존성들을 포함 한다.
  • Log in to Docker Hub:Docker Hub에 로그인 한 후 이미지를 Docker Hub에 푸시할 준비를 한다.
  • Build and push : 빌드된 Docker 이미지를 Docker Hub에 푸시한다. 이렇게 함으로써 다른 서버나 환경에서 이미지를 가져와 사용할 수 있게 된다.

deploy 작업

deploy:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - name: SSH connect to production server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }} 
          username: ${{ secrets.USERNAME }} 
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          script: |
            cd project_dir
            docker-compose down 
            docker-compose pull 
            docker-compose up --force-recreate --build -d
  • needs:build :'build'작업이 성공적으로 완료된 후에만 시작된다. (needs:build를 통해 의존성이 지정된다.)
  • SSH connect to production server : SSH를 사용하여 프로덕션 서버에 접속한다.
  • script: 서버에서 다음의 작업을 순차적으로 수행한다.
    1.디렉토리로 이동
    2.현재 동작 중인 Docker Compose 서비스를 중단한다.
    3.최신 Docker Image를 Docker Hub에서 가져온다.
    4.가져온 최신 이미지를 기반으로 Docker compose 서비스를 재시작한다.
  • ${{ secrets.HOST }}:배포 대상 서버의 호스트명 또는 IP 주소.
    ex) example.com 또는 192.168.1.100
  • ${{ secrets.USERNAME }}:SSH 접속을 위한 사용자 이름.
    ex)root, ubuntu, deployer 등.
  • ${{ secrets.SSH_PRIVATE_KEY }}:SSH접속을 위한 개인 키.해당 키는 대상 서버에 등록된 공개 키와 쌍을 이룬다.GitHub secrets에는 개인 키의 전체 내용을 입력해야 한다.
  • ${{ secrets.PASSWORD }}:일부 SSH 접속 방식에서 사용자 암호를 요구할 수 있다. 하지만 대부분의 경우,키 기반 인증을 사용하여 패스워드 없이 접속 한다. 이 경우 해당 값은 필요 없을 수 있다.
  • ${{ secrets.PORT }}: SSH 서버가 리스닝하고 있는 포트 번호.기본적으로 SSH는 22번 포트를 사용한다. 하지만 보안 상의 이유나 기타 다른 이유로 변경된 경우 해당 포트 번호를 입력한다.

secret 변수 설정

yml에서 사용한 secret 변수 설정
Repository의 Settings ->security ->secrets -> actions 탭에 들어가 New repository secret 눌러 변수를 추가 할 수 있다.

0개의 댓글