
이전에 EC2 인스턴스 에 pm2 로 Next.js 배포하는법을 정리한적이 있었는데, 이번에는 Github-Actions, S3, CodeDeploy 를 이용해서 해당 pm2 로 배포한 NextJS 프로젝트의 CI/CD 를 구축해보려한다.
플로우는 아래와 같다.

push 혹은 merge 시에 Github-Actions 의해 Next.js 를 build 후 압축하여 S3 에 업로드함CodeDeploy 가 미리 작성해둔 appspec.yml 파일의 설정에 맞춰 S3 에 있는 빌드파일을 EC2 로 가져옴deploy.sh 스크립트를 실행하여 pm2 의 ecosystem.config.js 설정을 실행하여 프로젝트의 변경사항을 감지하고 배포함AWS S3 에 들어가 빌드된 프로젝트를 올릴 버킷 을 생성해 준다.

다음으로는 AWS IAM 에 들어가 EC2 인스턴스 에 할당해줄 아래의 정책을 추가한 역할 을 생성해준다.

생성 후 EC2 -> 보안 -> IAM 역할수정에 들어가 앞에서 생성한 IAM 역할을 지정해준다.

추가로 Code Deploy 에 할당해줄 역할 도 생성해준다.

AWS Code Deploy 에 들어가 아래와 같이 애플리케이션 을 생성해준다.

이어서 배포 그룹 도 생성해준다. 서비스 역할 은 앞에서 생성한 Code Deploy 역할 을 선택해준다.

황경에는 타겟 EC2 인스턴스 를 선택해주고, Load Balancer 는 비활성화 해주도록한다.


이제 Github-Actions 에서 AWS 에 접근해야하는데 이 때 Access Key와 Secret Access Key가 있어야 접근할 수 있으므로 다음과 같이 IAM 사용자 를 생성해준다.

이제 key 들을 발급받아 아래와 같이 repository secret key 에 등록해준다.
(여기서 AWS_REGION은 ap-northease-2, 아시아태평양 - 서울 이다.)

아래의 명령어를 통해 EC2 에 Codedeploy agent 를 설치해준다.
$ sudo apt update
$ sudo apt install ruby-full
$ sudo apt install wget
$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto
아래의 명령어로 잘 설치되었고, 동작하는지 확인할 수 있다
$ sudo service codedeploy-agent status

이제 Github-Actions 에 대한 스크립트를 .github/workflows/main.yml 에 작성한다.
# .github/workflows/main.yml
name: main
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Git Checkout # Git Checkout
uses: actions/checkout@v3
- name: Check Node v # 노드 버전 확인.
run: node -v
- name: Install Dependencies # 의존성 설치
run: yarn install --frozen-lockfile
- name: Build # 빌드
run: yarn build
- name: zip create # S3에 업로드할 zip 파일 생성
run: zip -qq -r ./hoon-build.zip .
shell: bash
# -qq: quit 모드로 실행 (에러나 경고메세지만 출력하도록 함)
# -r: 지정된 디렉토리를 재귀적으로 압축 (하위 디렉토리와 파일들 모두 압축)
- name: Configure AWS credentials # AWS 인증 확인
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Upload to S3 # zip 파일을 S3에 업로드
run: |
aws s3 cp --region ap-northeast-2 ./hoon-build.zip s3://{{AWS S3 bucket명}}/hoon-build.zip
- name: Code Deploy # S3에 올라간 zip 파일을 CodeDeploy로 가져옴
run: aws deploy create-deployment
--application-name {{CodeDeploy 어플리케이션 이름}}
--deployment-config-name CodeDeployDefault.AllAtOnce # CodeDeploy에서 설정한 배포 설정
--deployment-group-name {{CodeDeploy 배포 그룹 이름}}
--s3-location bucket={{AWS S3 bucket명}},bundleType=zip # Code Deploy가 S3에서 프로젝트를 찾을 수 있도록 경로 지정. (bucket=버킷 이름/test-build.zip)
appspec.yml 파일은 code-deploy 가 실행할 스크립트이다. S3 로 부터 프로젝트를 EC2 인스턴스 의 지정한 경로로 가져와 지정한 shell script 를 실행한다.
version: 0.0
os: linux # Ubuntu니까 linux로 설정.
files:
- source: /
destination: /home/ubuntu/deploy # EC2 인스턴스 안에 프로젝트를 저장할 경로.
overwrite: yes
permissions: # EC2 인스턴스에 프로젝트를 저장하기 위한 권한 설정.
- object: /home/ubuntu/deploy # EC2 인스턴스 안에 프로젝트를 저장할 경로.
owner: ubuntu
group: ubuntu
mode: 755
hooks:
AfterInstall: # 배포 완료 후 실행할 동작 설정.
- location: ./deploy.sh # deploy.sh를 실행.
timeout: 60 # 제한 시간 1000초 으로 설정. 1000초가 넘어가면 실패함.
runas: ubuntu # ubuntu 권한으로 실행.
pm2 로 프로젝트를 실행할거기 때문에 pm2 의 설정을 작성할 ecosystem.config.js 를 아래와 같이 작성해준다.
module.exports = {
apps: [
{
name: "hoon-server", // 앱의 이름
script: "./node_modules/next/dist/bin/next", // Next.js 스크립트 경로
args: "start", // Next.js 앱을 시작할 때 사용할 인수
exec_mode: "cluster", // 실행 모드: cluster 또는 fork 중 선택
instances: "2", // 클러스터 모드에서 실행할 인스턴스 수 (CPU 코어 수만큼)
autorestart: true, // 프로세스 자동 재시작 활성화
watch: true, // 파일 변경 감지 활성화 (개발 중에만 활용)
max_memory_restart: "1G", // 1GB 이상 메모리 사용 시 재시작
env: {
NODE_ENV: "production", // Node.js 환경 설정
},
},
],
};
또한, 해당 설정을 실행하기 위해 package.json 에 script 를 추가해준다.
{
...
"script": {
...
"deploy": "pm2 start ecosystem.config.js --env production",
...
}
}
이제 마지막으로 appspec.yml 파일에 의해 실행될 deploy.sh 이다. 해당 경로로 이동해 위에서 작성한 ecosystem.config.js 를 실행하는 script 인 yarn deploy 를 실행해준다.
REPOSITORY=/home/ubuntu/deploy
cd $REPOSITORY
yarn deploy
이제 로컬에서 git 타겟 브랜치 에 push 혹은 merge 시에 아래와 같은 화면을 확인할 수 있다.


아래와 같이 안녕하세요~! 를 추가한 부분이 자동으로 잘 반영된것을 볼 수 있다.

이전에 해당 작업을 했을때 따로 정리를 안해둬서 오랜만에 AWS 관련 내용을 정리하면서 해볼려니까 이슈가 조금 있었다...
code-deploy 에 대한 에러로그는 아래의 명령어로 확인할 수 있다.
$ cat /var/log/aws/codedeploy-agent/codedeploy-agent.log
처음에 역할을 잘 못 지정해서 이슈가있었는데 aws 에 역할 변경 후 EC2 인스턴스 에서도 아래의 명령어를통해 reset 시켜주었다.
# AWS 자격증명 파일 삭제
$ sudo rm -rf /root/.aws/credentials
# codedeploy-agent 재시작
$ sudo service codedeploy-agent restart
아무래도 프리티어 버전의 EC2 인스턴스 를 사용하니까 디스크 공간 이 모잘라서 계속 에러가 났었다. 아래의 명령어를 통해 디스크 공간 을 확인하고 부족하면 EC2 의 EBS 공간 을 늘려주자.
# 디스크공간 확인
$ df -h
deploy.sh 스크립트를 실행하는 과정에서 pm2 command 를 찾지 못해 pm2 의 경로를 찾아 /usr/bin/pm2 /usr/local/bin/pm2 에 심볼릭 링크 를 지정해주었다.
which pm2
sudo ln -s {which pm2} /usr/bin/pm2
sudo ln -s {which pm2} /usr/local/bin/pm2