AWS EC2와 RDS에 NestJS Github Action 배포하기
작업의 흐름
- EC2, RDS 생성/작업
- Dockerfile 작성
- ci_cd.yaml 작성 (Github Action)
- Github Action 세팅
AWS
EC2 생성
https://youtu.be/Jd7xdvwY_VQ?si=WPGOnAYwiUS0pwtD
EC2 기본 작업
sudo su
root 권한 주고
apt update
패키지 목록 업데이트
apt-get upgrade -y
설치된 패키지 업그레이드
램늘리기 (선택 사항)
// 사양 확인
free
// 스왑 파일 생성
dd if=/dev/zero of=/swapfile bs=128M count=16
// 권한 업데이트
chmod 600 /swapfile
// 스왑 영역 설정
mkswap /swapfile
// 스왑공간에 파일 추가하여 즉시 사용
swapon /swapfile
// 프로시저 상태 확인 - 파일 잘 만들어졌나
swapon -s
// 편집기 열고
vi /etc/fstab
// 제일 아래에 내용 추가
/swapfile swap swap defaults 0 0
// 확인
free
Docker 설치
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
설정
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
최신버전 설치
docker ps
설치 확인
Docker 공식 홈페이지 - ubuntu에 Docker 설치
RDS 생성
https://springdream0406.tistory.com/238
AWS RDS 프리티어 요금 부과 안되게 생성하기 (작성 중)
생성AWS RDS의 데이터베이스 생성으로 들어간다.(글에서 다루지 않은 부분은 기본설정 그대로 놔둡니다.) DB 인스턴스 식별자는 AWS의 DB탭에 표시되는 이름이며,마스터 사용자 이름은 DB 연결시
springdream0406.tistory.com
EC2에 ENV 파일 생성
sudo vi .env
github workflows에 적기에는 코드가 길어지고, 매번 .env 파일을 생성하고 지우는 행위는 아닌 것 같아서 직접 .env 파일 생성
EC2에 docker-compose.yaml 파일 생성
마찬가지로 docker-compose.yaml을 사용할 경우 github workflows의 코드가 깔끔해져서 생성함.
services:
프로젝트명:
image: 도커이미지 이름
ports:
- '포트:포트'
env_file:
- .env
아래 자동화에서
${{secrets.DOCKERHUB_USERNAME}}/${{secrets.PROJECT_NAME}}:latest
이렇게 적었으므로 그에 맞게 도커이미지 이름 작성하기
포트는 일반적으로 80:3000
공개키 허용 (Github Action에서 PEM Key를 이용한 연결을 사용할 경우)
EC2 서버 내부에서
sudo vi /etc/ssh/sshd_config
로 sshd_config 파일을 열고 맨 밑에
PubkeyAuthentication yes
PubkeyAcceptedKeyTypes=+ssh-rsa
추가 후 esc -> : -> wq
systemctl restart ssh
재시작
PostgreSQL SSL 설정
https://springdream0406.tistory.com/242
database "postgres", no encryption
AWS의 RDS에 postgres DB를 생성하고 연결하게 되면 이러한 에러가 발생한다.이유는 암호화된 연결을 사용하지 않아서 이고, 간단하게 해결하고 싶다면 (NestJS 기준) DB설정 코드에 ssl: { rejectUnauthorized:
springdream0406.tistory.com
Dockerfile 작성
개발과 배포를 분리하기 위해 Dockerfile.prod 로 파일 생성함
이후 코드들이 그에 따라 조금씩 변경됨
## .dockerignore
.github/
.vscode/
coverage/
dist/
node_modules/
postgres/
.env*
.git/
.gitignore
docker-compose*
Dockerfile*
# Dockerfile.prod
## 이미지 크기를 줄이기 위해 2단계로 나눔
# 1단계
FROM node:22-alpine AS build
WORKDIR /usr/src/app
COPY package*.json ./
COPY pnpm-lock.yaml ./
RUN npm i -g pnpm
# 의존성만 설치
RUN pnpm i
COPY . .
# 빌드
RUN pnpm run build
# 2단계
FROM node:22-alpine AS production
WORKDIR /usr/src/app
# 빌드된 파일만 복사
COPY --from=build /usr/src/app/dist /usr/src/app/dist
# 프로덕션 의존성만 복사
COPY --from=build /usr/src/app/node_modules /usr/src/app/node_modules
CMD ["node", "dist/main.js"]
Github workflows
루트에 .github/workflows 폴더 생성
원하는이름.yaml 파일 생성
name: AWS EC2 CI/CD
on:
push:
branches: ['main']
jobs:
#
test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Create Env File
env:
ENV: ${{secrets.ENV}}
DB_TYPE: ${{secrets.DB_TYPE}}
DB_HOST: ${{secrets.DB_HOST}}
DB_PORT: ${{secrets.DB_PORT}}
DB_USERNAME: ${{secrets.DB_USERNAME}}
DB_PASSWORD: ${{secrets.DB_PASSWORD}}
DB_DATABASE: ${{secrets.DB_DATABASE}}
REFRESHTOKEN_SECRET: ${{secrets.REFRESHTOKEN_SECRET}}
ACCESSTOKEN_SECRET: ${{secrets.ACCESSTOKEN_SECRET}}
FRONT_URL: ${{secrets.FRONT_URL}}
SOCIAL_CALLBACK_URL: ${{secrets.SOCIAL_CALLBACK_URL}}
SOCIAL_GOOGLE_ID: ${{secrets.SOCIAL_GOOGLE_ID}}
SOCIAL_GOOGLE_SECRET: ${{secrets.SOCIAL_GOOGLE_SECRET}}
SOCIAL_KAKAO_ID: ${{secrets.SOCIAL_KAKAO_ID}}
SOCIAL_KAKAO_SECRET: ${{secrets.SOCIAL_KAKAO_SECRET}}
SOCIAL_NAVER_ID: ${{secrets.SOCIAL_NAVER_ID}}
SOCIAL_NAVER_SECRET: ${{secrets.SOCIAL_NAVER_SECRET}}
run: |
touch .env.test
echo ENV="test" >> .env.test
echo DB_TYPE="$DB_TYPE" >> .env.test
echo DB_HOST="localhost" >> .env.test
echo DB_PORT="$DB_PORT" >> .env.test
echo DB_USERNAME="$DB_USERNAME" >> .env.test
echo DB_PASSWORD="$DB_PASSWORD" >> .env.test
echo DB_DATABASE="$DB_DATABASE" >> .env.test
echo REFRESHTOKEN_SECRET="$REFRESHTOKEN_SECRET" >> .env.test
echo ACCESSTOKEN_SECRET="$ACCESSTOKEN_SECRET" >> .env.test
echo FRONT_URL="$FRONT_URL" >> .env.test
echo SOCIAL_CALLBACK_URL="$SOCIAL_CALLBACK_URL" >> .env.test
echo SOCIAL_GOOGLE_ID="$SOCIAL_GOOGLE_ID" >> .env.test
echo SOCIAL_GOOGLE_SECRET="$SOCIAL_GOOGLE_SECRET" >> .env.test
echo SOCIAL_KAKAO_ID="$SOCIAL_KAKAO_ID" >> .env.test
echo SOCIAL_KAKAO_SECRET="$SOCIAL_KAKAO_SECRET" >> .env.test
echo SOCIAL_NAVER_ID="$SOCIAL_NAVER_ID" >> .env.test
echo SOCIAL_NAVER_SECRET="$SOCIAL_NAVER_SECRET" >> .env.test
- name: Setup node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install pnpm
run: npm i -g pnpm
- name: Install dependencies
run: pnpm i
- name: Run tests
run: pnpm test
build:
# test가 완료되어야 함
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to Dockerhub
uses: docker/login-action@v2
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_ACCESSTOKEN}}
- name: Build and Push Dokcer image
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/${{secrets.PROJECT_NAME}}:latest -f Dockerfile.prod .
docker push ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.PROJECT_NAME}}:latest
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: SSH to EC2 and deploy
uses: appleboy/ssh-action@v0.1.3
with:
host: ${{secrets.EC2_HOST}}
username: ${{secrets.EC2_USER}}
key: ${{secrets.EC2_SSH_KEY}}
script: |
sudo docker compose down
sudo docker rmi ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.PROJECT_NAME}}:latest
sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.PROJECT_NAME}}:latest
sudo docker compose up -d
name은 github action에서 진행내역에 뜨는 이름
들여쓰기 주의
DOCKERHUB_ACCESSTOKEN 은 Docker Hub의 Account settings에서 발급받기
EC2_HOST 는 퍼블릭 IPv4 주소
EC2_USER 는 일반적으로 ubuntu
EC2_SSH_KEY 는 pemkey
Github Action 세팅
해당 레퍼지토리의 세팅에서
로 가서 위에서 작성한 yaml에 들어가는 환경변수들 등록하기.
(EC2_SSH_KEY의 경우 start와 end 표시 전부 포함해서 그대로 복붙)
EC2 https 적용
https://springdream0406.tistory.com/241
배포 cookie 문제
소셜 로그인을 위해, jwt로 만든 refreshToken을 cookie에 담아서 주고받는 기능이 있는 프로젝트를, Front는 Netlify에, Back은 AWS EC2에 배포를 했다.문제1. EC2 https처음 만난 문제는 Back인 EC2의 https 변경이
springdream0406.tistory.com
참고
https://sjh9708.tistory.com/237
[AWS & Github Actions] CI/CD 파이프라인 구축 (Spring + Docker)
진행중인 프로젝트의 데브서버에 CI/CD 파이프라인을 구축하는 작업을 맡게 되었다.이전 포스팅에서 AWS EC2에 스프링 프로젝트를 Docker 컨테이너 사용과 함께 가장 심플한 형태로 배포해 본 적이
sjh9708.tistory.com