Deployment Nuxt3 Project in AWS EC2 with AWS CodeDeploy and Github Action - Code part
ServerHi, I’m Lovefield.
This article describes how to deploy Nuxt3 project using Github Action and AWS CodeDeploy, following “Deployment Nuxt3 Project in AWS EC2 with AWS CodeDeploy and Github Action - Setting part”
1.Install AWS CodeDeploy Agent
First install the AWS CodeDeploy Agent on the instance where you want to run the deployment. Enter the following command to proceed with the installation.
shell
sudo apt update
sudo apt install ruby-full
sudo apt install wget
cd /home/ubuntu
wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
Note that it is recommended to do so after giving the IAM settings to the instance. If you gave an IAM role to an instance after the Code Deploy Agent was installed, the role does not apply and you must restart the CodeDeploy Agent. In that case, please restart using the command sudo service codedeploy-agent restart.
Use the following commands to verify that the Code Deploy Agent is installed and running.
shell
sudo service codedeploy-agent status
> codedeploy-agent.service - LSB: AWS CodeDeploy Host Agent
> Loaded: loaded (/etc/init.d/codedeploy-agent; generated)
> Active: active (running) since Tue 2023-11-07 10:20:04 KST; 5h 39min ago
2. Create Github Action
Create the file .github/workflows/deploy.yml to set up Github action.
yml
name: Deploy
on:
pull_request:
branches:
- stage
types: [closed]
The "on" part is the part that specifies the trigger. Triggered when "pull_request" occurred. Properties add when PR is directed to stage and when PR is closed. PR recognizes merged as closed.
yml
jobs:
buildAndDeploy:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
The "jobs" part is actually the space where you write the command statement. You have created a task called "buildAndDeploay" and attach conditions to the bottom of it. The statement "if" determines whether the PR is actually merged. The buildAndDeploy entry runs only when merged.
Github Action allows you to use Ubuntu, MacOS, and Windows as virtual machines. Among them, we designated them to use the familiar ubuntu. Permissions is a permission-related setting. I give you read and write permissions because you need to build.
yml
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "18.x"
registry-url: https://npm.pkg.github.com
scope: "@octocat"
- uses: szenius/set-timezone@v1.2
with:
timezoneLinux: "Asia/Seoul"
- name: Check version
run: node -v
- name: Get current date
id: date
run: echo "date=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT
The "steps" section is a list of commands that are executed sequentially on the virtual machine in Github Action. First, run the items that you need by default.
The actions/checkout@v3 section is a command that allows the branch of the current store to be used. It's a must-have part of creating Action.
actions/setup-node@v3 specifies the version of the node to use because Node.js must be used.
The time on the computer where Github Action runs is the UTC time zone by default. We're going to use the Korean time zone, so we'll designate it as "Asia/Seoul".
Save the time zone when the action ran because you wanted to use a timestamp in the Build file. You will use the following command to name the file.
yml
- name: Install
run: yarn install --frozen-lockfile
- name: Create env file
run: echo "$ENV_VALUE" >> .env
env:
ENV_VALUE: ${{ secrets.STAGE_BUILD_ENV }}
- name: Build
run: yarn run build
- name: Get file name
id: file
run: echo "filename=front-end-${{ steps.date.outputs.date }}.zip" >> $GITHUB_OUTPUT
- name: Create ZIP file
run: zip -qq -r ./${{ steps.file.outputs.filename }} .
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2
- name: Upload Build file
run: aws s3 cp --region ap-northeast-2 ./${{ steps.file.outputs.filename }} s3://deploy/${{ steps.file.outputs.filename }}
- name: Create AWS codedeploy
run: aws deploy create-deployment
--application-name Git-action-stag
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name git-action-stage-group
--s3-location bucket=deploy,key=${{ steps.file.outputs.filename }},bundleType=zip
The "Install" part is familiar to you. Install the necessary modules before you build.
The "Create env file" part is the process of making the settings registered in secrets into a .env file. Due to the nature of the project, I used the .env file, so I wrote it because I needed it.
The "Build" part is the syntax for finally executing Build.
Specify the file name to use in the "Get file name" section. Combined with the date specified above, a file name in the form of "front-end-YYYYYMMDD-HHMMSS.zip" is configured.
In the "Create Zip file" section, create a zip file using the file name declared earlier.
In the "Configure AWS Credentials" section, set permissions to access AWS.
In the "Upload Build file" section, upload the compressed Build file to the S3 bucket.
In the "Create AWS Codeddeploy" section, specify the file location you uploaded to S3, the application you set up in AWS "CodeDeploy", and send a deployment request.
3. Create appspec.yml
apspec.yml is a file that you refer to when AWS Code Deploy runs.
Create the file "appspec.yml" at the top of the repository.
yml
version: 0.0
os: linux
files:
- source: /
destination: /home/deploy/action
overwrite: yes
permissions:
- object: /
pattern: "**"
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 60
runas: root
The "files" section determines where files uploaded to S3 will be released. The source part is not the path of the EC2 instance; it is the path of the compressed file. The "destination" part is the actual path of the EC2 instance.
The "permission" part is the user's permission to execute the current command.
"hooks" can specify which scripts to run during the deployment process. There are many points in time, but we used ApplicationStart.
4. Create deploy.sh
The hook file specified in apspec.yml.
Create deploy.sh at the top of the repository.
shell
#!/usr/bin/env bash
cd /home/deploy/action
TIMESTAMP=`date +%Y%m%d`
echo ">>> 프론트 재시작 스크립트 - $(date +%Y-%m-%d\ %H\:%M\:%S) <<<" >> "/home/deploy/log/$TIMESTAMP.log"
echo ">>> pid 확인" >> "/home/deploy/log/$TIMESTAMP.log"
PID=$(pgrep -f ".output/server/index.mjs")
if [ -z $PID ]
then
echo ">>> pid 없습니다" >> "/home/deploy/log/$TIMESTAMP.log"
else
echo ">>> $PID 번 pid 종료" >> "/home/deploy/log/$TIMESTAMP.log"
kill -9 $PID
fi
nohup node /home/deploy/action/.output/server/index.mjs 1>> /home/deploy/log/$TIMESTAMP.log 2>&1 &
echo ">>> 프론트 배포 $(date +%Y-%m-%d\ %H\:%M\:%S) <<<" >> "/home/deploy/log/$TIMESTAMP.log"
If you plan to use pm2, you can use the pm2 command. No particular reason but I didn't use pm2. The above script is described as follows.
1. Go to the folder you want to work with.
2. Create timestamp
3. Verify running pid
4. Exit if pid is present
5. Run applications using nohup