촬리의늘솔길

CI/CD - 프로젝트에 적용하기 - github Actions&NCP&GHCR 사용 본문

✍️2023/Cloud

CI/CD - 프로젝트에 적용하기 - github Actions&NCP&GHCR 사용

리촬리 2023. 9. 15. 23:25

프론트 CI/CD

Dockerfile - front

FROM node:18.16-alpine
WORKDIR /app/frontend

COPY package*.json ./
RUN yarn install

COPY . .

EXPOSE 3000
CMD ["npm", "start"]

CICD -front

name: Build and Deploy Docker Image

on:
  push:
    branches:
      - main
      - develop

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18]

    name: Node ${{ matrix.node-version }} sample
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: yarn install

      #ESLint 경고 무시
      - name: Build
        run: npm run build -- --no-verify

      # Docker 빌드 생성 및 푸시
      - name: dev Docker build & push
        if: contains(github.ref, 'main') || contains(github.ref, 'develop')
        run: |
          echo ${{ secrets.SONG_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker build -f Dockerfile -t ghcr.io/whatever-mentoring/whatssue-fe/whatssue:1.0 .
          docker push ghcr.io/whatever-mentoring/whatssue-fe/whatssue:1.0

      # 개발서버 SSH접속 및 배포
      - name: Deploy
        uses: appleboy/ssh-action@master
        if: contains(github.ref, 'main') || contains(github.ref, 'develop')
        with:
          host: ${{ secrets.NCP_DEV_SERVER_IP }}
          username: ${{ secrets.NCP_DEV_SERVER_USER }}
          password: ${{ secrets.NCP_DEV_SERVER_PASSWORD }}
          port: ${{ secrets.NCP_DEV_SERVER_SSH_PORT }}
          script: |
            echo "${{ secrets.SONG_TOKEN }}" | sudo docker login ghcr.io -u ${{ github.actor }} --password-stdin
            if [ "$(docker ps -aq -f name=whatssue-fe)" ]; then
                  sudo docker stop whatssue-fe
                  sudo docker rm whatssue-fe
            fi
              # 이전 이미지를 제거합니다.
              if [ "$(docker images -q ghcr.io/whatever-mentoring/whatssue-fe/whatssue)" ]; then
                sudo docker rmi ghcr.io/whatever-mentoring/whatssue-fe/whatssue
              fi

            sudo docker pull ghcr.io/whatever-mentoring/whatssue-fe/whatssue:1.0
            sudo docker run -d -p 3000:3000 --name whatssue-fe ghcr.io/whatever-mentoring/whatssue-fe/whatssue:1.0
            sudo docker image prune -f

docker ps -aq -f name=whatssue-fe

: 컨테이너의 name 이 whatssue-fe 인것만 찾아서 stop

(백엔드도 마찬가지)

이미지 제거

현재 이미지 태그가 다 똑같아서

중복된 이미지가 업로드 될 경우, 누적된다.(이전에 이미 있던것의 태그는 none으로 바뀜)

때문에 리소스 낭비가 심해서 이미지 이름으로 검색하여 제거해준다.

(추후 동적 이미지 태그 부여)

              # 이전 이미지를 제거합니다.
              if [ "$(docker images -q ghcr.io/whatever-mentoring/whatssue-fe/whatssue)" ]; then
                sudo docker rmi ghcr.io/whatever-mentoring/whatssue-fe/whatssue
              fi

ESlint

프론트 코드 문법이나 안쓰이는 코드를 검토해주는 ESlint..

오류가 뜨는것같아 --no-verify 옵션을 이용하여 일단 무시해주기로했다.

(근데 잘 무시 되는것 같지는 않음)

      #ESLint 경고 무시
      - name: Build
        run: npm run build -- --no-verify

참고

[React] Github Actions로 CI/CD 적용하기

CI/CD pipelines using React, GitHub Actions, and Heroku - LogRocket Blog

Setting up a CI/CD workflow on GitHub Actions for a React App (with GitHub Pages and Codecov)_github_weixin_0010034-CI/CD

How to Set Up Codecov with C and GitHub Actions in 2022

Treating warnings as errors because process.env.CI = true | bobbyhadz

[Git/Github] Github Actions를 이용한 Workflow 자동화와 CI/CD 파이프라인 구축하기 / eslint 적용하기 , "module is not defined" 에러 해결 과정


프로젝트 세팅 - Git Action CI / CD

백엔드 CI/CD 완료

(CI 는 나중에 lint 넣어서 해봐야징..)

Dockerfile - back

# Base image
FROM openjdk:17-jdk

# Set working directory
WORKDIR /app

# Copy the JAR file from the build output directory to the container
COPY build/libs/*.jar Whatssue.jar

# Expose port (if your Spring Boot application uses a different port, update it here)
EXPOSE 8090

# Command to run the Spring Boot application when the container starts
CMD ["java", "-jar", "Whatssue.jar"]

cd yaml 파일

# 작업명
name: CD NCP

# 실행해야 할 브랜치, push가 발생한 경우로만 한정하였다.
on:
  push:
    branches:
      - 'develop'
      - 'main'
  pull_request:
    branches:
      - "develop"
      - "main"

jobs:
  CD:
    ## 이거 NCP ubuntu OS 가 아니라, github Actions job 실행 환경의 ubuntu OS버전이다.
    runs-on: ubuntu-latest
    env:
      RESOURCE_PATH: ./src/main/resources/application.yml
    steps:
      ## Project JDK 17 Setting
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set yml file
        uses: microsoft/variable-substitution@v1
        with:
          files: ${{ env.RESOURCE_PATH }}
        env:
          spring.datasource.url: ${{ secrets.DB_HOST }}
          spring.datasource.username: ${{ secrets.DB_USERNAME }}
          spring.datasource.password: ${{ secrets.DB_PASSWORD }}

      # Gradle의 사용권한 셋팅
      - name: Grant Execute permission for gradlew
        run: chmod +x gradlew
        shell: bash

      # 프로젝트 테스트 진행없이 빌드
      - name: Build with Gradle
        run: ./gradlew build -x test
        shell: bash

      # Docker 빌드 생성 및 푸시
      - name: dev Docker build & push
        if: contains(github.ref, 'main') || contains(github.ref, 'develop')
        run: |
          echo ${{ secrets.SONG_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
          docker build -f Dockerfile -t ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0 .
          docker push ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0

      # 개발서버 SSH접속 및 배포
      - name: Deploy
        uses: appleboy/ssh-action@master
        id: deploy
        if: contains(github.ref, 'main') || contains(github.ref, 'develop')
        with:
          host: ${{ secrets.NCP_DEV_SERVER_IP }}
          username: ${{ secrets.NCP_DEV_SERVER_USER }}
          password: ${{ secrets.NCP_DEV_SERVER_PASSWORD }}
          port: ${{ secrets.NCP_DEV_SERVER_SSH_PORT }}
          script: |
            echo "${{ secrets.SONG_TOKEN }}" | sudo docker login ghcr.io -u ${{ github.actor }} --password-stdin
            if [ "$(docker ps -aq)" ]; then
            sudo docker rm -f $(docker ps -aq)
            fi
            sudo docker pull ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0
            sudo docker run -d -p 8090:8090 --name whatssue ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0
            sudo docker image prune -f

잘 되는것 같음

컨테이너가 멈춘 이유는 그냥 프로젝트 동작상의 오류로인한 멈춤 이슈인것 같고

컨테이너도 잘 돌아가는것 같음

근데 백그라운드 설정이라서 추후에는 stop 을 해줘야만 함

관련 명령어

ubuntu docker 설치

도커 이미지 빌드 및 푸쉬

(컨테이너 레지스트리를 github 으로 해둬서 ghcr.io로그인이 필요)

docker login [ghcr.io](<http://ghcr.io>)

docker build -t [ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0](<http://ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0>) .

docker push [ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0](<http://ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0>)

도커 이미지가 있는지 확인 명령어

docker images

도커 컨테이너가 떠있는지 확인하는 명령어

docker ps

도커 컨테이너 중지 명령어

docker stop \[options\] container \[container...\]

그냥 docker stop 컨테이너 ID 하면됨

도커 컨테이너 run 명령어

docker run -d -p 8090:8090 ghcr.io/whatever-mentoring/whatssue-be/whatssue:1.0

여기서 -d 옵션은 로그를 보지 않고 백그라운드로 돌리는 것을 의미함

로그를 보고 싶다면 -d 옵션만 빼면 됨.

도커 이미지 삭제 명령어

docker rmi 이미지 ID

강제 삭제

docker rmi -f 이미지ID

만약 'docker stop' 명령으로 컨테이너가 종료되지 않으면 'docker kill' 명령을 사용하여 강제로 종료할 수도 있습니다.

env 관련리소스

env파일 .gitignore로 안보이게 만들기

완성

이미지 올라갈때마다 자동으로 이전버전 지워지고

컨테이너도 재 실행됨 (따지고보면 그냥 이전꺼 지우고 새거 돌리는거)

추후 이미지 버전 자동 버전업 해서 올리는거 구현필요

728x90