Setting Up Zero-Downtime Deployment - Front-End Configuration
ServerHi, I’m Lovefield.
Continuing from the previous article, Setting Up Zero-Downtime Deployment - Environment Setup, this post will describe the configuration for achieving zero-downtime deployment of the front-end server. For the front-end framework, I used Nuxt.js, and the runtime environment was set up with Bun.js. Since building was a priority, I will first create a build and upload functionality using Git Actions.
Before writing the Git Action, you need to set the following secrets values:
- ENV: Environment variable values used by the front-end.
- HOST_DIR: Base directory location to be used on the server.
- HOST_IP: Server address.
- HOST_RUN_DIR: Directory location where scripts are executed on the server.
- HOST_USER: Server username.
- PEM_VALUE: PEM key value for accessing the server.
docker-compose.yml
YAML
name: Deploy
on:
push: # Executed when a push is made to the branch.
branches:
- main
workflow_dispatch: # Manually executed from the GitHub Actions page.
name:
description: "print name"
jobs:
buildAndDeploy:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v2 # Use bun.js
- name: Module Install
run: bun install --frozen-lockfile
- name: Create env
run: echo "$ENV" >> .env
env:
ENV: ${{ secrets.ENV }}
- name: Blue
run: bun run build
- name: Create ZIP
run: zip -qq -r ./.output.zip ./.output
- name: Upload ZIP file
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST_IP }}
username: ${{ secrets.HOST_USER }}
key: ${{ secrets.PEM_VALUE }}
port: 22
source: "./.output.zip"
target: ${{ secrets.HOST_DIR }}/
- name: Run Deploy Script
uses: appleboy/ssh-action@v1.1.0
env:
HOST_DIR: ${{ secrets.HOST_DIR }}
HOST_RUN_DIR: ${{ secrets.HOST_RUN_DIR }}
with:
host: ${{ secrets.HOST_IP }}
username: ${{ secrets.HOST_USER }}
key: ${{ secrets.PEM_VALUE }}
port: 22
envs: HOST_DIR,HOST_RUN_DIR
script: |
sudo cp -vf $HOST_DIR/.output.zip $HOST_RUN_DIR/front/blue/.output.zip
sudo cp -vf $HOST_DIR/.output.zip $HOST_RUN_DIR/front/green/.output.zip
cd $HOST_RUN_DIR
sudo sh deploy-frontend.sh
After performing the build and upload using GitHub Actions, the configuration executes ‘deploy-frontend.sh’ on the server. This ‘deploy-frontend.sh’ script updates the Blue and Green containers.
deploy-frontend.sh
Bash
#!/bin/bash
# Check if the blue container is running.
EXIST_BLUE=$(sudo docker compose ps -a | grep "frontend-blue")
target="blue";
target_port="8002"
TIMESTAMP=`date +%Y%m`
LOGFILE="./logs/frontend-$TIMESTAMP.log"
func_reload() # Re-load function
{
echo "[$(date +%Y-%m-%d\ %H\:%M\:%S)] $1 Container down" >> $LOGFILE
sudo docker compose down frontend-$1 # container down
rm -rf ./front/$1/.output # Delete existing files
sudo unzip -o ./front/$1/.output.zip -d ./front/$1 # unzip file
rm ./front/$1/.output.zip # delete zip file
echo "[$(date +%Y-%m-%d\ %H\:%M\:%S)] $1 Container up" >> $LOGFILE
sudo docker compose up frontend-$1 -d # container up
sleep 1.5
while true; do # Perform a health check every 2 seconds
RESPONSE=$(curl -I http://localhost:$2/health-check | grep "200" | awk '{print $2}')
echo "[$(date +%Y-%m-%d\ %H\:%M\:%S)] $1 Container Health Check" >> $LOGFILE
if [ "$RESPONSE" -eq "200" ]; then
break;
fi
sleep 2
done
}
touch $LOGFILE
echo "[$(date +%Y-%m-%d\ %H\:%M\:%S)] >>> Start of the front-end deployment script <<<" >> $LOGFILE
# If the Blue container is running
if [ "$EXIST_BLUE" ]; then
target="green";
target_port="8001"
else
target="blue";
target_port="8002"
fi
func_reload $target $target_port
if [ "$target" -eq "blue" ]; then
func_reload "green" "8001"
else
func_reload "blue" "8002"
fi
echo "[$(date +%Y-%m-%d\ %H\:%M\:%S)] >>> End of the front-end deployment script <<<" >> $LOGFILE
After writing the script as described above, it can be executed either through a Git push or by directly creating an action. The process will follow these steps:
Git Action builds the files based on the main branch.
Git Action compresses the built files and transfers them to the server.
Git Action executes the deployment script on the server.
The deployment script unzips the received file and updates the Blue and Green containers respectively.
Once everything is completed, log files will be created in the logs folder, as shown below.
Plain Text
[2024-12-22 23:28:50] >>> Start of the front-end deployment script <<<
[2024-12-22 23:28:50] green Container down
[2024-12-22 23:29:03] green Container up
[2024-12-22 23:29:11] green Container Health Check
[2024-12-22 23:29:11] blue Container down
[2024-12-22 23:29:22] blue Container up
[2024-12-22 23:29:28] blue Container Health Check
[2024-12-22 23:29:28] >>> End of the front-end deployment script <<<
With this, the front-end deployment configuration is complete.