Kubernetes Deployment: Deploying ReactJS applications on the GKE

Niranjan Gawali
Globant
Published in
7 min readDec 14, 2023
Deploy ReactJS application on the GKE
Deploy ReactJS application on the GKE

This is the fourth blog in a comprehensive five-part series on Kubernetes deployments. The previous and remaining parts are outlined below.

We’ll deploy a ReactJS app on Google Kubernetes Engine (GKE) in Part IV of our Kubernetes Deployment series. Additionally, we’ll use the previously deployed NodeJS APIs from Part II in the application.

Before you begin, it’s recommended that you have a basic understanding of Docker and Kubernetes concepts. These include deployments, services, pods, secrets, config maps, and clusters. This understanding will help you follow the steps in this blog and understand each step’s importance.

GKE is a powerful platform for managing containerized apps. By deploying our ReactJS app on Kubernetes, we can harness the benefits of features such as automatic scaling, self-healing, and rolling updates. These features provide us with efficiency and resilience in managing our application.

To complete the steps in this blog, you must have a Google Cloud Platform (GCP) account. If you don’t already have one, you can create a free GCP account by following this link. GCP provides a free tier with $300 credits for 90 days. This account will grant you access to all the essential GCP services needed to follow the steps in the blog, which include creating and managing a GKE cluster, creating a service, and deploying a ReactJS app on the cluster.

Creating a Project, Cluster, and Namespace

In Part 1, we set up a GCP project, a GKE cluster, and a namespace to enhance the management of Kubernetes resources. To proceed with this tutorial, make sure you have completed the following steps:

  1. Create the GCP Project and enable the required APIs.
  2. Create the GKE cluster.
  3. Establish a namespace for resource management.
  4. Set up a folder for configuration management. Create a book-management-reactjs folder to store the configuration files for the ReactJS application.

After executing the above steps, you can use the following commands in the cloud shell to establish a connection with the cluster.

# To set the default project
gcloud config set project kubernetes-applications-demo


# To get the cluster credentials
gcloud container clusters get-credentials kubernetes-demo
--region asia-south1 --project kubernetes-applications-demo


# To set the default namespace
kubectl config set-context --current --namespace=development

ReactJS Application

In this blog, you can use any ReactJS application or the provided ReactJS application that already integrates with previously deployed NodeJS applications. Access it through this link.

This simple application allows you to create, list, edit, and delete books. If you want to run the application locally, follow the instructions mentioned in the Readme file.

Containerizing the Application with Docker

Let’s understand the configuration required to create the Docker images we use in the Kubernetes deployment. This Docker file is present in the root of book-management-app API project, which I shared earlier.

# React build creation
FROM node:latest as node
ARG REACT_APP_BASE_URL
ENV REACT_APP_BASE_URL=$REACT_APP_BASE_URL
WORKDIR /app
COPY . .
RUN npm i
RUN npm run build

# NGINX configuration
FROM nginx:alpine
COPY --from=node /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

This Dockerfile creates a Docker image for a React app with an NGINX server to serve the static files. Here is a breakdown of what each section of the Dockerfile does:

  1. FROM node:latest as node: This line specifies the base image to use for the first stage of the build, which is the creation of the React app. It uses the latest version of the Node.js image available.
  2. ARG REACT_APP_BASE_URL: This line declares an argument that can be passed to the Docker build command. In this case, it’s used to set the base URL for the React app.
  3. ENV REACT_APP_BASE_URL=$REACT_APP_BASE_URL: This line sets an environment variable using the value passed in the ARG statement. This environment variable is then used in the React app to set the base URL.
  4. WORKDIR /app: This line sets the working directory /app within the container.
  5. COPY . .: This line copies all the files in the current directory (where the Dockerfile is located) to the /app directory in the container.
  6. RUN npm i: This line runs the npm i command to install the dependencies for the React app.
  7. RUN npm run build: This line runs the npm run build command to build the React app.
  8. FROM nginx:alpine: This line specifies the base image for the second build stage, which is the NGINX server.
  9. COPY --from=node /app/build /usr/share/nginx/html: This line copies the built React app from the build’s first stage to the NGINX container’s directory.
  10. COPY nginx.conf /etc/nginx/conf.d/default.conf: This line copies the NGINX configuration file from the local directory to the /etc/nginx/conf.d/default.conf location in the container.
  11. EXPOSE 80: This line exposes port 80, the default HTTP traffic port.
  12. CMD ["nginx", "-g", "daemon off;"]: This line sets the command to run when the container starts. In this case, it starts the NGINX server and sets it to run in the foreground using the daemon off; command.

Now, let’s check the NGINX configuration file we will use while creating the Docker build.

server {
listen 80;
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
  • This configuration sets up a server block to serve a React app on port 80.
  • The root directory for static files is set to /usr/share/nginx/html.
  • The default index files are index.html and index.htm.
  • The location/ block handles all requests to the server root.
  • The try_files directive ensures that any requested URL is served the same index.html file.
  • Custom error pages for server errors are defined in the error_page and location = /50x.html part.

You can use the following commands to create the image and push it to the docker hub.

# To create image
docker build --build-arg REACT_APP_BASE_URL=<base-url> -t <username>/<image-name>:<tag> .

# To login wiht docker
docker login --username=<username> --email=<email>
Password:

# To push the image to the docker hub
docker push <username>/<image-name>:<tag>

If you want to create and test the image instance locally, please use the following command to create the instance locally.

docker run -p 80:80 -d <username>/<image-name>:<tag>

Creating your image is not mandatory, and you can use the following image of the same NodeJS application.

niranjang2/book-management-app:gke-react

Kubernetes Configuration

Now, let’s proceed toward creating Kubernetes configuration files that will be used to create the Kubernetes resources.

We are going to create the following configurations.

  • Deployment
  • Service

Deployment

Deployment is a declarative process for defining and managing the desired state of containerized applications, including Pods and ReplicaSets, with automatic configuration management. It allows you to describe the application’s life cycle, define the number of pods, and specify what images should be used to create a Pod. The Deployment Controller handles the update of resources defined in the deployment file. For more details about deployment, please refer to the following links.

Below is the complete deployment configuration file.

apiVersion: apps/v1
kind: Deployment
metadata:
name: book-mgmt-app-deploy
labels:
name: book-mgmt-app-deploy
app: book-management
namespace: development
spec:
replicas: 2
selector:
matchLabels:
name: book-mgmt-app-pod
app: book-management
template:
metadata:
name: book-mgmt-app-pod
labels:
name: book-mgmt-app-pod
app: book-management
spec:
containers:
- name: book-management-app-image
image: niranjang2/book-management-app:gke-react
ports:
- containerPort: 80

As we can see in the specifications section for the template, we can see the image.

niranjang2/book-management-api:gke-react

As stated earlier, you can use the provided image or create a new one.

Create a file named book-mgmt-app-deploy.yaml and execute the provided command to create the deployment.

kubectl create -f book-mgmt-app-deploy.yaml

Once the deployment is created, we can check its status using the following command or verify it using UI.

kubectl describe deployment book-mgmt-app-deploy -n development
GKE Deployment
GKE Deployment

Service:

A service is a way to expose applications deployed on one or more pods within a cluster. Three types of services are available: NodePort, LoadBalancer, and ClusterIP. The default service type is ClusterIP when no type is specified. We will use the LoadBalancer service to make the React application accessible to the outside world. For further details on services, please refer to this link.

Below is the configuration file.

apiVersion: v1
kind: Service
metadata:
name: book-mgmt-app-service
labels:
name: book-mgmt-app-service
app: book-management
namespace: development
spec:
type: LoadBalancer
selector:
name: book-mgmt-app-pod
app: book-management
ports:
- name: http
port: 80
targetPort: 80

Create the file book-mgmt-app-service.yamland use the following command to create the service file.

kubectl create -f book-mgmt-app-service.yaml.yaml

The created service can be verified using the following command, or the same can be verified using the UI.

kubectl describe service book-mgmt-app-service -n development
GKE Service
GKE Service

Once the service is exposed, we go to the exposed endpoint and see the below application.

Book Management Application
Book Management Application

Conclusion

The ReactJS app is deployed on the GKE cluster successfully. Access the source code on GitHub. Find the necessary Kubernetes files in the kubernetes folder. Please make the necessary modifications to the container image mentioned in the source file.

Using Docker and Kubernetes for deployment offers benefits like containerization and orchestration. Kubernetes helps scale and manage the app effectively. The included Kubernetes files simplify deployment on any cluster, ensuring scalability and performance.

The upcoming blog focuses on automating ReactJS app deployment to GKE using GitHub Actions. Share your comments and queries below.

Reference Links

--

--