처음으로 해본 '제대로 된' 프로젝트 KOJ ④

KOJ의 DX를 위한 많은 노력들. Docker & Github Actions

Featured image

들어가며

사실 그동안 글을 많이 안썼기도 했지만… 이 environment탭에 글을 많이 못쓴것도 사실입니다. 개발 환경이나, 언어에 구애받지 않고 사용할 수 있는 그러한 것들을 다루는 섹션이었죠… 이번 글에서 다룰 주제는 ‘개발 환경 세팅’ 이기 때문에 오랫동안 새 글을 받아보지 못한 이 environment 섹션에 새로운 글이 되어줄 것입니다.

DX, DevOps, CI/CD… 이런 말들을 들어보셨을 것입니다. 서비스를 만드는것도 일종의 작업이고 노동입니다. 도구를 사용하는 사람이라면, 편하고 효율적으로 일 하고 싶어하고, 컴퓨터와 함께 일하는 우리들은 자동화 할 수 있는것이 상당히 많습니다. 일을 최대한 편하게 하기 위한 KOJ 프론트담당의 이야기를 시작해볼까 합니다. 배포 설정에 대한 이야기도 같이요.

배경

KOJ는 제가 일하는 연구실의 서버 컴퓨터에서 실행되어야 합니다. 코드 작성 -> git pull -> 빌드 -> 실행을 기능 하나 하나 찍어낼 때마다 반복하는것은 정말 귀찮은 일입니다. 마치 세탁물을 세탁기 -> 건조기 -> 정리 하는것이 귀찮은 것처럼 말이죠… 이번 KOJ 프로젝트에서는 Github에서 제공하는 Github Action을 십분 활용해서 커밋 -> 배포가 될 수 있도록 하기 위해서 제가 했던 노력들을 설명해볼까 합니다.

왜 Docker를..?

기술을 사용한다면, 사용하는 합리적인 이유가 필요하겠지요. 향후에 다른 서버에 배포 될 때의 실행도 보증할 수 있기도 하고, docker 이미지로 배포를 해둬서 버전 관리를 하면 배포를 하다가 뭔가 문제가 생겼을 때, 잘 돌아갔던 이전 버전으로 돌려서 장애 대처도 쉽게 할 수 있죠.

Github Workflow 작성

.github/workflows/docker-publish.yml링크를 첨부하고 시작하겠습니다. 단순히 yml 파일 하나만 첨부하는 것이 아니고, 기존에 github action을 사용해 본 경험이 없는 분이더라도 이해할 수 있도록 최대한 설명을 자세히 하면서 시작하겠습니다. Github Actions에 필요한 yml 파일을 작성하는 모든 명세는 공식 docs에 잘 되어 있고, 상당히 양이 많으니, 이 글에서는 제가 구성한 작업을 여러분도 재구성 할 수 있을 정도의 수준으로 설명해볼까 합니다.

Github Workflow - on

Github Workflow는 특정한 이벤트(특정 브랜치에 커밋 발생 등)가 발생했을 때, 실행될 작업 목록의 집합입니다. “이러한 이벤트가 발생했을 때, 내가 정해놓은 일을 해라” 하는 것이죠. “세탁기에서 세탁이 완료되면 세탁물을 건조기에 넣고 건조해라” 와 같은 형식인겁니다.

on:
  push:
    branches: ["main"]

이 부분은 “main” 브랜치에 푸쉬 되었을 때. 실행할 일들이다. 라는 뜻이 되겠습니다.

Github Workflow - jobs

작업들이 실행될 조건을 지정하였으니, 이제 실제로 실행될 작업에 대해서 기술해야겠죠.

jobs:
  publish:
    name: publish image
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: Login
        run: |
          echo $ | docker login ghcr.io -u $ --password-stdin
      - name: Build and Publish
        run: |
          docker build . --tag $/$
          docker push $/$

각 필드 이름이 직관적이기에 짚고 넘어갈 부분만 간단히 살펴봅시다.

job의 name 필드

publish라는 job의 이름을 나타내는 필드가 있지만, github의 action 필드에 표시될 이름을 별도로 지정할 수 있습니다.

job의 runs-on 필드

해당 job이 실행될 환경을 지정할 수 있습니다. github에서 제공하는 리눅스 컨테이너를 사용할 수도 있고, 본인이 직접 호스팅 해놓은 github action runner 환경에서 실행 할 수도 있습니다. 관련 github docs

steps의 uses 필드

uses: actions/checkout@v3 라고 되어 있습니다. 해당 action은 runner가 해당 steps 들을 실행할 때, repo를 checkout 해서 사용 할 수 있게 하는 action 입니다. 여기에서는 레포지토리 내용을 읽어서 도커 이미지를 빌드해야 하기 떄문에 사용하였습니다.

step의 name과 run

뒤는 쉘 스크립트 작성입니다. GHCR(GitHub Container Repository)라고 해서 도커 이미지를 관리해주는 깃헙 서비스를 이용할 수 있는 토큰을 이용해서 ghcr.io 서비스에 로그인을 하고, 빌드/이미지 배포까지 하고 있습니다.

실제 배포될 서버에 실행

이제 우리는 github에서 제공한 실행환경을 통해서 우리의 코드 빌드 결과물을 도커 이미지화 시켜서 GHCR에 성공적으로 배포하였습니다. 이제는 이 이미지를 우리가 배포할 타겟 서버에 실제로 배포해야 합니다. 사람이 직접 한다면 ssh로 원격 접속을 해서, ghcr에 로그인 해서, docker compose를 통해서 이미지를 올리겠죠. ssh 인증키를 등록하고, 로그인해서 docker관련 작업을 하고 빠져나오면 됩니다.

deploy:
  needs: publish
  name: deploy image
  runs-on: ubuntu-latest

  steps:
    - name: install ssh keys
      run: |
        install -m 600 -D /dev/null ~/.ssh/id_rsa
        echo "$" > ~/.ssh/id_rsa
        ssh-keyscan -p $ -H $ > ~/.ssh/known_hosts
    - name: connect, login, and pull
      run: |
        ssh -p $ $@$ "
          cd $
          echo $ | docker login ghcr.io -u $ --password-stdin
          docker compose pull
          docker compose up -d
          exit
        "
    - name: cleanup
      run: rm -rf ~/.ssh

참고가 될만한 글로 ssh 키 발급 관련 stackoverflow 답변 글을 첨부합니다.