Git action과 docker hub을 이용한 Continuous Integration

2024. 4. 11. 13:59Software Engineering

1. 개요

전체적인 CI/CD 작업과정을 설명하고 이 포스트에서는 CI 작업을 진행하고자 한다. 이 글은 스프링 백엔드 서버를 기준을 설명한다.

2. 설계한 CI/CD 과정

  1. 유저가 브랜치에 변경사항을 push함에 따라 git action이 실행된다.
  2. git action이 CI 과정을 진행한다.
    1. Docker image 빌드
    2. Docker hub에 빌드한 image push
  3. CI action이 종료됨에 따라 자동으로 git action이 CD 과정을 호출하여 진행한다.
    1. Portainer에서 컨테이너 별로 제공하는 webhook을 post 메소드로 호출한다.
  4. Portainer는 docker hub에서 새로운 이미지를 요청하여
  5. ec2에 이미지를 빌드할 수 있게 해준다.

3. Dockerfile

Spring 이 빌드 된 이미지를 Docker hub에 올려야 하기 때문에 Dockerfile이 실행될 때 Spring 프로젝트를 build하여 jar 파일로 만든 이후 실행까지 시켜줘야 한다.

FROM bellsoft/liberica-openjdk-debian:21 AS builder
ENV WORK /workspace
COPY build.gradle settings.gradle gradlew $WORK/
COPY gradle $WORK/gradle
COPY ./src $WORK/src

WORKDIR $WORK

RUN apt-get update && apt-get install -y dos2unix && dos2unix gradlew
RUN chmod +x gradlew
RUN ./gradlew clean bootJar --parallel --no-daemon

FROM bellsoft/liberica-openjdk-debian:21

ARG JAR_FILE=workspace/build/libs/*.jar
COPY --from=builder $JAR_FILE app.jar

ENTRYPOINT ["java", \
            "-Xms1400m", \
            "-Xmx1400m", \
            "-jar", \
            "-Dspring.profiles.active=prod", \
            "/app.jar"]
  • 스프링 프로젝트는 jdk 21를 이용했기 때문에 jdk 21 이미지를 빌더로 사용했다.
  • dos2unix : 텍스트 파일 내에 포함된 줄 구분자를 Linux 기준으로 변경한다. (CRLF -> LF)
  • ENTRYPOINT
    • Xms / Xmx : Java 힙의 최초 크기 지정
    • -Dspring.profiles.active : application.yml 설정 정보 파일을 application-prod.yml 을 기준으로 build 한다.

4. Git Action에서 Continuous Integration 을 위한 yml 파일 작성

name: be-docker-buildx-ci

on:
  push:
    branches:
      - 'main'
    paths:
      - 'chatty-be/**'

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      -
        name: Assume IAM role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}
      -
        name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_SECRET_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          context: ./chatty-be
          tags: leahpar0401/wequiz-be:latest
          platforms: linux/arm64
  • path
    • git repository 내부에 FE, BE, ML 을 모두 두었기 때문에 특정 폴더에 푸쉬가 되었을 때 실행시킨다.
  • QEMU / Buildx
    • docker 에서 제공하는 buildx 명령어를 통해 ARM / AMD 플랫폼에 관계 없이 멀티 플랫폼에서 이미지를 빌드 할 수 있게 한다. 내부적으로 QEMU 라는 하드웨어 가상화 에뮬레이터가 작동한다.
  • AWS IAM 권한 부여
    • 진행하고 있는 프로젝트에서 환경변수 파일들을 AWS Secret Manager에서 관리하기로 했다. 이에 Docker 에서 빌드할 때 접근할 수 있는 권한을 주기 위해 설정해주었다.
  • Docker hub
    • 당연하게도, Docker hub에 미리 계정을 만들어 두어야 한다. 우리가 만든 이미지가 Docker hub의 본인 레포지토리에 저장되기 때문이다. 아래 tags에 레포지터리명을 넣어두었는데 레포지토리 또한 미리 만들어두어야 한다.
    • platforms 명령어를 통해 ARM / AMD 플랫폼 모두 빌드할 수 있다. 둘 다 넣으면 두 가지 모두 빌드가 된다. 다만, 우리는 ARM 기반 ec2 한대만 가용하기로 했기 때문에 굳이 AMD 플랫폼을 추가하지는 않았다.

5. 테스트

CI 과정을 진행하기 위한 준비가 끝났다. main에 변경사항을 주어 푸쉬해보자.

잘 실행이 되었다면 action 탭에서 아래 사진과 같이 확인할 수 있을 것이다. 또한 Docker hub에도 이미지가 잘 올라갔는지 확인하자.

linux/arm64 기반으로 이미지가 생성되어 docker hub 에 잘 올라간 것을 확인할 수 있다. 여기까지 잘 되었다면 CI 과정까지 끝이 난 것이다. 다음 포스트는 CD를 진행하기 위한 설정을 하고자 한다.