서론
사내 서비스가 Git Actions, Docker, EC2, PM2를 활용해 CI/CD 및 파이프라인을 구축하여 사용하고 있었기에 학습이 필요하다..
간단하게 따라해볼 무언가를 찾아서 따라해보면서 학습할 것이 필요했는데
초행이다보니 같은 환경에서 진행한 분을 찾기 어려워 외국 유튜브 영상이나 기타 해외 자료들을 활용하며 따라하며 공부했다.
CI/CD란?
Continuos Integration / Continuous Delivery의 약자로 단어 뜻대로 지속적 통합과 배포를 뜻한다.
DockerFile 작성
Docker에 이미지를 빌드하고 컨테이너 생성을 하는 과정은 단순하고 Nodejs docs에서도 가이드라인을 제시해준다.
https://nodejs.org/ko/docs/guides/nodejs-docker-webapp
하지만 netsjs dockerfile을 사용하고 싶어 검색하여 사용하였다..
https://www.tomray.dev/nestjs-docker-production
나는 예제에다 alpine을 추가하여 사용했는데, 알파인은 클라우드 환경을 고려한 가벼운 리눅스 이미지다.
실습을 진행할 것이기 때문에 알파인으로 사용하였다.
DockerFile
# Base image
FROM node:18-alpine
# Create app directory
WORKDIR /usr/src/app
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# Install app dependencies
RUN npm install
# Bundle app source
COPY . .
# Creates a "dist" folder with the production build
RUN npm run build
# Start the server using the production build
CMD [ "node", "dist/main.js" ]
.dockerignore
Dockerfile
.dockerignore
node_modules
npm-debug.log
dist
CI를 위한 설정파일 생성
github actions은 CI를 역할을 수행하는 강력한 도구중 하나이다.
github actions을 사용하기 위해 깃헙 내 레포에서 Actions에서 워크플로우를 생성했다.
git-action.yml
name: Docker Image CI
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login Dockerhub
env:
DOCKER_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
DOCKER_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
- name: Build the Docker image
run: docker build -t manaweb-api .
- name: taging
run: docker tag manaweb-api:latest mag123c/manaweb-api:latest
- name: Push to Dockerhub
run: docker push mag123c/manaweb-api:latest
1. 메인 브렌치에 push될 때만 동작
2. 현재 레포의 코드를 체크아웃
3. 환경변수를 통한 도커 로그인
4. 도커 이미지 빌드
5. 푸시
환경변수는 내 깃허브 레포 > Secrets > Secrets and variable에서 변수 설정을 할 수 있다.
또한 여기서 푸시와 빌드 사이에 이미지 태깅에 대한 코드를 추가하였는데, 아래 트러블슈팅 1에서 다루었듯이 빌드 후 바로 푸시를 하게 되면 올바른 태그네임을 찾을 수 없다는 에러를 뱉어냈다.
Github Actions 동작 확인하기
계속된 실패로 지쳐있다가 태깅을 해주자 성공적으로 작동하는 모습이다.
AWS EC2 생성 및 Github Runner(self-hosted) 생성
ubuntu의 프리티어를 사용했으며 간단하게 인바운드 설정만 마친 뒤 인스턴스를 생성했다.
생성에 대한 포스팅은 생략하도록 하며 접속이 완료된 후 아래 명령어를 실행하자.
# root 계정으로 전환 + 현재 환경변수 사용
sudo su
# 패키지 버전 최신화
sudo apt update
sudo apt-get upgrade -y
깃허브의 레포에서 Settings - Actions - runner - New self-hosted runner에서 셋팅에 관련된 가이드라인을 받아볼 수 있다.
self-hosted의 가이드라인을 따라할 뿐이지만, 코드의 대략적인 기능을 파악해보았다.
#Download
## 1. 디렉토리 생성 및 이동
mkdir actions-runner && cd actions-runner
## 2. actions-runner 설치
curl -o actions-runner-linux-x64-2.309.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.309.0/actions-runner-linux-x64-2.309.0.tar.gz
## 3.설치한 파일의 SHA-256 해시를 계산하여 파일 체크
echo "2974243bab2a282349ac833475d241d5273605d3628f0685bd07fb5530f9bb1a actions-runner-linux-x64-2.309.0.tar.gz" | shasum -a 256 -c
## 4.설치
tar xzf ./actions-runner-linux-x64-2.309.0.tar.gz
####################################################
#Configure
## 1. 내 레포와 연결. 액세스 권한이 있는 상태로 설정됨
./config.sh --url https://github.com/mag123c/manaweb-api --token A4Y6RDGK6BFAYHTP2KKLL2LFAXJFC
## 2. 러너 실행
./run.sh
### ./run.sh & : 백그라운드로 실행
### nohup ./run.sh : 세션이 종료되어도 runner 유지 (ssh 세션 끊어도 유지)
정상적으로 ubuntu ip의 Runners가 등록된 모습
마지막 명령어인 ./run.sh를 사용하여 실행시키면 아래와 같은 모습이 된다.
CD pipeline 생성
workflows에 CD를 위한 yml파일을 생성했다.
name: CD Pipeline
on:
workflow_run:
workflows: ["CI Pipeline"]
types:
- completed
jobs:
build:
runs-on: self-hosted
steps:
- name: Pull Docker image
run: sudo docker pull mag123c/manaweb-api:latest
- name: Delete Old docker container
run: sudo docker rm -f manaweb-api-container || true
- name: Run Docker Container
run: sudo docker run -d -p 8080:8080 --name manaweb-api-container mag123c/manaweb-api
1. github actions에서 CI pipline이 동작이 완료되었을 때 CD 파이프라인이 실행되게 이름 및 타입 설정.
on:
workflow_run:
workflows: ["CI Pipeline"]
types:
- completed
2. runs-on은 작업이 실행될 환경을 지정한다. 깃헙 가이드라인에 따르면, yaml 파일에 self-hosted를 붙이라고 되어 있다.
3. 이미지를 다운로드(Pull)하고, 이전 컨테이너를 삭제한 다음 새로운 컨테이너를 실행한다.
CD 파이프라인은 CI 파이프라인이 성공적으로 동작이 완료되면 Docker 이미지를 다운로드하고 이를 사용하여 새로운 컨테이너를 실행하여 배포하는 역할을 한다. 이전 버전의 컨테이너는 삭제되고 새로운 버전이 설정한 포트를 통해 실행될 것이다.
EC2에 Docker 설치
https://docs.docker.com/engine/install/ubuntu/
위 공식문서를 활용하여 설치를 진행해보자.
# Docker 공식 GPG Key 추가
## 1. 패키지 목록 업데이트
sudo apt-get update
## 2. 필요한 패키지 설치(인증, 통신)
sudo apt-get install ca-certificates curl gnupg
## 3. Docker 패키지 관리에 사용할 dir 생성
sudo install -m 0755 -d /etc/apt/keyrings
## 4. GPG Key 다운로드 + 파일 경로 및 파일명 지정
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Docker Repo를 Apt 소스에 추가
## 1. Apt 저장소를 /etc/apt/sources.list.d/docker.list 파일에 추가
## 현재 ubuntu 버전의 코드명을 가져와서 사용
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## 2. Docker 패키지 사용을 위한 업데이트
sudo apt-get update
## 3. Docker 관련 패키지 설치 (도커엔진, 플러그인, compose 등)
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
설치가 완료되었으면 확인해보자.
# 현재 실행중인 Docker Container 목록 표시
sudo docker ps
정상적으로 찍히는 모습이다. (아직 실행중인 컨테이너가 없기 때문에 아무 값도 없다)
이후 docker login 명령어를 통해 도커에 로그인을 한다.
EC2에서 컨테이너 확인
Git Actions을 통해 CI/CD가 완료되고 나면 EC2에 정상적으로 컨테이너가 실행이 되어야 한다.
# 실행중인 docker container 확인
docker ps
하지만 명령어를 입력해도 실행되는것이 없어 5~6시간을 정상적으로 EC2에 배포가 되지 않은 것으로 착각했다.
# 실행중이거나 종료된 모든 컨테이너 확인
docker ps -a
모든 컨테이너를 확인해보니 아래처럼 컨테이너를 실행하자 마자 종료가 되는 모습이다.
해결한 과정은 아래 트러블슈팅의 2번 항목에서 확인할 수 있다.
5~6시간의 삽질 끝에 에러를 해결하고 나니 정상적으로 컨테이너가 실행되었다
curl 명령어를 통해 확인해보면 잘 동작한다.
또한 ec2의 public ip:port로 URL을 입력해도 잘 동작하는 모습.
이제 배포된 프로젝트의 API를 프론트에서 호출하여 사용하기만하면 끝!
트러블 슈팅
1. An image does not exist locally with the tag: [repo]/[image]
2. Docker Container 실행 후 바로 종료되는 현상
참조
1. AWS EC2에 도커 설치하려다 에러 발생했을 때
https://boying-blog.tistory.com/82
ssh를 password없이 restart할 때
$ sudo /etc/init.d/ssh restart
2. 'github action run after another' 키워드로 검색
3. 궁금해서 찾아본 workflow 트리거들
https://docs.github.com/en/actions/using-workflows/triggering-a-workflow
4. ubuntu에 docker 설치하기 (docker docs)
https://docs.docker.com/engine/install/ubuntu/
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!