MERN Stack with Kubernetes

In this article, I will cover how you can setup MERN stack application on Kubernetes.
Prerequisites
It is assumed that you have an understanding of the following tools/concepts and have them installed on your system:
- Docker
- Minikube
- NodeJS
Introduction
The purpose of this article is to familiarize you with the deployment process of MERN stack on Kubernetes. We have minimal requirements on our side:
- Deployment of the server (NodeJS)
- Deployment of the client (ReactJS)
- Initiation of services (MongoDB)
In addition to that, we will get hands-on experience to:
- Inspect status of the deployments, pods, services.
- Start/Stop the deployments, pods, services whenever we need to.
- Inspect the logs and descriptions of individual deployments, pods, and services.
Lets Dive In Coding
We start by creating our base-directory mern-stack.
Within that directory, we will create the following files and directories:-
- Client/Dockerfile
- Server/Dockerfile
- server-deployment.yaml
- client-deployment.yaml
For simplicity, I created 2 folders for separation of concern, Client folder includes the React app as front-end, while Server folder includes the NodeJS app as back-end. As we need two different docker images for the Kubernetes deployment, Client and Server folders, each would have their own Dockerfile. Having docker images to be ready, is a precursor to the deployment of Kubernetes. In addition to that, server-deployment.yaml is used to build deployment for NodeJS app (back-end) on Kubernetes, while client-deployment.yaml is used for ReactJS app (front-end) on Kubernetes.
Now let’s start coding, paste the following lines in Client/Dockerfile to dockerize the front-end of the app.
WORKDIR /usr/src/app/client
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
We have our file ready to build the docker image, now move on to paste the following lines in Server/Dockerfile to dockerize the back-end.
WORKDIR /usr/src/app/server
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3010
CMD ["npm", "start"]
We have both front-end and back-end docker files ready. Now let’s move on to the Kubernetes setup files.
Now paste the following lines in server-deployment.yaml placed in the root directory.
kind: Deployment
metadata:
name: mongo
spec:
selector:
matchLabels:
app: mern-stack-app-server
replicas: 1
template:
metadata:
labels:
app: mern-stack-app-server
spec:
containers:
- name: mongo
image: mongo:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 27017
volumeMounts:
- name: data
mountPath: /data
readOnly: false
volumes:
- name: data
persistentVolumeClaim:
claimName: mongo-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-data
labels:
app: mern-stack-app-server
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app: mern-stack-app-server
spec:
ports:
- name: mongo
port: 27017
targetPort: 27017
type: NodePort
selector:
app: mern-stack-app-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mern-stack-app-server
spec:
selector:
matchLabels:
app: mern-stack-app-server
replicas: 1
template:
metadata:
labels:
app: mern-stack-app-server
spec:
containers:
- name: mern-stack-app-server
image: mern-stack-app-server:1.0.0
imagePullPolicy: Never
ports:
- containerPort: 3010
volumeMounts:
- name: data
mountPath: /data
readOnly: false
volumes:
- name: data
persistentVolumeClaim:
claimName: mongo-data
Above code, will create the following:-
- 1 deployment of Server app
- 1 deployment of MongoDB
- Persistent volume claim for MongoDB and attachment to server app for data persistence
- MongoDB service for MongoDB database communication with server app
Now, paste the following lines of code in client-deployment.yaml in the root directory.
kind: Deployment
metadata:
name: mern-stack-app-client
spec:
selector:
matchLabels:
app: mern-stack-app-client
replicas: 1
template:
metadata:
labels:
app: mern-stack-app-client
spec:
containers:
- name: mern-stack-app-client
image: mern-stack-app-client:1.0.0
imagePullPolicy: Never
ports:
- containerPort: 3000
Above mentioned code, will create the client-side deployment. This is all the coding files we need for Kubernetes deployment. Rest is just the commands for appropriate exposure of components to each other.
In the app, replace the mongo host in mongodb connection string, by mongo, like this:
const connection = "mongodb://mongo:27017/kubernetes-app"
Guide to Build for deployment on Kubernetes
Make sure you are in the root directory of your project. Run the following commands sequentially, in order to deploy on Kubernetes:
this will start the minikube cluster single node.
minikube start
this will make docker inside minikube accessible via cmd.
eval $(minikube docker-env)
build docker server-app image.
docker build -t mern-stack-app-server:1.0.0 ./server -f ./server/Dockerfile --no-cache
build docker client-app image.
docker build -t mern-stack-app-client:1.0.0 ./client -f ./client/Dockerfile --no-cache
deploy server-app on kubernetes using kubectl.
kubectl apply -f server-deployment.yaml
deploy client-app on kubernetes using kubectl.
kubectl apply -f client-deployment.yaml
get the server-app and client-app pod name, and expose it to localhost access.
kubectl get pods
kubectl port-forward <pod name here including 'mern-stack-app-server'> 32111:3010
kubectl port-forward <pod name here including 'mern-stack-app-client'> 32000:3000
This would make the server-app accessible via http://localhost:32111 and the client-app at http://localhost:32000.
Managing MERN Stack On Kubernetes
Now, as your app is up and running on Kubernetes cluster, you must know what and how to perform operations on the running app.
Inspecting Kubernetes Components
kubectl describe pods <pod_name>
kubectl describe deployments <deployment_name>
kubectl describe services <service_name>
kubectl describe pvc <pvc_name>
kubectl describe pv <pv_name>
Inspecting Logs
kubectl logs <pod_name>
kubectl logs <deployment_name>
kubectl logs <service_name>
In order to keep listening to logs, add -f after kubectl logs in the above commands.
Interact with the container inside Pod
kubectl exec -it <pod_name> -- /bin/bash
Stopping/Deleting Kubernetes Components
kubectl delete -f server-deployment.yaml
kubectl delete -f client-deployment.yaml
In conclusion, MERN Stack app can be easily deployed and configured on Kubernetes cluster, if the right procedure and technique is followed, as mentioned in this article.