Server

GitHub Actions + Docker로 CI환경 구축

범데이 2024. 7. 13. 20:54
728x90

오늘은 GitHub Actions와 Docker로 구성된 CI 환경을 구축하는 방법을 포스팅해보려 한다.

 

개발하고 있는 React APP의 CI/CD 환경을 구축하기에 앞서 초석을 다지기 위한 CI 구축 단계라고 이해하면 된다.

 

 

작업의 흐름은 다음과 같다.

  1. 소스코드 Push
  2. GitHub Actions 동작
  3. GitHub Runner가 업데이트된 소스 코드가 반영된 Docker Image 생성
  4. 생성된 Docker image를 Docker Hub에 푸시

 

 

이제 이 구성을 세팅하는 방법을 알아보자.


1. GitHub Actions workflow (yml파일) 생성

GitHub의 repository 페이지에서 "Actions" > "New workflow" 를 누른다.

 

 

그런 다음, Choose a workflow에서 "node.js" 를 검색 후, "Configure" 버튼을 누른다.

 

그러면 친절하게도 node.js기준으로 설정할 workflow yml파일을 샘플로 작성하여 보여주는데,

 

나는 서두에 말한 흐름에 맞게 구성하기 위해 다음과 같이 yml파일을 설정하였다.

 

[<PROJECT_PATH>/.github/workflows/ci.yml]

name: CI/CD Pipeline

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x]

    steps:
    - name: Check out Git repository
      uses: actions/checkout@v4

    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Build Docker image
      run: docker build -t ${{ secrets.DOCKER_USERNAME }}/bumday_site:latest .

    - name: Push Docker image
      run: docker push ${{ secrets.DOCKER_USERNAME }}/bumday_site:latest

 

해당 파일의 내용을 간단하게 해석해보면 다음과 같다.

 

수행조건(on):

- 해당 레포지토리의 "main" 브랜치에 push 이벤트가 발생했을때 해당 작업이 수행된다.

 

작업(job/build):

- ubuntu-latest OS에서 수행된다

- node.js 버전은 18.x 버전을 사용한다.

- 소스코드를 Git repository로부터 checkout한다.

- Docker Hub에 로그인한다

- Docker image를 빌드한다.

- 빌드된 Docker image를 Docker Hub에 push한다.

 

secrets.DOCKER_USERNAME, secrets.DOCKER_PASSWORD는 GitHub에서 세팅하는 공개되지 않는 변수 같은 개념인데, 이에 대해서는 밑의 3번 단계에서 다룬다

 

이로서 GitHub repository에 push 할 시 GitHub의 Actions가 수행할 작업들을 구성하였다.

 

 

2. Docker 파일 생성

Dockerfile 파일을 생성한다.

 

이 파일에는 Docker image가 빌드될 때 수행할 일련의 작업들을 작성해준다.

 

[<PROJECT_PATH>/Dockerfile]

FROM node:18

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 8080

CMD ["npm", "start"]

 

 

해당 파일의 내용도 해석해보면 다음과 같다.

- node.js 18.x 버전을 사용한다.

- Docker 내에 working directory로 "/app" 경로를 설정한다.

- package.json 파일을 Docker 이미지 내 해당 경로로 복사한다.

- npm install(프로젝트 의존성 파일 설치)를 수행한다.

- 해당 프로젝트의 파일들을 Docker 이미지 내에 복사한다.  (관련해서 아래 .dockerignore 추가설명)

- 해당 도커 이미지를 8080번 포트를 외부에 공개한다는 설정(EXPOSE)를 한다.

- "npm start" 명령어를 수행하여 웹서비스를 실행한다.

 

 

중간에 파일을 복사하는 과정이 있는데, 불필요한 파일 등은 제외시켜줄 필요가 있다.

 

이를 위해 .dockerignore 파일도 생성한 후, 아래와 같이 미포함할 파일들을 포함시켜준다.

 

[<PROJECT_PATH>/.dockerignore]

.git
.gitignore
/node_modules
Dockerfile
README.md

 

 

이로써 docker build 명령어를 수행 시, Docker image가 어떻게 생성되게 할지 구성을 완료하였다.

 

 

3. Docker Hub Token 생성 & GitHub Secret 설정

(Docker Hub 계정이 없다면, 먼저 생성해주어야 한다.)

 

 

Docker Hub에서 Account Settings를 클릭한 후, 좌측의 "Security" 탭을 누른다.

 

 

토큰의 설명을 작성해 주고 (EX: DOCKER_HUB_TOKEN)

접근권한을 설정해준다. (EX: Read, Write, Delete)

 

 

그런 다음, 생성된 토큰을 따로 복사해둔다

(주의사항: 표시된 바와 같이 딱 한번만 보여주니, 꼭 적절한곳에 따로 적어 보관해두자.)

 

 

 

그런 다음, GitHub Action workflow에서 사용할 Docker Hub Username, Password를 설정해 줄 것이다.

 

Secret1 )

Name: DOCKER_USERNAME

Secret: <Docker Hub 유저명>

 

Secret2 )

Name: DOCKER_PASSWORD

Secret: <방금 생성한 Docker Hub Token>

 

 

 

4. 소스코드 Push하여 GitHub Actions 동작 테스트

 

이제 소스코드를 Push하여 GitHub Action이 잘 동작하는지 보자.

(만일 위와같이 workflow가 생성되지 않았다면, Settings > Actions > General 설정을 한번 검토해보자)

 

 

workflow yml 파일에 작성한 바와 같이, 순차적으로 작업이 실행되며 출력되는 텍스트들을 실시간으로 확인할 수 있다.

 

 

잠시 후, 모든 작업이 성공적으로 끝나면 위와 같이 녹색 표시와 함께 모든 작업들이 체크 표시됨을 확인할 수 있다.

 

 

 

만일 작업이 실패하면, 빨간 X표시와 함께 작업이 실패했다고 메일로 알람이 온다.

 

정말 좋은세상이다.. (라고 하기엔 GitHub Action은 이미 지금으로부터 5년전부터 제공되던 서비스이다.)

 

 

 

 

Docker Hub 레포지토리에서도 확인해보면, 이미지가 방금 push되었음을 확인할 수 있다.

 

 

마무리

오늘은 소스코드를 Push하여 자동으로 Docker image를 빌드하고 푸시하는 간단한 CI 프로세스를 구현하였다.

 

이제 이 Docker Hub에 있는 Docker image를 배포 환경에서 끌어다 쓸 수 있도록 세팅해주면 CD 프로세스까지 구현이 완료된다.

 

내가 현업에서 사용하던 통상적으로 사용되는 방법은 Kubernetes와 같은 Container orchestration 환경을 구축하여, Docker repository를 계속 주시하고 있다가 새로운 image가 업데이트 되면 자동으로 이미지를 교체하는 방식으로 CI/CD가 이뤄지도록 구축하였었다.

 

간만에 세팅하고 포스팅으로 정리해봤는데, 최대한 심플하게 구성하다보니 빠트린 점이 있을 수도 있다.

(부족한 부분이나 개선점이 있으면 얼마든지 댓글로 말씀 주시면 감사드리겠습니다.)

반응형