깃허브 액션은 깃허브에서 만든 CI/CD이다. CICD에 대해 간략히 설명하자면, Continuous Integration/Continuous Delivery의 약자로 지속적인 통합과 지속적인 배포를 의미한다.
지속적인 통합은 각각의 깃허브 브렌치에서 코드 조각이 지속적으로 merge되며 품질을 관리할 수 있도록 함을 뜻한다. CI가 없다면 개발을 마친다음 배포가 되어야 버그 발생 유무를 확인할 수 있는데, CI 덕분에 테스트와 코드 병합을 원할하게 진행할 수 있다.
CD는 말 그대로 배포를 의미한다. 배포환경을 결정하고 어떻게 빌드하고 배포할지 단계를 정하는 일을 담당한다.
소프트웨어 개발 생태계에서 배포 자동화는 굉장히 중요하다. 즉 배포에 있어 지연이 생기거나 어려움이 있다면 서비스를 사용하는 유저는 골치 아파진다. 개발자가 개발에만 집중하기 위해서는 이러한 배포 자동화는 단연코 필수적이다. 결국엔 CI/CD가 필요하다.
깃허브 액션은 강력하다. 간단한 yml파일만 입력하면 정말 간편하게 배포할 수 있다. 특히 레포지토리를 공개로 설정해두면 사용량 제한 없이 무료로 사용이 가능하다. 비공개 레포지토리여도 사용량 제한이 거의 없을 정도로 널널하다.
가격을 조금 알아보자면 아래와 같다. 그마저도 self-hosted로 배포하면 그냥 무료인 수준이다. 비공개 레포지토리만 가격 설정이 붙어있다.
비공개 레포지토리도 한달에 2000분 정도 걸린다. 보통 한 번 배포하는데 1분정도 걸린다는걸 감안하면 2000번 배포할 수 있다는 소리다. 개인이 개발하는덴 아무 지장이 없을 정도로 남아도는 셈이다.
문법은 정말 간단하다.
깃허브 레포지토리 상단에서 Actions를 선택하고,
set up a workflow yourself 를 클릭한다.
그럼 이런식으로 입력하는 창이 나온다. 참고로 경로는 .github/workflow/main.yml이다. 여기에 다음과 같은 코드를 작성하고 커밋을 눌러주면 정상적으로 반영이 된다.
name: projectname
on: push
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- run: docker compose up -d
name의 경우에는 프로젝트 이름(아무거나 지정해주면 된다)
on은 액션이 동작하는 이벤트를 지정해주는 건데, 우선은 push로 설정해둔다. 추후에 브랜치 풀 리퀘스트로 이벤트 지정해줄 수 있다. 또한 각각 이벤트에 따라 지정해둔 잡을 실행시켜줄 수도 있다. Cron이라던가 반복적인 작업 또한 물론 가능하다.
jobs는 실행시킬 단위를 뜻한다.
build는 말 그대로 빌드 단위
runs-on은 실행시킬 서버를 의미한다. 공개 레포라면 깃허브에서 기본적으로 제공하는 서버를 사용할 수 있지만 이 포스트에서는 self-hosted를 사용한다.
steps는 실행 단위를 적는 칸이다. - run 옵션을 활용하여 각각의 cli명령어를 실행해줄 수 있다. 여기서는 docker compose 배포 명령을 이용한다.
따로 배포서버를 사용하지 않을 계획이거나 비공개 레포지토리의 경우에는 돈을 쓰지 않기 위해서 Ownserver로 지정해놓는걸 추천한다. 필자의 경우에는 혹사시키는 Mac Mini서버를 구축해두고 있기 때문에 별다른 어려움이 없었다.
필자가 맥 미니를 home server로 구축한 이유와 방법이 궁금하다면 이 포스트를 참고하면 된다.
우선 상단의 Settings로 이동해주고
Actions 옵션을 클릭해준다.
Actions에서 runners로 이동해주고 New self-hosted runner를 입력해준다.
실행할 서버의 환경을 지정해준다. 필자의 경우 MacOS의 M1(ARM64)을 사용하고 있기 때문에 해당 환경에 맞게 아키텍처를 지정해준다. 이후 download와 Configure의 명령어를 그대로 cli 커맨드에 복사 붙혀넣기 해주면 깃허브에서 정상적으로 서버를 인식하게 된다.
그럼 위 사진처럼 새로운 runner가 생성되게 된다. 타이틀 옆에 보면 태그가 적혀있는데 이게 yml코드의 runs-on을 뜻한다.
도커 컴포즈는 여러 컨테이너를 하나의 서비스로 묶어 관리하기 쉽도록 해주는 도구다. 예를들어 백엔드 서버와 데이터베이스 서버를 각각 컨테이너화 해서 하나의 서비스로 묶으려면 각각의 컨테이너를 run하는 것 보다, compose로 묶어서 배포해주는게 환경설정 및 관리에 용이하다. 특히 하나의 서버에서 여러개의 서비스를 하는 경우에는 네트워크 분리나 통합적인 관리 측면에서 효율적이다.
필자도 도커로 처음 배포할 당시에는 각각의 컴포넌트로 관리했었는데, 지금 돌이켜보면 그때로 돌아가기 힘들 정도로 docker compose 가 익숙해져 버렸다. 그래서 컨테이너 테스트할때를 제외하곤 도커 명령어를 잘 안친다.
아무튼 docker compose를 사용하기 위해서는 Dockerfile을 작성해야 한다.
FROM node:18
WORKDIR /app
COPY package*.json /app
RUN npm install --global node-gyp
RUN npm install
RUN npm install -g typescript
RUN npm install pm2 -g
COPY . /app
RUN npm i -d @types/node
RUN tsc
RUN npm run bundle
CMD [ "pm2-runtime", "start", "npm", "--", "start" ]
EXPOSE 9023
pm2로 작동하는 node서버의 예시다. 이 포스트에서 다루지는 않겠지만, 도커파일을 작성하는 다른 블로그글을 첨부해두니 필요하신 분은 참고하시길 바란다.
[Docker] Docker File을 이용하여 Docker Image만들기
다음으로 docker-compose.yml를 작성하자면 다음과 같다. 프로젝트 디렉토리에 docker-compose.yml파일을 생성한 후 예시코드를 작성하자면,
version: '3.1'
services:
main:
build:
context: .
dockerfile: ./Dockerfile
ports:
- 9023:9023
environment:
DB_CLIENT: mysql
DB_HOST: 172.17.0.1
DB_USER: root
DB_PASS: pi1GfukVsan5UJGugWxF
DB_DATABASE: e2echat
DB_PORT: 13309
NODE_ENV: production
VIRTUAL_HOST: chat.devent.kr
LETSENCRYPT_HOST: chat.devent.kr
LETSENCRYPT_EMAIL: hhj@devent.kr
network_mode: "bridge"
db:
image: mysql:8.0
ports:
- 13309:3306
environment:
MYSQL_ROOT_PASSWORD: pi1GfukVsan5UJGugWxF
volumes:
- .docker/setup.sql:/docker-entrypoint-initdb.d/setup.sql
network_mode: "bridge"
redis:
image: redis:latest
command: redis-server --port 6379
container_name: redis
hostname: redis
labels:
- "name=redis"
- "mode=standalone"
ports:
- 6379:6379
로 작성할 수 있다.
version: 은 docker compose의 버전을 의미한다.
services: 는 하나의 컴포즈 묶음에서 동작할 컨테이너 서비스를 정의하는 구간이다.
main: db: redis:와 같은 것들은 서비스 이름으로 필자가 임의로 설정한 서비스 이름이다. 원하는 명칭으로 바꿔도 된다.
일전에 만든 도커 파일을 빌드하기 위해서는 서비스 명 아래에
build:
context: .
dockerfile: ./Dockerfile
로 이미지를 생성하는 과정을 거쳐야 한다.
ports: 는 말 그대로 포트를 외부로 노출하는 구문이다.
environment: 는 환경 변수 설정이다.
network_mode: "bridge"는 컨테이너의 네트워크를 브릿지 모드로 설정한다는 뜻이다.
이제 docker와 github action으로 배포할 준비가 끝났다. 배포를 위해서는 self-hosted서버에 docker가 설치되어 있어야 하고 온라인 상태여야 한다. 노트북으로도 충분히 가능하니 별다른 제약사항은 없다. 이제 github push를 하면 정상적으로 서비스를 배포할 수 있다.