Introduction: Why Kubernetes for Node.js?
Modern JavaScript (Node.js) web applications require high availability, scalability, and fault tolerance. When your application grows beyond a single server, manual management becomes a nightmare. This is where Kubernetes (K8s) comes to the rescue — a container orchestration system that automates deployment, scaling, and management of applications.
In this guide, we will go through the complete journey: from a simple Node.js application to running it in a production-like environment on Kubernetes. You will learn how to package your code into a Docker image, create the necessary K8s resources (Pod, Deployment, Service), and configure external access.
1. Preparing the Node.js Application
First, let's create a simple Express application. It will respond to HTTP requests and display the container hostname (useful for checking load balancing).
1.1. File app.js
const express = require('express');const os = require('os');
const app = express();const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => { res.json({ message: 'Hello from Node.js on Kubernetes!', hostname: os.hostname(), timestamp: new Date().toISOString() });});
app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});1.2. File package.json
{ "name": "k8s-node-app", "version": "1.0.0", "dependencies": { "express": "^4.18.2" }, "scripts": { "start": "node app.js" }}2. Containerization: Docker Image
Kubernetes works with containers. Let's create a minimal Dockerfile for our Node.js application. We'll use the official Node.js image and multi-stage build to optimize size.
2.1. Dockerfile
FROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=production
FROM node:18-alpineWORKDIR /appCOPY --from=builder /app/node_modules ./node_modulesCOPY . .EXPOSE 3000CMD ["node", "app.js"]Build the image and push it to Docker Hub or another registry:
docker build -t your-dockerhub/k8s-node-app:v1 .docker push your-dockerhub/k8s-node-app:v13. Deploying to Kubernetes
Now let's move to the main part — creating Kubernetes resources. We will use Deployment (to manage Pods) and Service (for network access).
3.1. Creating a Deployment
A Deployment ensures that the desired number of Pods with your application are always running. Create a file deployment.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: node-app-deployment labels: app: node-appspec: replicas: 3 selector: matchLabels: app: node-app template: metadata: labels: app: node-app spec: containers: - name: node-app image: your-dockerhub/k8s-node-app:v1 ports: - containerPort: 3000 env: - name: PORT value: "3000" resources: requests: memory: "64Mi" cpu: "100m" limits: memory: "128Mi" cpu: "200m"3.2. Creating a Service
A Service provides a stable IP address and DNS name for accessing Pods. Create service.yaml:
apiVersion: v1kind: Servicemetadata: name: node-app-servicespec: selector: app: node-app ports: - protocol: TCP port: 80 targetPort: 3000 type: ClusterIP3.3. Running on the Cluster
Execute the commands (make sure you have kubectl configured and access to the cluster):
kubectl apply -f deployment.yamlkubectl app