MERN Stack with Kubernetes
In this article, I will cover how you can setup MERN stack application on Kubernetes.
It is assumed that you have an understanding of the following tools/concepts and have them installed on your system:
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:-
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.
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
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>
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.