Deploy Web Application with GitHub Actions (CI/CD) and Amazon Web Service EC2
Writing a web application with a wide range of topics is not easy. We have to go through many processes such as, collect the customer's business requirements, plan the project implementation, calculate the progress time, and finally deploy the website application system to the internet. One of the above steps, the step of deploying the project to the internet is equally interesting, but requires a lot of expertise, both in terms of programming knowledge and experience in using the linux open source operating system.
I. A brief introduction to the basics
In the blog post In this tutorial we will go through the process of deploying a simple NextJS web application to AWS EC2, with CI/CD support coming from Github Action. To do this, we need to briefly learn the following technologies:
- GitHub Action
- AWS EC2 Instance
- Bash shell scripting
- CI/CD
- Next.JS
1. Github Action
GitHub ACtion is a tool for creating workflows containing instructions for performing installation and testing steps. Test the website system automatically (Continue Integration). After that, we will proceed to build the source code and send it to website servers on the internet (Continue Delivery).
This process happens automatically every time, user push code to main branch, or pull request request to merge main branch code is made. In the process of executing instructions from the Github Action workflow. If an error occurs, the whole CI / CD process will be interrupted, and error messages will be sent to the developers quickly to help developers detect and fix them.
2. AWS EC2 Instance
Surely all of us have access visit websites online and wonder where they come from. Well, I have the answer for you whether it's from online servers, cloud services, or your own computer. These include popular services such as: Amazon Web Service, Microsoft Azure, Digital Ocean, Hostinger.
One of the most popular services, as well as trusted by many organizations, is AWS. Basically, AWS is a combination of many tools that help create and manage servers with different types of cloud computing services. Typically EC2, which is a virtual machine running on the AWS platform, with many configuration choices, along with the ability to replicate EC2 VMs will help your web services be deployed and run smoothly. more smoothly.
3. Bash shell scripting
Bash shell scripting is human-made command line Use pre-programmed, defined. Usually integrated in UNIX or UNIX-like operating systems such as Linux, Mac OS. These commands were born to help us perform daily computer tasks and workflows smoothly, quickly, and fully automate repetitive tasks.
In terms of time and productivity, Shell Script (Bash script) will be better than having to move the mouse to operate on the interactive graphical user interface (GUI). And because CI/CD-related jobs often repeat certain steps, it's essential to have a basic understanding of shell scripting.
4. CI/CD
CI (Continuous Integration) Is a process of continuous data integration, allowing developers to push code to a code repository (GitHub, Git Lab, BitBucket, …). Then CI will automatically run, checking for errors arising from the code that the developers put up. Common types of CI will be Unit Test, Coverage Test, End to End Test, Selenium Headless Test. Thereby giving feedback to help developers quickly solve problems when there are bugs. As a result, the website system operates efficiently, quickly and maximizes work productivity, avoiding potential overlapping bugs when adding many new features later.
CD (Continuous Delivery)
Is the process of transferring data continuously. You can understand CD as more advanced technology of CI. It not only performs the task of launching and finding bugs through different forms of testing in existing code, but also proactively changing the testing environment or staging or production, to point to the right deploy object. .
5. NextJS
Developed based on Facebook's famous JavaScript library is React.JS. NextJS not only allows us to break down the website into separate JSX files representing each individual component, the shared component can be reused throughout the website system. It also integrates some other attractive features that React JS is not available to us such as: Router ,Server Side Rendering, Image Optimization,…
II. Install CI/CD with GitHub Action and Self Hosted
OK. After we've gone through the concepts of the technologies, and how CI/CD works, next we'll install and deploy a simple Next.JS Web application on AWS. EC2.
1. Create a Next.JS project with TypeScript support
- Before you start working, remember to install Node JS 16.x and Visual Studio Code.
- Open Terminal and type the following command to create a project, name the project my-app.
npx create-next-app@latest --ts
- The process will take place in a few minutes
- After creating it, type the following command to open the Project on Visual Studio Code
cd my -app && code .
- The generated project will have the following directory tree structure:
├── next.config.js
├── node_modules
├── package.json
├── pages
│ ├── api
│ │ └── hello.js
│ ├── _app.js
│ └── index.js
├── public
│ ├── favicon.ico
│ └── vercel.svg
├── [README.md](http: //readme.md/)
├── styles
│ ├── globals.css
│ └── Home.module.css
└── yarn.lock
2. Run Next.JS on localhost:
- To make sure the code when deploying, we should build and run in production mode for testing. However, when you are in the process, you should use development mode to make it easier to debug.
- Run the following command combination in Terminal:
npm install -g yarn && \
yarn build && \
yarn start
- Go to localhost:3000 to test and The output will look like the image below
3. Upload the project to the Repository of GitHub and configure GitHub Actions:
- If you have never used GitHub, create an account before performing the following steps.
- After creating the repository, we will push the code in the my-app directory to the newly created Repository. Since this is one of the familiar operations that programmers often do, I will not mention it in detail in this blog post.
- In the repository, select Actions tab, select Worflows suggested as Node.js
- Name the workflow
- Edit the content of the workflow.yml file Follow the best workflow below, and click Start Commit to save the workflow to the Repository.
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions /language-and-framework-guides/using-nodejs-with-github-actions
name: Auto Deploy NextJS to EC2 Instance
on:
push:
branches: ["main"]
env:
test: test
jobs:
build:
runs-on: self-hosted
strategy:
matrix:
node-version: [16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/ releases/
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node -version }}
- name: Install Yarn, PM2
run: npm install -g yarn pm2
- name: Install Node Module
run: yarn
- name: Build,Start and Restart Web Application
run: RUNNER_TRACKING_ID="" && yarn build && pm2 start yarn -- start && pm2 restart yarn
- Next, go to the Settings Tab and select Actions → Runner → New self-hosted runner
- Select the Linux operating system and copy the code circled in red as shown in the image:
- Next we will prepare the bash shell script toAutomate the setup process of Github Action Runner Self hosted for Server.
- Note the code just copied above we will replace it at “
”
- Note the code just copied above we will replace it at “
#!/bin/bash
# Change Directory to HOME directory
cd $HOME
set -xe
# This code will be copy and paste to EC2 instance User Data Field, Or UserData Property in Cloudformation,...
# Set environmentable to detect your project source code folder in EC2/VMware Instance
# Change project name here
PROJECT_NAME=todo-list-website
echo "This script will set up your server to be listenning GitHub Action and pull code Automatically when main branch or master branch change"
mkdir actions-runner && cd actions-runner
curl -o actions-runner- linux-x64-2.296.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.296.2/actions-runner-linux-x64-2.296.2.tar.gz
tar xzf ./actions-runner-linux-x64-2.296.2.tar.gz
################################# ################################################## ################################################## #####
# Warning this token and link is getting from TAB Setting -> Actions -> Runner -> Create New Runner -> Linux in your GitHub Repository
echo -ne '\n' | <Copy this link from Configure Section in Add New Runner Page>
##################################### ################################################## ################################################## #
sudo ./svc.sh install
sudo ./svc.sh start
sudo ./svc.sh status
echo "Complete Setup Github Action CI/CD by GitHub Runner"
4. Create EC2 Server on AWS and Embed Bash Shell Script:
- Before doing this part, you should learn briefly about AWS, as well as EC2 and SSH Key to connect to the server in case of exception handling.
- Suppose after successful account registration, you go to the homepage and search for EC2 as shown:
- Click on EC2 to go to the Dashboard to manage virtual servers in the cloud
- Click the yellow Launch Instance to initialize the Server
- Follow the steps shown below:
(Note) in the Key pair (login) step, you need to learn about AWS SSH and Key pair first, and then follow the steps in the Network settings Tab later.
Finally, we click Launch instance to launch the virtual server, the boot process will take place in a few minutes.
Go to the newly created Instance, click Connect, select SSH Client and follow instructions for accessing the server:
- Paste the shell script commands just Create the above into the server's terminal, after running it will have the GitHub Action Runner service working as shown below:
- Reload Create Runner page, you will see 1 Server is in Idle state. So we have successfully configured the GitHub Action Runner service, now you can write CI/CD instructions through the workflows I mentioned in the steps above.
5. Install Nginx to point port 3000 to port 80:
- By default, the Next.JS project only works on port 3000, but what we need is that we don't need to enter port 3000 to still be able to access the website. So I will prepare the following combination of bash shell script commands to help you set up ngnix more easily.
#!/bin/bash
sudo apt update
sudo apt install nginx -y
sudo ufw allow 'Nginx HTTP'
sudo rm -r -f /etc/nginx/sites-enabled/default
sudo touch /etc/nginx/sites -enabled/default
sudo chmod -R 777 /etc/nginx/sites-enabled/default
cat << EOF > /etc/nginx/sites-enabled/default
# Cache zone
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone =STATIC:10m inactive=7d use_temp_path=off;
upstream nextjs_upstream {
server 127.0.0.1:3000;
# We could add additional servers here for load-balancing
}
server {
listen 80 default_server;
server_name _;
server_tokens off;
gzip on;
gzip_proxied any;
gzip_comp_level 4;
gzip_types text/css application/javascript image/svg+xml;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
# BUILT ASSETS (EG JS BUNDLES)
# Browser cache - max cache headers from Next.js as build id in url
# Server cache - valid forever (cleared after cache "inactive" period)
location /_next/static {
proxy_cache STATIC;
proxy_pass http://nextjs_upstream;
# For testing cache - remove before deploying to production
add_header X-Cache-Status \$upstream_cache_status;
}
# STATIC ASSETS (EG IMAGES)
# Browser cache - "no-cache" headers from Next.js as no build id in url
# Server cache - refresh regularly in case of changes
location /static {
proxy_cache STATIC;
proxy_ignore_headers Cache-Control;
proxy_cache_valid 60m;
proxy_pass http://nextjs_upstream;
# For testing cache - remove before deploying to production
add_header X-Cache-Status \$upstream_cache_status;
}
location / {
proxy_pass http://nextjs_upstream;
}
}
EOF
sudo chmod -R 700 /etc/nginx/sites-enabled/default
sudo systemctl stop nginx
sudo systemctl start nginx
6. CI/CD
Capability Test - To test GitHub's CI/CD feature Action, go to “pages/index” edit any title you want, and push the code to the main branch
- The code build process will take place and when it's done, the site will automatically update to your new code. - Wish you success
- This is the process of building web app.
- And here is the result