Source: Dev.to | Jan 23, 2026 (UTC)
Today I completed a full real-world DevOps deployment where I built, containerized, and deployed a Node.js application using Docker, Kubernetes, Minikube, Ingress, HTTPS, and RBAC, all running on AWS EC2.
This project helped me connect all core DevOps concepts into one working system.
🔧 Tech Stack Used
Node.js – Application layer
Docker (Multi-Stage Build) – Optimized container image
Docker Hub – Image registry
AWS EC2 (Linux) – Cloud infrastructure
Kubernetes (Minikube) – Container orchestration
kubectl – Cluster management
Kubernetes Deployment & Service
NodePort Service
Ingress Controller
HTTPS (TLS Certificates)
Docker Volumes & Networks
RBAC (Role & RoleBinding)
🧱 Step 1: Node.js Application
I started with a simple Node.js web application that serves a static page to confirm deployment status.
🐳 Step 2: Docker Multi-Stage Build
To keep the image lightweight and production-ready, I used a multi-stage Docker build:
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
FROM node:18-alpine
WORKDIR /app
COPY –from=build /app .
EXPOSE 3000
CMD [“node”, “app.js”]
Benefits:
Smaller image size
Faster deployments
Better security
📦 Step 3: Push Image to Docker Hub
docker build -t /devops-node .
docker login
docker push /devops-node
Now the image is accessible from anywhere, including Kubernetes.
☁️ Step 4: AWS EC2 Setup
Launched an EC2 Linux instance
Installed:
Docker
kubectl
Minikube
Ran Minikube inside EC2 to simulate a real Kubernetes environment
☸️ Step 5: Kubernetes Deployment
Created a Deployment with multiple replicas:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-deploy
spec:
replicas: 2
selector:
matchLabels:
app: node
template:
metadata:
labels:
app: node
spec:
containers:
– name: node
image: /devops-node
ports:
– containerPort: 3000
Applied using:
kubectl apply -f deployment.yaml
🌐 Step 6: Kubernetes Service (NodePort)
apiVersion: v1
kind: Service
metadata:
name: node-service
spec:
type: NodePort
selector:
app: node
ports:
- port: 80 targetPort: 3000
This exposed the app internally within the cluster.
🔀 Step 7: Ingress Controller
Enabled ingress in Minikube:
minikube addons enable ingress
Ingress configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: node-ingress
spec:
rules:
- host: devops.local http: paths:
- path: / pathType: Prefix backend: service: name: node-service port: number: 80
Mapped the domain in /etc/hosts:
devops.local
🔐 Step 8: HTTPS with TLS
Generated certificates:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout key.pem -out cert.pem
Created Kubernetes TLS secret:
kubectl create secret tls node-tls –cert=cert.pem –key=key.pem
Updated ingress with TLS configuration and re-applied it.
The site now runs on HTTPS.
📦 Step 9: Docker Volumes & Network
Created Docker volume for persistent data
Used Docker networks for container communication
Ensured clean separation of concerns
🔐 Step 10: RBAC Security
Created a Role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: devops-role
rules:
- apiGroups: [“”] resources: [“pods”] verbs: [“get”, “list”]
Bound it using RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: devops-binding
subjects:
- kind: User name: devops-user roleRef: kind: Role name: devops-role apiGroup: rbac.authorization.k8s.io
This ensured least-privilege access inside the cluster.
✅ Final Outcome
✔ Node.js app running on AWS EC2
✔ Docker multi-stage image pushed to Docker Hub
✔ Kubernetes Deployment & Service
✔ Ingress routing with HTTPS
✔ Persistent storage using volumes
✔ Secure access using RBAC
🎯 What I Learned
How real DevOps components connect end-to-end
Debugging Kubernetes ImagePullBackOff issues
Difference between NodePort, Service & Ingress
HTTPS using Kubernetes TLS secrets
Importance of RBAC in production clusters


Залишити відповідь