After containerizing an application with Docker, the next logical step is deploying it on Kubernetes.
Kubernetes helps automate application deployment, scaling, networking, and management of containerized workloads. Instead of manually running containers, Kubernetes ensures your application remains available and can easily scale when needed.
In this guide, we’ll deploy a Docker image of a Node.js application on Kubernetes using a Deployment and a Service.
Prerequisites
Before starting, make sure you have:
- Docker installed
- Kubernetes cluster running (Docker Desktop Kubernetes, Minikube, Kind, EKS, etc.)
- kubectl configured
- A Docker image pushed to Docker Hub
In my case, the image was:
madhavnaks/node-app:latest
Enter fullscreen mode Exit fullscreen mode
Why Kubernetes?
Running a container using Docker is straightforward:
docker run -p 3000:3000 madhavnaks/node-app:latest
Enter fullscreen mode Exit fullscreen mode
However, in production environments we need much more than simply running a container.
Kubernetes provides:
- High availability
- Self-healing containers
- Load balancing
- Service discovery
- Horizontal scaling
- Rolling updates
This makes it the industry standard for container orchestration.
Understanding the Kubernetes Architecture for This Deployment
For this deployment, we’ll use two Kubernetes resources:
Deployment
A Deployment is responsible for:
- Creating Pods
- Maintaining desired replica count
- Recreating failed Pods automatically
- Managing updates and rollbacks
Service
A Service provides a stable network endpoint for Pods.
Since Pod IPs change frequently, Services allow applications and users to communicate reliably with Pods.
Deployment and Service Manifest
Create a file named:
app.yaml
Enter fullscreen mode Exit fullscreen mode
Add the following configuration:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 2
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: madhavnaks/node-app:latest
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: node-app
spec:
selector:
app: node-app
type: NodePort
ports:
- port: 123
targetPort: 3000
nodePort: 32000
Enter fullscreen mode Exit fullscreen mode
Understanding the Deployment Configuration
Replica Count
replicas: 2
Enter fullscreen mode Exit fullscreen mode
Kubernetes will maintain two running Pod instances of the application.
If one Pod crashes, Kubernetes automatically creates another one to maintain the desired state.
Docker Image
image: madhavnaks/node-app:latest
Enter fullscreen mode Exit fullscreen mode
Kubernetes pulls the image directly from Docker Hub and uses it to create containers.
Container Port
containerPort: 3000
Enter fullscreen mode Exit fullscreen mode
This specifies the port on which the Node.js application listens inside the container.
Understanding the Service Configuration
The Service exposes our Pods to network traffic.
Service Port
port: 123
Enter fullscreen mode Exit fullscreen mode
This is the port exposed by the Kubernetes Service inside the cluster.
Target Port
targetPort: 3000
Enter fullscreen mode Exit fullscreen mode
Traffic arriving at the Service is forwarded to port 3000 inside the container.
NodePort
nodePort: 32000
Enter fullscreen mode Exit fullscreen mode
This exposes the application outside the cluster.
Requests reaching:
<Node-IP>:32000
Enter fullscreen mode Exit fullscreen mode
are forwarded to:
Service Port β Target Port β Container
Enter fullscreen mode Exit fullscreen mode
which means:
32000 β 123 β 3000
Enter fullscreen mode Exit fullscreen mode
Deploying the Application
Apply the manifest:
kubectl apply -f complete.yaml
Enter fullscreen mode Exit fullscreen mode
Expected output:
deployment.apps/node-app created
service/node-app created
Enter fullscreen mode Exit fullscreen mode
Verify the Deployment
Check Deployments:
kubectl get deployments
Enter fullscreen mode Exit fullscreen mode
Example output:
NAME READY UP-TO-DATE AVAILABLE
node-app 2/2 2 2
Enter fullscreen mode Exit fullscreen mode
Check Pods:
kubectl get pods
Enter fullscreen mode Exit fullscreen mode
Example:
NAME READY STATUS
node-app-xxxxx 1/1 Running
node-app-yyyyy 1/1 Running
Enter fullscreen mode Exit fullscreen mode
Notice that Kubernetes created two Pods because we specified:
replicas: 2
Enter fullscreen mode Exit fullscreen mode
Check Services:
kubectl get svc
Enter fullscreen mode Exit fullscreen mode
Example:
NAME TYPE CLUSTER-IP PORT(S)
node-app NodePort 10.x.x.x 123:32000/TCP
Enter fullscreen mode Exit fullscreen mode
Accessing the Application
To access the application:
http://localhost:32000
Enter fullscreen mode Exit fullscreen mode
Or:
http://<Node-IP>:32000
Enter fullscreen mode Exit fullscreen mode
depending on your Kubernetes setup.
The request flow looks like:
User
β
βΌ
NodePort (32000)
β
βΌ
Service Port (123)
β
βΌ
Target Port (3000)
β
βΌ
Node.js Container
Enter fullscreen mode Exit fullscreen mode
Benefits of Using a Deployment
Deployments provide several production-grade capabilities:
Self-Healing
If a Pod crashes:
kubectl delete pod <pod-name>
Enter fullscreen mode Exit fullscreen mode
Kubernetes automatically creates a replacement Pod.
Scaling
Increase replicas easily:
replicas: 5
Enter fullscreen mode Exit fullscreen mode
Apply again:
kubectl apply -f complete.yaml
Enter fullscreen mode Exit fullscreen mode
Kubernetes creates additional Pods automatically.
Rolling Updates
When a new Docker image version is pushed:
image: madhavnaks/node-app:v2
Enter fullscreen mode Exit fullscreen mode
Applying the updated manifest performs a rolling update with minimal downtime.
Key Takeaways
β Deployments manage Pods automatically
β Replica count ensures high availability
β Services provide stable networking
β NodePort exposes applications outside the cluster
β Kubernetes continuously maintains the desired state of the application
Conclusion
Deploying a containerized application on Kubernetes is a major step toward building production-ready cloud-native applications.
Using a Deployment and Service, Kubernetes can automatically manage application availability, networking, scaling, and recovery without manual intervention.
Once you’re comfortable with these fundamentals, the next topics to explore are ConfigMaps, Secrets, Ingress, Persistent Volumes, and Helm Charts.
Happy Learning and Happy Kubernetes! π
λ΅κΈ λ¨κΈ°κΈ°