프로필사진
[CI/CD적용기3] 프로젝트 build - 로컬 vs Dockerfile vs Github Actions

2023. 9. 7. 23:04🔴 ETC/CICD

300x250

Github Actions를 사용하기 앞서 세팅해줘야하는 내용은 이전 포스트 참고

2023.09.07 - [🔴 ETC/CICD] - [CI/CD적용기2] Docker + Github Actions으로 배포 자동화

 

[CI/CD적용기2] Docker + Github Actions으로 배포 자동화

목표 : - Github Actions를 사용하여 CI/CD를 구축한다 - workflow : - build my project -> login to my Docker hub -> build and push my Image - 즉, 빌드한 결과물을 Docker Image로 만들어서 내 Docker Hub으로 push 하는 일련의 작

kkangdda.tistory.com


Github Action 코드를 짜다 보니, 프로젝트 빌드하는 과정을 어떤 식으로 해야지 효율적인지 궁금해졌다.
빌드하는 부분을 총 3번의 다른 방식으로 구성해 보았고, Github Action의 걸린 시간을 살펴보았다.

 

첫 번째 방식, 로컬 pc에서 내가 직접 프로젝트 build -> Github Action에서 나머지 작업 자동화

Dockerfile

# nginx 이미지를 사용합니다. 뒤에 tag가 없으면 latest 를 사용합니다.
FROM nginx

# root 에 app 폴더를 생성
RUN mkdir /app

# work dir 고정
WORKDIR /app

# work dir 에 build 폴더 생성 /app/build
RUN mkdir ./build

# host pc의 현재경로의 build 폴더를 workdir 의 build 폴더로 복사
ADD ./build ./build

# nginx 의 default.conf 를 삭제
RUN rm /etc/nginx/conf.d/default.conf

# host pc 의 nginx.conf 를 아래 경로에 복사
COPY ./nginx.conf /etc/nginx/conf.d

# 80 포트 오픈
EXPOSE 80

# container 실행 시 자동으로 실행할 command. nginx 시작함
CMD ["nginx", "-g", "daemon off;"]

github-action.yml

name: WORKFLOW_FOR_DOCKER

on:
  push:
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  # 1. 빌드 머신 준비
  build:
    runs-on: ubuntu-latest

    steps:
      # 2. 빌드 머신에 Repository Check Out
      - uses: actions/checkout@v3

      - name: Start Actions
        run: echo Start Actions!

      # 3. Docker Meta를 이용하여 생성할 이미지의 이름과 버전 정보 태깅 
      - name: Docker meta
        id: docker_meta
        uses: crazy-max/ghaction-docker-meta@v1
        with:
          images: iDaeun/daeun-portfolio-app
          tag-semver: |
            {{version}}
            {{major}}.{{minor}}

      # 4. 빌드 머신에 Docker 빌드에 필요한 사항 준비
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
        
      # 5. 이미지를 업로드 할 내 도커허브 로그인
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          
      # 6. 도커 이미지 빌드하고 허브로 푸쉬
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}

      - name: Finish Git Actions
        run: |
          echo Finished All Actions 🥳
          echo Please Check Your Docker Hub!

on > push > branch ["main"] : main 브랜치에 코드를 푸쉬하면 Github Action이 yml 파일에 정의한 작업내용에 따라 실행된다.
먼저 프로젝트를 빌드해 놓을 뒤 main 브랜치에 강제로 test 코드를 푸쉬하여 Github Action이 시작되도록 하였다.

그 결과, 걸린 시간 : 22초

 

두 번째 방식, Dockerfile 내부에서 프로젝트 build 자동화 -> Github Action에서 나머지 작업 자동화

Dockerfile

## builder
FROM node:17-alpine AS builder

# work dir 고정
WORKDIR /app

COPY package-lock.json ./
COPY package.json ./
RUN npm ci

COPY . ./
RUN npm run build

# nginx 이미지를 사용합니다. 뒤에 tag가 없으면 latest 를 사용합니다.
FROM nginx

# host pc의 현재경로의 build 폴더를 workdir 의 build 폴더로 복사
COPY --from=builder /app/build /app/build

CMD ["ls", "-al"]

# nginx 의 default.conf 를 삭제
RUN rm /etc/nginx/conf.d/default.conf
# host pc 의 nginx.conf 를 아래 경로에 복사
COPY ./nginx.conf /etc/nginx/conf.d

# 80 포트 오픈
EXPOSE 80

# container 실행 시 자동으로 실행할 command. nginx 시작함
CMD ["nginx", "-g", "daemon off;"]

--from : 새로운 빌드 스테이지를 뜻한다.
'builder'라고 정해준 스테이지에서 node를 사용해 주었고, 그 아래 새로운 스테이지에서 nginx를 사용하였다.

이렇게 해서 아래와 같은 순서로 실행되도록 하였다 :
1. 첫 번째 스테이지 (builder) : node사용하여 npm으로 프로젝트 빌드 (이전에는 내가 직접 로컬 pc에서 빌드했던 과정)
2. 두 번째 스테이지 : builder 스테이지에서 빌드한 결과물을 COPY 하여 가져오고, nginx로 Docker Image 빌드

github-action.yml > 첫 번째 방식과 동일함

그 결과, 걸린 시간 : 1분 23초

 

세 번째 방식,  Github Action에서 프로젝트 build + Docker 작업 모두 자동화

Dockerfile

# nginx 이미지를 사용합니다. 뒤에 tag가 없으면 latest 를 사용합니다.
FROM nginx

# work dir 고정
WORKDIR /app

# host pc의 현재경로의 build 폴더를 workdir 의 build 폴더로 복사
ADD ./build ./build

# nginx 의 default.conf 를 삭제
RUN rm /etc/nginx/conf.d/default.conf

# host pc 의 nginx.conf 를 아래 경로에 복사
COPY ./nginx.conf /etc/nginx/conf.d

# 80 포트 오픈
EXPOSE 80

# container 실행 시 자동으로 실행할 command. nginx 시작함
CMD ["nginx", "-g", "daemon off;"]

두 번째 방식에서 추가해 줬던 프로젝트 빌드 과정을 삭제했다.

github-action.yml 

name: WORKFLOW_FOR_DOCKER

on:
  push:
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  # 1. 빌드 머신 준비
  build:
    runs-on: ubuntu-latest

    steps:
      # 2. 빌드 머신에 Repository Check Out
      - uses: actions/checkout@v3

      - name: Start Actions
        run: echo Start Actions!

      ## 개선 ##
      - uses: actions/setup-node@v3
        with:
          node-version: 16.14.2
      - run: npm ci
      # - run : npm test (build 보다 먼저 test 실행)
      - run: npm run build

      - name: Log Test
        run: ls -al
        shell: bash
      #########

      # 3. Docker Meta를 이용하여 생성할 이미지의 이름과 버전 정보 태깅 
      - name: Docker meta
        id: docker_meta
        uses: crazy-max/ghaction-docker-meta@v1
        with:
          images: iDaeun/daeun-portfolio-app
          tag-semver: |
            {{version}}
            {{major}}.{{minor}}
      # 4. 빌드 머신에 Docker 빌드에 필요한 사항 준비
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
        
      # 5. 이미지를 업로드 할 내 도커허브 로그인
      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          
      # 6. 도커 이미지 빌드하고 허브로 푸쉬
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}

      - name: Finish Git Actions
        run: |
          echo Finished All Actions 🥳
          echo Please Check Your Docker Hub!

Github Action workflow에는 아래의 코드만 추가해 주었다 :

      ## 개선 ##
      - uses: actions/setup-node@v3
        with:
          node-version: 16.14.2
      - run: npm ci
      # - run : npm test (build 보다 먼저 test 실행)
      - run: npm run build

      - name: Log Test
        run: ls -al
        shell: bash
      #########

이는 node를 사용하여 npm install & build를 해주는 과정이다.
두 번째 방식에서는 Dockerfile에 해당 과정을 넣어주었다면, 이번에는 Github Action에 넣어준 것이다.

그 결과, 걸린 시간 : 1분


Github Actions에서 걸린 시간만 보면 첫 번째 방식이 제일 짧았지만, 이는 로컬에서 프로젝트를 빌드하는 시간을 뺀 시간이다.
그리고 나는 프로젝트 빌드하는 과정 또한 자동화하고 싶었기 때문에, 두 번째와 세 번째 방식이 내가 원하는 방향이다.

두 방식은 프로젝트 빌드를 하는 주체만 다른데, 하나는 Dockerfile에서, 다른 하나는 Github Actions에서 실행한다.
두 방식의 시간차는 약 23초로, Github Actions workflow에서 프로젝트 빌드를 해주는 게 더 빨랐다.

생각해 보면 Dockerfile에서 프로젝트 빌드를 하기 위해서는 프로젝트의 모든 소스를 COPY 한 뒤에 이를 빌드하는 방식이다.
그에 반해 Github Actions에는 소스를 COPY 할 필요 없이 바로 npm install & build를 할 수 있다.

물론 더 추가해야 하는 부분은 많지만, 프로젝트 빌드 자동화를 생각으로만 해보다가 직접 구성해 보고 개선시켜 보니 Github Actions를 이해할 수 있는 좋은 기회였다.

300x250