How to Deploy React.js and Node.js Dockerized Containers to a Kubernetes Cluster

Prerequisites
- Text Editor
- Node.JS
- Docker Desktop
Creating the Node.JS Applciation
Step 1: Create a project working directory named react-node-app and open it with VS Code.
In the project working directory, create a new folder named backend and cd into the created folder. This folder will contain all the code and dependencies for the Express server.
Step 2: Initialize the Node.js application as follows:
npm init -ynpm init -yThe command will initialize the Node.js application and generate the package.json file. Next, let’s install all the dependencies required to run the Node.js application:
npm i express
npm i -g nodemonnpm i express
npm i -g nodemonThe command will install express and nodemon. We will use the express to create the back-end server.
We will use nodemon to monitor the Node.js application scripts and detect any changes. When any changes are detected, it automatically restarts the Node.js application during development.
"dev": "nodemon -L app.js""dev": "nodemon -L app.js"Step 4: In the backend folder, create a new file named app.js
Step 5: Add the following code in the app.js:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.get('/', (req, res) => {
res.json([
{
"id":"1",
"title":"Movie Review: The Perk of Being a Wallflower"
},
{
"id":"2",
"title":"Game Review: Need for Speed"
},
{
"id":"3",
"title":"Show Review: Looking for Alaska"
}
])
})
app.listen(4000, () => {
console.log('listening for requests on port 4000')
})const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.get('/', (req, res) => {
res.json([
{
"id":"1",
"title":"Movie Review: The Perk of Being a Wallflower"
},
{
"id":"2",
"title":"Game Review: Need for Speed"
},
{
"id":"3",
"title":"Show Review: Looking for Alaska"
}
])
})
app.listen(4000, () => {
console.log('listening for requests on port 4000')
})The code above will create an Express get route. The backend will be listening for requests on port 4000. Let’s run the Node.js application.
Running the Node.js Application
To run the Node.js application, use the following command:
npm run devnpm run devCreating the React.js Application
To create the React.js application, apply the following steps below:
Step 1: While in the project working directory, run the following command to create a React.js application
npx create-react-app frontendnpx create-react-app frontendThe command will create a new folder named frontend in the project working directory. Now, cd into the frontend folder.
Step 2: In the src folder, open the App.js file, delete everything from it and paste the following code:
import { useEffect, useState } from 'react'
import './App.css';
function App() {
const [blogs, setBlogs] = useState([])
useEffect(() => {
fetch('http://localhost:4000/')
.then(res => res.json())
.then(data => setBlogs(data))
}, [])
return (
<div className="App">
<header className="App-header">
<h1>all blogs</h1>
{blogs && blogs.map(blog => (
<div key={blog.id}>{blog.title}</div>
))}
</header>
</div>
);
}
export default App;import { useEffect, useState } from 'react'
import './App.css';
function App() {
const [blogs, setBlogs] = useState([])
useEffect(() => {
fetch('http://localhost:4000/')
.then(res => res.json())
.then(data => setBlogs(data))
}, [])
return (
<div className="App">
<header className="App-header">
<h1>all blogs</h1>
{blogs && blogs.map(blog => (
<div key={blog.id}>{blog.title}</div>
))}
</header>
</div>
);
}
export default App;The code will create a simple react application that will make API requests to the Express server. It will fetch the results from http://localhost:4000/ where our backend is running.
Running the React.js Application
Before you run the React.js application, ensure the Node.js application is running on http://localhost:4000/. To run the React.js application, run the following code:
npm startnpm startThe command will start our application. We can access it on http://localhost:3000/.
We have connected the two applications, and the front end can now communicate with the back end. Let’s now containerize the two applications using Docker.
Containerizing the Node.js Application
To containerize the Node.js using Docker, follow the steps below:
Step 1: Create a file named Dockerfile in the backend folder
The Dockerfile will have the commands required to build a Docker image for the Node.js application. Add the following code in the created Dockerfile:
# Requires node:18-alpine as the base image for Dockerizing the Node.js application
FROM node:18-alpine
# It installs the nodemon package for monitoring the Express server
RUN npm install -g nodemon
# Creating the working directory
WORKDIR /app
# Copying the dependencies in the package.json file
COPY package.json .
#Installing all the dependencies
RUN npm install
#Copying all the files to the working directory
COPY . .
#Container will run on this port
EXPOSE 4000
#Command to start the Docker container Node.js application
CMD ["npm", "run", "dev"]# Requires node:18-alpine as the base image for Dockerizing the Node.js application
FROM node:18-alpine
# It installs the nodemon package for monitoring the Express server
RUN npm install -g nodemon
# Creating the working directory
WORKDIR /app
# Copying the dependencies in the package.json file
COPY package.json .
#Installing all the dependencies
RUN npm install
#Copying all the files to the working directory
COPY . .
#Container will run on this port
EXPOSE 4000
#Command to start the Docker container Node.js application
CMD ["npm", "run", "dev"]Step 2: Building the Docker image
To build the Docker image for the Node.js application, first cd into the backend folder. You will then run the following command:
docker build -t <docker-username>/node-js .docker build -t <docker-username>/node-js .The command will build the Docker image.
Pushing the Node.js Docker Image to Docker Hub
To push the Docker image to Docker Hub, run the following command:
docker push <docker-username>/node-jsdocker push <docker-username>/node-jsStarting the Containerized Node.js Application
To start the containerized Node.js application, run the following command:
docker run -p 4000:4000 <docker-username>/node-jsdocker run -p 4000:4000 <docker-username>/node-jsWe can also access the containerized Node.js application on http://localhost:4000/.
Containerizing the React.js Application
To containerize the React.js using Docker, follow the steps below:
Step 1: Create a file Dockerfile in the frontend folder and add the following code in the created Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]FROM node:18-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]Step 2: Building the Docker image
To build the Docker image for the React.js application, first cd into the frontend folder. You will then run the following command:
docker build -t <docker-username>/react-js .docker build -t <docker-username>/react-js .The command will build the Docker image.
Pushing the React.js Docker Image to Docker Hub
To push the Docker image to Docker Hub, run the following command:
docker push <docker-username>/react-jsdocker push <docker-username>/react-jsStarting the Containerized React.js Application
Before you run the containerized React.js application, ensure the containerized Node.js application is running on http://localhost:4000/. To start the containerized React.js application, run the following command:
docker run -p 3000:3000 <docker-username>/react-jsdocker run -p 3000:3000 <docker-username>/react-jsThe command will start the containerized React.js application. We can also access the containerized React.js application on http://localhost:3000/
Our containerized React.js application is also running and connected to the back end. Let’s now deploy the two containerized applications to the Kubernetes Cluster.
Creating the Kubernetes Cluster
We will create and run Kubernetes Cluster locally using Minikube. We will deploy the two containerized applications to the Minikube Kubernetes Cluster. Minikube comes together with Docker during the installation process. To check the installed Minikube version, run the following command:
minikube versionminikube versionMinikube depends on the Docker driver to run. To create and run a Kubernetes Cluster using Minikube, execute the following command:
minikube start --driver=dockerminikube start --driver=dockerDeploying the Containerized applications to the Minikube Kubernetes Cluster
We will deploy the containerized applications to the Minikube Kubernetes Cluster using the Kubernetes CLI. Kubernetes CLI (kubectl) is a powerful command line interface tool that assists in the deployment of any containerized applications to a created Kubernetes Cluster. You can interact with the containerized applications using the kubectl commands and access their resources.
You need to install the Kubernetes CLI using the following command:
choco install kubernetes-cli
brew install kubernetes-clichoco install kubernetes-cli
brew install kubernetes-cliTo check the installed version, use the following command:
kubectl versionkubectl versionTo deploy the containerized applications, we need to create a node-js-deployment.yaml and react-js-deployment.yaml files. Kubernetes CLI will use these two files and deploy the two containerized applications.
Creating the node-js-deployment.yaml File
In the project working directory, create a file named node-js-deployment.yaml and paste the following code:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-js-deployment
spec:
replicas: 2
selector:
matchLabels:
app: node-js
template:
metadata:
labels:
app: node-js
spec:
containers:
- name: node-js
image: <docker-username>/node-js
resources:
limits:
memory: "356Mi"
cpu: "500m"
ports:
- containerPort: 4000
---
apiVersion: v1
kind: Service
metadata:
name: node-js-service
spec:
type: LoadBalancer
selector:
app: node-js
ports:
- port: 4000
targetPort: 4000
protocol: TCPapiVersion: apps/v1
kind: Deployment
metadata:
name: node-js-deployment
spec:
replicas: 2
selector:
matchLabels:
app: node-js
template:
metadata:
labels:
app: node-js
spec:
containers:
- name: node-js
image: <docker-username>/node-js
resources:
limits:
memory: "356Mi"
cpu: "500m"
ports:
- containerPort: 4000
---
apiVersion: v1
kind: Service
metadata:
name: node-js-service
spec:
type: LoadBalancer
selector:
app: node-js
ports:
- port: 4000
targetPort: 4000
protocol: TCPThe file consists of two parts: Deployment and Service.
Deployment: This part of the file specifies the number of application pods that will run after the deployment. Pods are multiple instances or replicas of the same containerized application. It also shows the port the container will be running and resource limits for each application pod. It also shows the Docker image that will create the containers during deployment. We will use
<docker-username>/node-jsimage from Docker Hub.Service: The service distributes the containerized application’s traffic to the running pods equally. Additionally, it exposes the running application to be accessed outside the Kubernetes cluster. Furthermore, the service assigns an External IP address to the containerized application. We can use it to access the application in a web browser.
Creating the react-js-deployment.yaml File
In the project working directory, create a file named react-js-deployment.yaml and paste the following code:
apiVersion: apps/v1
kind: Deployment
metadata:
name: react-js-deployment
spec:
replicas: 2
selector:
matchLabels:
app: react-js
template:
metadata:
labels:
app: react-js
spec:
containers:
- name: react-js
image: <docker-username>/react-js
resources:
limits:
memory: "356Mi"
cpu: "500m"
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: react-js-service
spec:
type: LoadBalancer
selector:
app: react-js
ports:
- protocol: TCP
port: 3000
targetPort: 3000apiVersion: apps/v1
kind: Deployment
metadata:
name: react-js-deployment
spec:
replicas: 2
selector:
matchLabels:
app: react-js
template:
metadata:
labels:
app: react-js
spec:
containers:
- name: react-js
image: <docker-username>/react-js
resources:
limits:
memory: "356Mi"
cpu: "500m"
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: react-js-service
spec:
type: LoadBalancer
selector:
app: react-js
ports:
- protocol: TCP
port: 3000
targetPort: 3000To deploy the two containerized applications to the Minikube Kubernetes cluster, apply the following commands:
kubectl apply -f node-js-deployment.yaml
kubectl apply -f react-js-deployment.yamlkubectl apply -f node-js-deployment.yaml
kubectl apply -f react-js-deployment.yamlTo see the deployments, run this command:
kubectl get deploymentskubectl get deploymentsGetting the containerised application pods
To get the running pods, run this command:
kubectl get podskubectl get podsGetting the containerized applications service
To get the containerized applications service run this command:
kubectl get servicekubectl get serviceWe have two application services described in the two .yaml files. The two services are running, but the EXTERNAL-IP is pending. We will expose the two services to access the applications outside the Kubernetes cluster in a web browser.
Exposing the two services
For Minikube to assign an EXTERNAL-IP and expose the two services, run these commands for each of the services:
node-js-service
minikube command node-js-serviceminikube command node-js-serviceThe code will expose the service and assign http://127.0.0.1:3215/ as the EXTERNAL-IP.
You can access the application in the web browser using http://127.0.0.1:3215/.
react-js-service
For the react-js-service, run the following command:
minikube service react-js-serviceminikube service react-js-serviceThe Minikube command will expose the service and assign http://127.0.0.1:2910 as the EXTERNAL-IP
Before you access the react-js-service, ensure the exposed node-js-service is still running in your browser. To access the react-js-service in the web browser, click on this URL http://127.0.0.1:2910:
Conclusion
In this tutorial, we have learned how to deploy React.js and Node.js Dockerized containers to a Kubernetes Cluster. We started with an Express backend server using Node.js. We then created a front-end web application using React.js and connected the two applications. After setting up the Node.js Express server and React.js web application, we then used Docker to containerize the two applications.
We created two stand-alone Docker containers, and we also created a Kubernetes Cluster that runs on our local machine using Minikube. We finally deployed the two containerized applications to the Kubernetes Cluster and accessed the application services. You can access the complete code here. Happy Deployment!