[CI/CD] Github Action 시작하기 - Docker Hub, Slack 연동

2025. 4. 8. 17:50·Server & Infra

 

GitHub Action 이란?

 

GitHub Actions는 GitHub 저장소(Repository)에 내장된 워크플로우 자동화 도구입니다. 소프트웨어 개발 수명 주기 전반에 걸쳐 다양한 작업을 자동화할 수 있도록 설계되었으며, 특히 CI/CD(Continuous Integration/Continuous Deployment) 파이프라인 구축에 강력한 기능.

 

 

- Workflow (워크플로우): 자동화하려는 전체 프로세스를 정의. 하나 이상의 Job으로 구성되며, YAML 파일을 사용하여 .github/workflows/ 디렉토리에 정의한다.

- Event (이벤트): 워크플로우 실행을 트리거하는 특정 활동(예: push, pull_request 생성, schedule 등)

- Job (잡): 특정 Runner에서 실행되는 Step들의 집합. 기본적으로 Job들은 병렬로 실행되지만, 순차적으로 실행되도록 의존성을 설정할 수도 있다.

- Step (스텝): Job 내에서 실행되는 개별적인 작업 단위입니다. 쉘 명령어를 실행하거나, 미리 만들어진 Action을 사용할 수 있습니다. Job 내의 Step들은 순차적으로 실행.

- Action (액션): 워크플로우의 가장 작은 빌딩 블록으로, 재사용 가능한 코드 단위입니다. GitHub Marketplace에서 찾거나 직접 만들 수 있습니다. (예: actions/checkout, actions/setup-node)

- Runner (러너): 워크플로우 Job을 실행하는 서버. GitHub에서 제공하는 GitHub-hosted runner 또는 직접 관리하는 Self-hosted runner를 사용할 수 있다.


 

먼저 프로젝트에 적용하기 위해 폴더 부터 생성해야 한다.

 

.github/workflows 아래에 ci.yml 파일 생성!

 

🤖 내가 만들 Workflows! 

1. main 브랜치에 코드가 push 되거나 pull_request가 생성될 때 실행됩니다.
2. Node.js (TypeScript) 프로젝트를 빌드합니다.
3. npm 의존성 설치 속도를 높이기 위해 캐싱(caching)을 활용합니다.
4. 빌드된 결과물과 환경 변수를 포함하여 Docker 이미지를 빌드하고 Docker Hub에 푸시합니다 (docker compose 사용). 
5. 워크플로우 실행 결과를 Slack으로 알림 받습니다.

 

워크플로우 분석 (단계별 설명) 🧐

하나씩 작성 해보자..

 


워크플로우의 이름을 지정.

(GitHub 저장소의 'Actions' 탭에서 이 이름으로 워크플로우 실행 내역을 확인할 수 있습니다.)

 

 

 

 


main 브랜치에 코드가 푸시될 때 실행됩니다.

main 브랜치를 대상으로 하는 Pull Request가 생성되거나 업데이트될 때 실행됩니다.

 

 

 

 

 

제 프로젝트는 비공개 Repo라 Slack 사용 시 권한 설정이 필요했습니다.

 

 

 

 

 

 

 

 

워크플로우는 하나 이상의 Job으로 구성됩니다. 각 Job은 독립적인 환경(Runner)에서 실행됩니다. 여기서는 build라는 단일 Job을 정의!

 

 

 

env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} => docker-compose 파일에서 해당 변수를 쓰기 위함 (뒤에서 Docker Compose 파일에서 추가 설명하겠습니다.)

 

 

최종적으로 작성한 코드
# .github/workflows/ci.yml
name: CI - Build and Push Docker Image

# Event Trigger 정의
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions: write-all

# Job 정의
jobs:
  build:
    runs-on: ubuntu-latest # runner vm 
    
    # docker-compose 파일의 환경 변수를 위하여
    env:
      DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}

    steps:
    # GitHub Actions는 해당 프로젝트를 리눅스 환경에 checkout하고 나서 실행을 합니다.
    # 마치 우리가 브랜치를 만들 때 checkout하는 것처럼요. 꼭 필요합니다.
      - name: Checkout Source
        uses: actions/checkout@v3

    # Node.js 환경 세팅 
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 20

    # push할 때마다 npm을 install 해야될까..
    # 아닙니다. 해당 프로젝트의 node_modules가 변했는지 안 변했는지를 이용해서 모듈 변화가 있을 때만 npm install을 해줄 수도 있다다.
      - name: Cache node modules
        # 그걸 제공하는 Action가 존재한다다.
        uses: actions/cache@v3
        # 해당 step을 대표하는 id를 설정할 수도 있어요.
        # 해당 값은 뒤의 step에서 사용해볼게요.
        id: cache
        with:
          # node_modules라는 폴더를 검사하여
          path: node_modules
          # 아래 키값으로 cache가 돼있는지 확인합니다.
          key: npm-packages-${{ hashFiles('**/package-lock.json') }}


    # 의존성 설치
    # if 키워드는 해당 스텝을 실행할지 말지를 결정할 수 있는 키워드.
    # `steps.cache.outputs.cache-hit`이 값은 무엇일까요?
    # 위 step에서 정했던 cache라는 id를 steps.cache로 가져올 수 있어요.
    # cache라는 id 값을 가진 step에서는 cache-hit라는 output을 내뱉네요? 
    # 그걸로 cache가 hit 됐는지 안 됐는지를 알 수 있나봐요!
    # 그 값이 true가 아닐 때만 npm install을 하겠죠?
      - name: Install Dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: npm install

      - name: Run Build
        run: npm run build-ts

    # 프로덕션 환경에서는 .env 파일을 생성해줘야 합니다.
      - name: Create .env file for production
        run: |
          echo "${{ secrets.ENV_PRODUCTION }}" > .env
        shell: bash

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

      - name: Build and Push Docker Compose
        run: |
          docker compose build
          docker compose push

    # Slack 알림 설정
      - name: action-slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          author_name: Lee Chang Min
          fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
          # fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required
        if: always() # Pick up events even if the job fails or is canceled.

 

STEP 별 설명!

  • steps: 👣
    • build Job 내에서 순차적으로 실행될 개별 작업(Step)들을 정의
  • Step 1: Checkout Source (actions/checkout@v3) 
    • uses: actions/checkout@v3: 미리 만들어진 checkout Action을 사용
    • 이 Step은 워크플로우가 실행되는 Runner 환경으로 현재 저장소의 코드를 가져옵니다(checkout). 워크플로우에서 프로젝트 파일에 접근하려면 가장 먼저 이 작업이 필요합니다.
  • Step 2: Set up Node.js (actions/setup-node@v3) 
    • uses: actions/setup-node@v3: Node.js 환경을 설정하는 공식 Action입니다.
    • with: node-version: 20: with 키워드를 사용하여 Action에 필요한 파라미터를 전달합니다. 여기서는 Node.js 20 버전을 사용하도록 지정합니다.
  • Step 3: Cache node modules (actions/cache@v3) 
    • uses: actions/cache@v3: 파일이나 디렉토리를 캐싱하는 공식 Action입니다. npm 의존성처럼 자주 바뀌지 않는 파일을 캐싱하여 워크플로우 실행 속도를 크게 향상시킬 수 있습니다.
    • id: cache: 이 Step에 cache라는 고유 ID를 부여합니다. 이후 Step에서 이 Step의 출력(output)을 참조할 때 사용됩니다.
    • with:
      • path: node_modules: node_modules 디렉토리를 캐싱 대상으로 지정합니다.
      • key: npm-packages-${{ hashFiles('**/package-lock.json') }}: 캐시를 식별하는 고유 키를 생성합니다. hashFiles 함수는 package-lock.json 파일의 내용 해시 값을 계산합니다. 즉, package-lock.json 파일 내용이 변경되지 않으면 동일한 캐시 키가 생성되어 기존 캐시를 재사용하고, 변경되면 새로운 캐시 키가 생성되어 캐시를 새로 저장합니다. 똑똑하죠? 
  • Step 4: Install Dependencies 
    • if: steps.cache.outputs.cache-hit != 'true': 이 Step의 실행 조건을 정의합니다. steps.cache.outputs.cache-hit는 이전 cache Step (ID가 cache인 Step)의 출력 값 중 cache-hit를 참조합니다. 이 값은 캐시를 성공적으로 불러왔는지 여부를 나타냅니다 (true 또는 false). 따라서 이 조건은 "캐시 히트가 true가 아닐 때", 즉 캐시를 찾지 못했거나 유효하지 않을 때만 아래 run 명령어를 실행하라는 의미입니다.
    • run: npm install: npm 패키지 의존성을 설치합니다. (팁: 보통 npm ci를 사용하는 것이 package-lock.json을 기반으로 더 빠르고 일관된 설치를 보장하므로 권장됩니다! )
  • Step 5: Run Build 
    • run: npm run build-ts: package.json에 정의된 build-ts 스크립트를 실행하여 TypeScript 프로젝트를 JavaScript로 컴파일(빌드)합니다.
  • Step 6: Create .env file for production 
    • run: |: 여러 줄의 쉘 스크립트를 실행합니다.
    • echo "${{ secrets.ENV_PRODUCTION }}" > .env: GitHub Secrets에 저장된 ENV_PRODUCTION 변수의 내용을 Runner 환경에 .env 파일로 생성합니다. Docker 이미지 빌드 시 이 .env 파일이 포함되어 프로덕션 환경 변수를 주입할 수 있습니다. 주의: .env 파일을 Git에 직접 커밋하는 대신, 이렇게 CI 과정에서 동적으로 생성하는 것이 보안상 안전합니다. 🔒
    • shell: bash: 스크립트를 실행할 쉘을 명시적으로 지정합니다.
  • Step 7: Login to Docker Hub (docker/login-action@v3) 
    • uses: docker/login-action@v3: Docker 레지스트리(기본값: Docker Hub)에 로그인하는 공식 Action입니다.
  • Step 8: Build and Push Docker Compose 
    • run: |: 여러 줄의 docker compose 명령어를 실행합니다.
  • Step 9: action-slack (8398a7/action-slack@v3) 🔔📢
    • uses: 8398a7/action-slack@v3: 워크플로우 결과를 Slack으로 보내는 커뮤니티 Action입니다.

 


Tip!

 

1. docker compose 작성 시 아래 처럼 환경 변수를 사용해야 한다. 그러기 위해서는 간단하게 ci.yml 에 사용할 env 추가하면 된다.

 

 

 

2. 현재 프로젝트의 .env 파일에 환경 변수들이 많을때 이것을 다 git Action에 등록하는것 보다. ENV_PRODUCTION 하나만 등록해놓고 .env 내용을 var 에 복사한다.

 

그리고 STEP 6 처럼 간단히 사용 가능하다.

 


 

끝 

이제 CI/CD 부분의 CI 완료.. 다음편은 CD 설정 으로..

저작자표시 비영리 변경금지 (새창열림)

'Server & Infra' 카테고리의 다른 글

[CORS] 프론트와 백엔드 서버의 분리 환경 속 에서 발생한..  (0) 2025.01.21
JMeter - 부하 테스트 (feat. Cloud Run)  (0) 2024.09.19
'Server & Infra' 카테고리의 다른 글
  • [CORS] 프론트와 백엔드 서버의 분리 환경 속 에서 발생한..
  • JMeter - 부하 테스트 (feat. Cloud Run)
창MIN
창MIN
  • 창MIN
    미니의 코드
    만들고 도전하는것을 좋아합니다💻
  • Guest
    Gmail
    GitHub
  • 전체
    오늘
    어제
    • 분류 전체보기 (25)
      • Google Cloud (6)
      • NodeJS (3)
      • NestJS (1)
      • Python (1)
      • DB (1)
      • Docker & Kubernetes (1)
      • Server & Infra (3)
      • CS (7)
      • Algorithm (2)
        • 개념 (2)
        • 문제 (0)
      • 개발 (0)
  • 인기 글

  • 태그

    알고리즘
    redoc
    typeScript
    signed url
    cloud logging
    Cloud Function
    cloud buckets
    서버 부하 분산
    버킷 cors
    Google Cloud
    cors 작동
    nodejs
    서버 부하
    google api gateway
    쿠키와 세션의 개념
    cors 개념
    파일 무결성
    Cloud Storage
    Cors
    Secret Manager
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
창MIN
[CI/CD] Github Action 시작하기 - Docker Hub, Slack 연동
상단으로

티스토리툴바