Github Action으로 배포 이미지를 생성해보자! - (3)

HanSH·2024년 3월 6일

NestJS

목록 보기
20/29

이전 포스트에서는 Dockerfile으로 NestJS 서버 이미지를 만들었습니다. 이걸 다른 플랫폼으로 옮겨서 실행하려 하니 arm64에서는 amd64의 이미지를 실행할 수 없다고 하네요..?

amd64에서 작성한 파일을 arm64로 옮겨서 빌드하고 빌드한 이미지 이름으로 docker-compose 수정하고 실행하고...
매우 비효율적인 작업이라 생각했습니다.

그래서 arm64, amd64 두 아키텍처를 지원하는 이미지 파일을 만드는 간단한 CI 환경을 제작해보려 합니다.

CI/CD 툴

Jenkins, Github Action 등 여러 툴이 있지만 push 시 빌드를 하여 docker hub에 바로 등록을 하는 방법을 사용하고싶기에 Github Action을 사용하였습니다.

Github Action

깃헙 액션은 workflow 단위로 이루어집니다. workflow가 여러개면 여러개의 workflow가 동작을 하게 되죠. 이때 모든 workflow가 실행되기 원하지 않으므로 해당 workflow에 조건을 걸게 됩니다.

아래는 workflow의 예제입니다.
자세한 내용은 Github Action Docs를 참고해주세요!

# .github/workflows/build_image.yml
name: Docker Image Build and Push

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Get current date
      id: date
      run: echo "::set-output name=date::$(date +'%y.%m.%d')"

    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up QEMU # Quick Emulator
      uses: docker/setup-qemu-action@v1

    - name: Set up Docker Buildx # docker buildx 설정
      uses: docker/setup-buildx-action@v1

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

    - name: Build and push Docker image
      uses: docker/build-push-action@v2
      with:
        context: .
        file: ./Dockerfile
        platforms: linux/amd64,linux/arm64
        push: true
        tags: |
          han990401/rgback:latest
          han990401/rgback:${{ steps.date.outputs.date }}

name

깃헙 액션을 구분하는 이름입니다. 해당 리포지토리에서 중복되지 않고 알아보기 쉽게 작성해주시면 됩니다.

on

언제 동작할 것인지 설정합니다.
push/pull/label/issues 등 여러 상황이 만들어지거나 수정될 때 동작을 할 수 있게 합니다.

여기서는 main에 merge가 된 경우에만 image를 만들어 배포를 하고, main에는 직접 push를 하지 않기에 main branch에 push를 하게끔 작성하였습니다.

jobs

해당 workflow에서 실행될 작업들을 지정합니다. 여기서 사용하는 build라는 이름은 단순히 빌드를 하겠다라고 알려주는 역할을 합니다. 사용자 정의 이름이지요.

runs-on

어느 os에서 실행될 지 명시합니다. 기본은 linux이지만 다른 os 환경에서 빌드되기를 원한다면 해당 os를 적어줘야합니다.

단계

  1. runs-on: ubuntu-latest
    어느 환경에서 실행될 것인지 명시합니다. 리눅스에서 돌아가니 ubuntu로 하면 되겠네요!

  2. steps
    해당 단계에서 어느 이름으로 보일지, 어떤 작업을 할 지를 정의합니다. 이 부분의 작성은 gpt의 도움을 받아 작성하였습니다.

모든 과정을 완료하면 아래와 같이 로그가 남게 됩니다.

배포가 완료된 후 docker hub에 들어가보면

이미지 업로드가 잘 된것을 확인할 수 있습니다.

Deploy까지 해보자

이미지를 도커 허브에 올리는 과정을 마쳤습니다. ssh 접속을 하고 자동으로 배포하는 스크립트도 추가 해봅시다.

github action 스크립트 수정

- name: SSH Remote Commands
  uses: appleboy/ssh-action@v0.1.4
  with:
    host: ${{ secrets.SSH_HOST }}
    username: ${{ secrets.SSH_USERNAME }}
    key: ${{ secrets.SSH_PRIVATE_KEY }}
    port: ${{ secrets.SSH_PORT }}
    timeout: 3m
    script: |
      cd docker/prod
      bash deploy.sh

배포까지는 3분이면 충분하니 timeout을 3분으로 설정했습니다. 접속에는 password와 key 둘 중 하나를 사용할 수 있는데, 저는 rsa 키를 이용하여 접속을 하도록 하였습니다.

rsa 키 설정

키를 발급하고 pub과 key를 각각 서버와 secret에 등록하면 됩니다.
윈도우를 주 OS로 사용하니 윈도우 기준으로 작성하겠습니다.

키 발급

rsa 키를 발급받아봅시다.
ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\HanSH/.ssh/id_rsa): c:\Users\HanSH/.ssh-github_1/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in c:\Users\HanSH/.ssh-github_1/id_rsa
Your public key has been saved in c:\Users\HanSH/.ssh-github_1/id_rsa.pub
The key fingerprint is:
SHA256:LX/l7***********gAMdEwyp7wKiqsXY3bfT6E hansh@DESKTOP-B04M6C1
The key's randomart image is:
+---[RSA 3072]----+
|    .=o+         |
|    . O.   **    |
|     o o **      |
|      . **       |
| .   .  S.o   . .|
|o ...    +.o o o.|
|oo = . .E +.= +o.|
| ..   . .o.= *=. |
|+.  *o  .ooo**=o.|
+----[SHA256]-----+
  • Enter file in which to save the key 에는 원하시는 저장 경로를 입력해주시면 됩니다.
  • passphrase는 salt, petter라고 보면 됩니다. 덧붙여서 암호를 만드는것이죠.

이후 폴더로 가보면

.ssh-github_1
├── id_rsa     << 개인 키
└── id_rsa.pub << 공개 키

이런식으로 파일이 생성되어있습니다.

공개키는 서버의 .ssh 폴더의 authorized_keys에 추가해줍시다.

ssh-rsa AAAAB3NzaC****u8UxVvBYL****2mLuG2Ugr1QpTMfk= hansh@DESKTOP-B04M6C1

개인키는 Repository Secret에 추가해줍시다.
이때 ----BEGIN---- 부터 -----END----까지 전부 적어주셔야합니다!

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA2cmEAX9g2CBjRG9gSi95YuD9+r8Ewed81CAcj3mpjW79n1nADUfw
9WjJjzYLwEXsRHuIYLolsxWmNzavSXGwFNECfYN1FbUwVhlYF0WZtEHK58RbXrNurbmlTh
LwLAKm2RKcoYf5UXEUA1kB1rAkC/kAfM7q67Cr1c4Mqtz1G
***
DWTWrBiqQJ5bMTHuSXEYvKbc3j6l5FphyUysNdbZUmHsWtqnUi3oFVGhB+WseiF8vbFGaN
X6OodY8+Fxa8l+HapLNlbD1fG4JxGzvCCQOfeszfLrDoaNztzK+xMzqnrLpfOO4vR/sm0k
t7g8/r5zvms4tkWN4OGgiwlaztaZWDiGmhSYZxltkO+uajr2Uvi5rCQOHX9TzQffWAa7wQ
tiNOh18+O2/MEAAAAVaGFuc2hAREVTS1RPUC1CMDRNNkMxAQIDBAUG
-----END OPENSSH PRIVATE KEY-----

Github Action의 환경변수

외부에 노출시키고싶지 않은 값이 있다면 환경변수를 이용하는것이 좋습니다. 깃헙은 Repository 단위로 환경변수(secret)을 설정할 수 있도록 지원합니다!


참고

::save-state name={name}::{value}

관련 링크
save-state 명령이 곧 지원 중단된다고 합니다. 따라서 해당 명령 대신 깃헙 env에 저장하도록 권장한다고 합니다.

echo "now=$(date +'%y.%m.%d')" >> $GITHUB_OUTPUT 이런식으로 사용하면 됩니다!

사용은 기존에 쓰던 코드 그대로 쓰면 됩니다!

image tag의 arm64와 amd64

arm과 x86-64의 관계라고 보면 됩니다.
액션에는 latest밖에 없는데 이미지에는 왜 arm64와 amd64가 있냐!! 하신다면 처음 올렸을 당시 제가 docker image 동작 방식을 정확히 이해하지 못해서 그렇습니다.
platforms: linux/amd64,linux/arm64 이 구문으로 인해 amd64와 arm64를 모두 지원하는 이미지가 생성됩니다. 이후 docker로 이 이미지를 사용한다면 x86-64 아키텍처에서는 amd64를, arm64 아키텍처에서는 arm64를 선택하여 실행할 수 있습니다. 이를 통해 크로스 플랫폼 개발이 용이해집니다. (Github Action을 선택한 이유가 이것때문이기도 하고요. push 하기만 하면 그대로 빌드해서 올려주니까요.)

profile
저는 말하는 싹 난 감자입니다

0개의 댓글