Introduction✨
Hello developers 👋, My name is Md taqui imam, i am a Full Stack web developer, today i will tell you "how you can deploy a MERN stack app in Kubernetes".
So let's start and don't forget to SUBSCRIBE Newsletter 📩 follow me in Github and Twitter .
Here's a short introduction about Kubernetes :
In today's world, most applications are built using microservices architectures and container technologies like Docker. Kubernetes has emerged as the defacto platform for orchestrating containers at scale across on-premise and cloud infrastructures.
In this detailed post, we will deploy a full-fledged MERN (MongoDB, Express, React, Node.js) stack application on Kubernetes. The MERN stack is one of the most popular techniques for building modern web apps, combining React for the frontend, Express for the API backend and MongoDB for data storage.
Kubernetes provides a powerful platform to run stateful and stateless containers, handle service discovery, load balancing, auto-scaling, upgrades and more - all with declarative configurations and minimal maintenance. Let's delve into setting up a development environment, deploying the services and exploring key Kubernetes concepts.
Setting Up the Development Environment
The first step is to install the necessary tools on your development machine:
Docker - Used to build container images for each component of our application. Docker simplifies packaging code and dependencies into portable images.
Kubectl - The Kubernetes command line client that allows us to interact with the Kubernetes API server and manage the cluster. We will use it to deploy and manage application resources.
Minikube - A tool that runs a single-node Kubernetes cluster locally for testing and development purposes. It provisions a Virtual Machine, installs Kubernetes and configures the control plane. This gives us an isolated test environment without the overhead of a full production cluster.
To install these, follow the documentation for your operating system. Once installed, we can initialize Minikube:
minikube start
This will provision a VM, download a Kubernetes version, configure RBAC and pods network etc. To verify it's running correctly:
kubectl cluster-info
The cluster API endpoint, Kubernetes master location and number of nodes should be displayed.
Now our development environment is set up to deploy containers and experiment with Kubernetes features on a local single-node cluster.
Containerizing the Application Components
The next step is building Docker images for each component of our MERN application - MongoDB, Express and React. We'll store these images in a Docker registry like Docker Hub for later deployment.
For MongoDB, create a Dockerfile that clones the latest code, sets up configuration and exposes the default port:
FROM mongo:latest
COPY mongod.conf /etc/mongod.conf
EXPOSE 27017
Build and tag the image:
docker build -t myuser/mongodb .
docker push myuser/mongodb
Similarly, create Dockerfiles and images for the Express API and React front-end services. The API Dockerfile would COPY the code and install dependencies before exposing the app port.
Now we have containerized the application components independently, along with any dependencies or configuration baked in. These images form the base units that Kubernetes will schedule and run as "pods".
Configuring Secrets and ConfigMaps
When deploying to Kubernetes, we need a secure and flexible way to inject configuration and credentials into containers at runtime. For this, Kubernetes supports Secrets and ConfigMaps.
Secrets hold sensitive data like passwords, keys or tokens in a base64 encoded format. ConfigMaps store non-sensitive configuration data like environment variables or properties files.
For our app, we will define:
A Secret for the MongoDB username and password
A ConfigMap for database URL, Node environment variables
The secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
stringData:
password: supersecurepass
The configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
MONGO_URI: mongodb://usr:pass@mongodb:27017/app
NODE_ENV: production
We can now apply these resources to Kubernetes:
kubectl apply -f secret.yaml
kubectl apply -f configmap.yaml
This securely stores sensitive values in etcd while exposing non-sensitive data to containers.
Deploying MongoDB
With container images and configurations ready, it's time to deploy MongoDB as a Kubernetes resource. We'll create a Deployment to launch replicated pods behind a Service for discovery.
The mongodb-deployment.yaml defines:
mongodb image from prepared Dockerfile
Pod spec with resources, ports and volumes
Pulls password from mongo-secret
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: myuser/mongodb
envFrom:
- secretRef:
name: mongo-secret
ports:
- containerPort: 27017
Next, a mongodb-service.yaml exposes port 27017 within the cluster:
apiVersion: v1
kind: Service
metadata:
name: mongodb
spec:
type: ClusterIP
ports:
- port: 27017
selector:
app: mongodb
Now apply both configs:
kubectl apply -f mongodb-deployment.yaml
kubectl apply -f mongodb-service.yaml
Kubernetes will create MongoDB pods and make them discoverable via DNS.
Deploying the Express API
Now for the Express backend API. Create an express-deployment.yaml:
Node.js image from prepared Dockerfile
Environment from app-config ConfigMap
Port 8080 exposed
apiVersion: apps/v1
kind: Deployment
metadata:
name: express
spec:
replicas: 1
selector:
matchLabels:
app: express
template:
metadata:
labels:
app: express
spec:
containers:
- name: express
image: myuser/express
envFrom:
- configMapRef:
name: app-config
ports:
- containerPort: 8080
An express-service.yaml exposes port 8080 externally:
apiVersion: v1
kind: Service
metadata:
name: express
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: express
Deploy both and the Express API is now available on port 30001!
Deploying the React Frontend
For the frontend, create a react-deployment.yaml:
React image from Dockerfile
Mount volumes for building
Port 80 exposed
apiVersion: apps/v1
kind: Deployment
metadata:
name: react
spec:
selector:
matchLabels:
app: react
template:
metadata:
labels:
app: react
spec:
containers:
- name: react
image: myuser/react
ports:
- containerPort: 80
A react-service.yaml exposes port 80 internally:
apiVersion: v1
kind: Service
metadata:
name: react
spec:
type: ClusterIP
ports:
- port: 80
selector:
app: react
Deploy and the React SPA is now being served from Kubernetes!
Accessing the Application
Now that all services are deployed, we can test the full MERN stack running on Kubernetes.
By default, the React service is only reachable within the cluster. We can port-forward it locally:
kubectl port-forward svc/react 8080:80
Now visit http://localhost:8080 to view the app.
The frontend makes API calls to the Express service endpoint, which connects to MongoDB. Even though components are split, Kubernetes handles discovery and routing requests between services.
This is just the beginning - Kubernetes unlocks many more advanced capabilities around auto-scaling, easy updates, reliability guarantees and more. We've learned the basics of deploying modern applications on Kubernetes using declarative configs.
In the future, areas to explore include service meshes, Helm charts for packaging configurations, ingress controllers, monitoring solutions and more to improve the experience of running containers at scale. Kubernetes is a powerful platform for developing and deploying distributed software.
Thankyou for reading my Blog post,
Subscribe Newletter 📩 For more👇
Follow me in Hashnode✅
Happy Coding 😊