Skip to content

jar 파일을 도커로 배포하는 Github Actions 스크립트 작성하기

amaranth edited this page Aug 3, 2023 · 2 revisions

*도커로 spring jar을 실행하는 방식

배포 스크립트 전문

name: Kerdy Backend Prod Server CI/CD

on:
  workflow_dispatch:

jobs:
  build:
    name: 빌드
    runs-on: ubuntu-22.04
    defaults:
      run:
        working-directory: backend/emm-sale
    services:
      mysql:
        image: mysql:8.0.28
        env:
          MYSQL_USER: user
          MYSQL_PASSWORD: password
          MYSQL_ROOT_PASSWORD: 1234
          MYSQL_DATABASE: kerdy
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      - name: workflow_dispatch에서 지정한 branch로 checkout
        uses: actions/checkout@v3
        with:
          token: ${{ secrets.SUBMODULE_TOKEN }}
          submodules: true
      
      - name: JDK 11로 설정
        uses: actions/setup-java@v3
        with:
          java-version: 11
          distribution: 'corretto'

      - name: Gradle에 실행 권한 부여
        run: chmod +x gradlew
      
      - name: Actions/Caches에 Gradle 라이브러리 캐싱
        id: cache-gradle
        uses: actions/cache@v3
        with:
          path: ~/.gradle/caches
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
          restore-keys: ${{ runner.os }}-gradle-
      # RestDocs의 index.html 업데이트 반영을 위해 2번 build하도록 함
      - name: gradle 빌드
        run: ./gradlew build && ./gradlew build
      
      - name: 도커 빌더 생성 및 부팅
        uses: docker/setup-buildx-action@v2

      - name: 도커 허브에 로그인
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: 도커 이미지 빌드 및 푸시
        uses: docker/build-push-action@v4
        with:
          context: backend/emm-sale
          file: backend/emm-sale/Dockerfile-prod
          platforms: linux/arm64/v8
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/kerdy:latest

  deploy:
    needs: build
    name: 배포
    runs-on: [ self-hosted, label-prod ]
    steps:
      - name: 도커 실행
        run: |
          docker stop kerdy && docker rm kerdy && docker rmi ${{ secrets.DOCKERHUB_USERNAME }}/kerdy
          docker run -d -p 8080:8080 --name kerdy ${{ secrets.DOCKERHUB_USERNAME }}/kerdy
      - name: 슬랙 메시지 보내기
        uses: 8398a7/action-slack@v3
        with:
          mention: 'here'
          if_mention: failure
          status: ${{ job.status }}
          fields: workflow,job,commit,message,ref,author,took
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        if: always()

Github Actions yml 파일 해석


기본 설정

name: Kerdy Backend Prod Server CI/CD    # (1)

on:
  workflow_dispatch:    # (2)
  1. 워크 플로우 명칭 설정

    워크플로우 목록에서 표시되는 이름이다.

  2. Actions 탭에서 워크플로우를 수동으로 실행할 수 있도록 설정

build 작업

  • job 관련 설정

    jobs:
      build:
        name: 빌드
        runs-on: ubuntu-22.04    # (1)
        defaults:
          run:
            working-directory: backend/emm-sale    # (2)
        services:
          mysql:    # (3)
            image: mysql:8.0.28
            env:
              MYSQL_USER: user
              MYSQL_PASSWORD: password
              MYSQL_ROOT_PASSWORD: 1234
              MYSQL_DATABASE: kerdy
            ports:
              - 3306:3306
            options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3    # (4)
    1. job 실행 환경을 Github 클라우드 서버로 설정(ubuntu-22.04 환경)
    2. 작업을 실행할 기준 디렉토리 경로를 backend/emm-sale로 설정
    3. 빌드 테스트를 위한 MySQL 환경을 설정
    4. mysql이 제대로 동작하는지 확인하기 위한 커맨드
  • 프로젝트 빌드 & jar 파일 생성

       steps:
          - name: workflow_dispatch에서 지정한 branch로 checkout
            uses: actions/checkout@v3    # (1)
            with:
              token: ${{ secrets.SUBMODULE_TOKEN }}    # (2)
              submodules: true    # (3)
          
          - name: JDK 11로 설정
            uses: actions/setup-java@v3
            with:
              java-version: 11
              distribution: 'corretto'
    
          - name: Gradle에 실행 권한 부여
            run: chmod +x gradlew
          
          - name: Actions/Caches에 Gradle 라이브러리 캐싱
            id: cache-gradle
            uses: actions/cache@v3
            with:
              path: ~/.gradle/caches
              key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
              restore-keys: ${{ runner.os }}-gradle-
          # RestDocs의 index.html 업데이트 반영을 위해 2번 build하도록 함
          - name: gradle 빌드
            run: ./gradlew build && ./gradlew build
    1. workflow_dispatch에서 지정해준 브랜치로 체크아웃한다.

    2. 서브 모듈을 사용하기 위한 액세스 토큰

    3. 서브 모듈 사용 여부

      서브 모듈 문서화 참조

    …(그 외는 이전 스크립트와 동일하기 때문에 생략)

  • dockerfile을 사용해 docker 이미지를 빌드한 뒤 DockerHub로 푸시

          - name: 도커 빌더 생성 및 부팅    # (1)
            uses: docker/setup-buildx-action@v2
    
          - name: 도커 허브에 로그인    # (2)
            uses: docker/login-action@v2
            with:
              username: ${{ secrets.DOCKERHUB_USERNAME }}
              password: ${{ secrets.DOCKERHUB_TOKEN }}
    
          - name: 도커 이미지 빌드 및 푸시    # (3)
            uses: docker/build-push-action@v4
            with:
              context: backend/emm-sale    # (3-1)
              file: backend/emm-sale/Dockerfile-prod    # (3-2)
              platforms: /linux/arm64/v8    # (3-3)
              push: true    # (3-4)
              tags: ${{ secrets.DOCKERHUB_USERNAME }}/kerdy:latest    # (3-5)
    1. 도커 빌더를 생성하고 부팅한다.

    2. DockerHub 계정의 유저명과 Access Token을 Github Actions Secret으로 등록하고, 해당 데이터를 사용해 도커 허브에 로그인한다.

    3. 도커 이미지를 빌드한다.

      3-1. 특정 경로에 위치한 파일(build’s context)

      3-2. 빌드 시 사용할 Dockerfile의 위치 지정

      • Dockerfile-prod

        FROM openjdk:11 as build
        ARG JAR_FILE=build/libs/*.jar
        COPY ${JAR_FILE} kerdy.jar
        ENTRYPOINT ["java","-Dspring.profiles.active=prod","-jar","/kerdy.jar"]
        

      3-3. docker image의 실행 환경을 설정하는 옵션으로, 도커 호스트(우리의 배포 서버)의 운영체제와 맞춰주어야 한다.

      3-4. 빌드 후 이미지를 Docker Hub repository에 push한다는 뜻.

      3-5. 이미지의 태그를 정의한다.(유저명/레포명:버전)

deploy 작업

  • 도커 컨테이너 실행

    deploy:
        needs: build    # (1)
        name: deploy
        runs-on: [ self-hosted, label-prod ]    # (2)
        steps:
          - name: 도커 실행
            run: |    # (3)
                docker stop kerdy && docker rm kerdy && docker rmi ${{ secrets.DOCKERHUB_USERNAME }}/kerdy
                docker run -d -p 8080:8080 --name kerdy ${{ secrets.DOCKERHUB_USERNAME }}/kerdy
    1. build 작업이 선행된 후 해당 job(deploy)을 실행한다는 의미이다.

    2. self-hosted, label-prod 라벨을 가진 러너에서 작업을 수행한다는 의미이다.

      image

    3. 도커 실행 중지 및 컨테이너 삭제 후 컨테이너 실행

      💡 풀받은 이미지가 없을 때 컨테이너를 실행시키면 자동으로 풀이 받아와진다.

      💡 유저 그룹에 docker 권한이 있기 때문에 sudo 없이도 실행할 수 있다.

  • 워크플로우 실행 결과를 슬랙으로 전송

          - name: 슬랙 메시지 보내기
            uses: 8398a7/action-slack@v3
            with:
              mention: 'here'
              if_mention: failure
              status: ${{ job.status }}
              fields: workflow,job,commit,message,ref,author,took
            env:
              SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
            if: always()
Clone this wiki locally