This guide will walk you through a simple CI/CD approach for deploying react web applications to Azure Cloud
Prerequisites
- Azure Account
- GitHub Account
- A React Application
We will be using GitHub Actions as our CI/CD platform to deploy, Docker to containerize our application, and Kubernetes
Why Docker?
Docker is a tool designed to make it easier for developers to develop, ship, and run applications by using containers. We are going to create a Dockerfile
with an Nginx image which will help us in serving the built project through a built server.
Why Kubernetes?
Kubernetes allows you to run your Docker containers and workloads and helps you to tackle some of the operating complexities.
Create Nginx Config
Create a file named nginx.conf
in the root folder of your project
This file will contain all the necessary information for Nginx to serve the index.html
present in the build
folder and takeyarn care of 404
s if a user visits a route that doesn't exist.
Note: If you have an SSL Certificate and you want to serve your website through HTTPS you need to add a block of code to redirect code from port 80
to 443
and serve the HTML file through that. You can read more about it here.
server {
listen 80;
listen [::]:80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
Create a Dockerfile
Create an empty file named Dockerfile
at the root of your project
This Dockerfile will use the Nginx configuration we created in the previous step and use the copy the HTML from the build directory to the Nginx directory, which will help in serving the site.
FROM node:14.17.0-alpine AS builder
# Directory
WORKDIR /app
COPY . .
FROM nginx:stable-alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY --from=builder /app/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Kubernetes Configuration
You can create a deployment.yaml
file with the necessary information to deploy your Docker Image
apiVersion: v1
kind: Pod
metadata:
name: react-project
labels:
app: web
spec:
containers:
- name: react-project
image: nginx
ports:
- containerPort: 80
Create the actions file
Create an empty directory named .github
and create a file named actions.yaml
inside it.
This file will help us with the step-by-step process of deploying our code to the server whenever a commit is pushed or a branch gets merged to the main
branch.
Following is a simple diagram of content present in the actions.yml
file.
You can read about creating an Azure Container Registry here and creating an Azure Kubernetes Cluster here
The basic setup of GitHub Actions to execute npm install
and npm run build
when any branch gets merged to the main
branch
name: react-project
on:
push:
branches: [main]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v2
with:
node-version: 16.x
- run: npm install
- name: Creates a build directory
run: npm run build
env:
# Any environment variables used in the project
Installing Azure CLI and configuring Azure credentials is the next step to make sure we can push the created Docker Image
- name: Install Azure cli
run: |
sudo apt-get install ca-certificates curl apt-transport-https lsb-release gnupg
curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
AZ_REPO=$(lsb_release -cs)
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
sudo apt-get update
sudo apt-get install azure-cli
- name: Configure Azure credentials
uses: azure/actions/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
You may notice that we are using a few secret variables here and there in the file, you can read about creating them here
Logging to Azure Container Registry and pushing the Docker Image to the registry
- name: Log into the registry
uses: docker/login-action@v1
with:
registry: ${{ secrets.AZURE_ACR_ENDPOINT }}
username: ${{ secrets.AZURE_ACR_USERNAME }}
password: ${{ secrets.AZURE_ACR_PASSWORD }}
- name: Build, tag, and push the image to Azure Container Registry
run: |
docker build -t react-project .
docker tag react-project:latest ${{secrets.AZURE_ACR_ENDPOINT}}/react-project:latest
docker tag react-project:latest ${{secrets.AZURE_ACR_ENDPOINT}}/react-project:${IMAGE_TAG}
docker push ${{secrets.AZURE_ACR_ENDPOINT}}/react-project:latest
docker push ${{secrets.AZURE_ACR_ENDPOINT}}/react-project:${IMAGE_TAG}
env:
IMAGE_TAG: ${{ github.sha }}
To get to know about retrieving your Azure Credentials, please refer here
${{ github.sha }}
helps in creating a unique hash string to differentiate between images pushed before.
Deploy the Docker Image to Kubernetes Cluster and verify if it's deployed
- name: Deploy to cluster
uses: steebchen/kubectl@v2.0.0
with: # defaults to latest kubectl binary version
version: v1.22.0
config: ${{ secrets.KUBE_CONFIGURATION }}
command: rollout restart react-project
- name: Verify the deployment
uses: steebchen/kubectl@v2.0.0
with:
config: ${{ secrets.KUBE_CONFIGURATION }}
version: v1.22.0 # specify kubectl binary version explicitly
command: rollout status react-project
Now that you have verified the deployment, after merging your code to the main branch all the code will be deployed to your server directly.