- Published on
24.02.16 양수원 회고
- Authors
- Name
- 양수원
24.02.16 양수원 회고
도커를 이용한 AWS 배포 자동화(CI/CD)
구성도
- 로컬 pc에서 개발후 Github에 push 하게되면
- Github Action이 동작한다. (workflow)
- Github Container Registry에 소스를 받은 후 Doker로 이미지를 빌드한다.
- 빌드된 이미지를 EC2에 등록된 Runner가 복사된다.
- 기존 이미지를 삭제하고 새로운 이미지로 실행을 한다.
Dockerfile 생성
FROM node:21
ARG RDS_USERNAME \
RDS_TYPE \
RDS_RORT \
RDS_PASSWORD \
RDS_HOSTNAME \
RDS_DB_NAME \
JWT_SECRET \
JWT_EXPIRE
ENV RDS_USERNAME=${RDS_USERNAME} \
RDS_TYPE=${RDS_TYPE} \
RDS_RORT=${RDS_RORT} \
RDS_PASSWORD=${RDS_PASSWORD} \
RDS_HOSTNAME=${RDS_HOSTNAME} \
RDS_DB_NAME=${RDS_DB_NAME} \
JWT_SECRET=${JWT_SECRET} \
JWT_EXPIRE=${JWT_EXPIRE}
RUN mkdir -p /var/app
WORKDIR /var/app
COPY . .
RUN rm yarn.lock || true
RUN rm package-lock.json || true
RUN npm install
RUN npm run build
EXPOSE 3000
CMD [ "node", "dist/main.js" ]
FORM
은 뒤에올 명령어들을 수행할 기본이미지를 지정한다.ARG
는 빌드 중에 전달되는 빌드의 변수들을 지정한다.ENV
는 환경변수를 설정하는데 빌드중에 전달받은 ARG 변수들로 환경변수를 지정하고있다.RUN
빌드 명령을 실행한다. 컨테이너 내부에 디렉토리를 생성하고 package.json 파일안에 있는 종속된 패키지들을 설치하고 build 한다.EXPOSE
애플리케이션이 수신 대기하고 있는 포트를 설정한다.CMD
컨테이너가 시작될 때 실행할 명령어를 지정한다. nest.js의 경우 dist폴더로 컴파일 되기 때문에 dist폴더안에 main 파일을 실행한다.
Github Access Token 발급
- Setting → Developer Settings → Personal access token → Generate new token
- workflow에 대한 권한을 허용하고 package의 대한 delete권한도 허용한다.
- 레파지토리의 환경변수로 Token을 설정한다.
Workflow 파일 작성
참조 : https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
name: CI/CD Docker
# 트리거를 수행할 브랜치를 지정합니다.
on:
push:
branches: [main]
# 환경설정
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/api-server
VERSION: ${{ github.sha }}
NAME: api-server
RDS_RORT: 3306
jobs:
# 빌드 Job
build:
name: Build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
# github repository에서 checkout
- uses: actions/checkout@v4
# docker build 수행
- name: Set up docker buildx
id: buildx
uses: docker/setup-buildx-action@v3
# GitHub 컨테이너 레지스트리에 로그인 후 빌드 & 푸시
- name: Login to ghcr
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
cache-from: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache,mode=max
build-args: |
RDS_TYPE=${{ secrets.RDS_TYPE }}
RDS_RORT=${{ env.RDS_RORT }}
RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}
RDS_HOSTNAME=${{ secrets.RDS_HOSTNAME }}
RDS_DB_NAME=${{ secrets.RDS_DB_NAME }}
RDS_USERNAME=${{ secrets.RDS_USERNAME }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
JWT_EXPIRE=${{ secrets.JWT_EXPIRE }}
# 배포 Job
deploy:
needs: build # build 후에 실행되도록 정의
name: Deploy
runs-on: [self-hosted, label-go] # AWS ./configure에서 사용할 label명
steps:
- name: Login to ghcr
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# 3000 -> 80 포트로 수행하도록 지정
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 8080:3000 --name api-server --network docker-compose_ugizz-network --restart always ${{ env.DOCKER_IMAGE }}:latest
name: CI/CD Docker
# 트리거를 수행할 브랜치를 지정합니다.
on:
push:
branches: [main]
# 환경설정
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/api-server
VERSION: ${{ github.sha }}
NAME: api-server
RDS_RORT: 3306
on
: 워크플로에 대한 트리거를 지정한다. main브랜치에 push 될때 동작된다.env
: 워크플로의 사용할수 있는 변수를 지정한다. secrets는 깃허브에 등록된 변수이다.
jobs:
# 빌드 Job
build:
name: Build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
# github repository에서 checkout
- uses: actions/checkout@v4
# docker build 수행
- name: Set up docker buildx
id: buildx
uses: docker/setup-buildx-action@v3
# GitHub 컨테이너 레지스트리에 로그인 후 빌드 & 푸시
- name: Login to ghcr
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
jobs
: 워크플로가 동작할때 실행되는 job을 말한다.- build 라는 job을 생성한다. 이름을 ‘Bulid’로 지정 빌드의 작업권한을 부여했다.
- steps: 작업의 실한 단계를 정의한다.
- 현재 상태에서 가상의 컨테이너 안으로 체크아웃을 진행
- docker 빌드를 진행
- GitHub Container Registry에 로그인
# GitHub 컨테이너 레지스트리에 로그인 후 빌드 & 푸시
- name: Build and push
id: docker_build
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
cache-from: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache
cache-to: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache,mode=max
build-args: |
RDS_TYPE=${{ secrets.RDS_TYPE }}
RDS_RORT=${{ env.RDS_RORT }}
RDS_PASSWORD=${{ secrets.RDS_PASSWORD }}
RDS_HOSTNAME=${{ secrets.RDS_HOSTNAME }}
RDS_DB_NAME=${{ secrets.RDS_DB_NAME }}
RDS_USERNAME=${{ secrets.RDS_USERNAME }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
JWT_EXPIRE=${{ secrets.JWT_EXPIRE }}
- 컨테이너 레지스트리에 빌드 후 푸시한다. 이때 cache를 지정하는데 아래는 지정했을떄와 안했을 때의 시간차이를 보여준다.
- Build 과정에서 엄청나게 시간이 짧아 진걸 확인할수 있다.
deploy:
needs: build # build 후에 실행되도록 정의
name: Deploy
runs-on: [self-hosted, label-go] # AWS ./configure에서 사용할 label명
steps:
- name: Login to ghcr
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# 3000 -> 80 포트로 수행하도록 지정
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 8080:3000 --name api-server --network docker-compose_ugizz-network --restart always ${{ env.DOCKER_IMAGE }}:latest
- ghcr에 저장되어있는 docker image를 이용해 컨테이너를 실행시킨다.
- docker run은 실행중인 도커 컨테이너를 중지하고 이전 버전인 컨테이너와 이미지를 삭제한다.
- run-on 부분에서 runner가 실행된다. 이때 AWS에 등록했을 때 사용할 label 명을 작성해야 한다.
AWS에 Github Runner 설치
repository → settings → Actions → Runners → Linux
# Create a folder
$ mkdir actions-runner && cd actions-runner# Download the latest runner package
$ curl -o actions-runner-linux-x64-2.313.0.tar.gz -L
https://github.com/actions/runner/releases/download/v2.313.0/actions-runner-
linux-x64-2.313.0.tar.gz
# Optional: Validate the hash
$ echo "56910d6628b41f99d9a1c5fe9df54981ad5d8c9e42fc14899dcc177e222e71c4
actions-runner-linux-x64-2.313.0.tar.gz" | shasum -a 256 -c
# Extract the installer
$ tar xzf ./actions-runner-linux-x64-2.313.0.tar.gz
- EC2 인스턴스에서 실행한다.
- Enter the name of the runner group to add this runner to : 엔터
- Enter the name of runner : 엔터
- Enter any additional label : label-go (워크플로우 yml에 작성했던 라벨명
- Enter name of work folder : 엔터
nohup ./run.sh &
- 백그라운드로 실행한다.