$ -weight: 500;">kubectl version --client
-weight: 500;">kubectl cluster-info
-weight: 500;">kubectl version --client
-weight: 500;">kubectl cluster-info
-weight: 500;">kubectl version --client
-weight: 500;">kubectl cluster-info
-weight: 500;">curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/-weight: 500;">install.sh | bash
k3d cluster create dev-cluster
-weight: 500;">kubectl get nodes
-weight: 500;">curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/-weight: 500;">install.sh | bash
k3d cluster create dev-cluster
-weight: 500;">kubectl get nodes
-weight: 500;">curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/-weight: 500;">install.sh | bash
k3d cluster create dev-cluster
-weight: 500;">kubectl get nodes
# Stage 1: Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN -weight: 500;">npm ci --only=production # Stage 2: Production stage
FROM node:20-alpine
WORKDIR /app # Create non-root user
RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 # Copy dependencies from builder
COPY --from=builder /app/node_modules ./node_modules
COPY server.js ./ RUN chown -R nodejs:nodejs /app
USER nodejs EXPOSE 3000
CMD ["node", "server.js"]
# Stage 1: Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN -weight: 500;">npm ci --only=production # Stage 2: Production stage
FROM node:20-alpine
WORKDIR /app # Create non-root user
RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 # Copy dependencies from builder
COPY --from=builder /app/node_modules ./node_modules
COPY server.js ./ RUN chown -R nodejs:nodejs /app
USER nodejs EXPOSE 3000
CMD ["node", "server.js"]
# Stage 1: Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN -weight: 500;">npm ci --only=production # Stage 2: Production stage
FROM node:20-alpine
WORKDIR /app # Create non-root user
RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 # Copy dependencies from builder
COPY --from=builder /app/node_modules ./node_modules
COPY server.js ./ RUN chown -R nodejs:nodejs /app
USER nodejs EXPOSE 3000
CMD ["node", "server.js"]
node_modules
-weight: 500;">npm-debug.log
.-weight: 500;">git
.gitignore
README.md
.env
.DS_Store
*.md
node_modules
-weight: 500;">npm-debug.log
.-weight: 500;">git
.gitignore
README.md
.env
.DS_Store
*.md
node_modules
-weight: 500;">npm-debug.log
.-weight: 500;">git
.gitignore
README.md
.env
.DS_Store
*.md
-weight: 500;">docker build -t demo-app:v1 .
-weight: 500;">docker run -p 3000:3000 demo-app:v1
-weight: 500;">docker build -t demo-app:v1 .
-weight: 500;">docker run -p 3000:3000 demo-app:v1
-weight: 500;">docker build -t demo-app:v1 .
-weight: 500;">docker run -p 3000:3000 demo-app:v1
-weight: 500;">docker build -t your-username/demo-app:v1 .
-weight: 500;">docker login
-weight: 500;">docker push your-username/demo-app:v1
-weight: 500;">docker build -t your-username/demo-app:v1 .
-weight: 500;">docker login
-weight: 500;">docker push your-username/demo-app:v1
-weight: 500;">docker build -t your-username/demo-app:v1 .
-weight: 500;">docker login
-weight: 500;">docker push your-username/demo-app:v1
apiVersion: apps/v1
kind: Deployment
metadata: name: demo-app labels: app: demo-app
spec: replicas: 3 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: demo-app image: your-username/demo-app:v1 ports: - containerPort: 3000 env: - name: PORT value: "3000" - name: NODE_ENV value: "production"
apiVersion: apps/v1
kind: Deployment
metadata: name: demo-app labels: app: demo-app
spec: replicas: 3 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: demo-app image: your-username/demo-app:v1 ports: - containerPort: 3000 env: - name: PORT value: "3000" - name: NODE_ENV value: "production"
apiVersion: apps/v1
kind: Deployment
metadata: name: demo-app labels: app: demo-app
spec: replicas: 3 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: demo-app image: your-username/demo-app:v1 ports: - containerPort: 3000 env: - name: PORT value: "3000" - name: NODE_ENV value: "production"
apiVersion: v1
kind: Service
metadata: name: demo-app--weight: 500;">service
spec: selector: app: demo-app ports: - protocol: TCP port: 80 targetPort: 3000 type: LoadBalancer
apiVersion: v1
kind: Service
metadata: name: demo-app--weight: 500;">service
spec: selector: app: demo-app ports: - protocol: TCP port: 80 targetPort: 3000 type: LoadBalancer
apiVersion: v1
kind: Service
metadata: name: demo-app--weight: 500;">service
spec: selector: app: demo-app ports: - protocol: TCP port: 80 targetPort: 3000 type: LoadBalancer
-weight: 500;">kubectl apply -f k8s/deployment.yaml
-weight: 500;">kubectl apply -f k8s/-weight: 500;">service.yaml -weight: 500;">kubectl get pods
-weight: 500;">kubectl get deployment demo-app
-weight: 500;">kubectl get -weight: 500;">service demo-app--weight: 500;">service
-weight: 500;">kubectl apply -f k8s/deployment.yaml
-weight: 500;">kubectl apply -f k8s/-weight: 500;">service.yaml -weight: 500;">kubectl get pods
-weight: 500;">kubectl get deployment demo-app
-weight: 500;">kubectl get -weight: 500;">service demo-app--weight: 500;">service
-weight: 500;">kubectl apply -f k8s/deployment.yaml
-weight: 500;">kubectl apply -f k8s/-weight: 500;">service.yaml -weight: 500;">kubectl get pods
-weight: 500;">kubectl get deployment demo-app
-weight: 500;">kubectl get -weight: 500;">service demo-app--weight: 500;">service
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5
livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5
livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5
app.get('/health', (req, res) => res.json({ -weight: 500;">status: 'healthy' })); app.get('/ready', (req, res) => { if (databaseConnected) { res.json({ -weight: 500;">status: 'ready' }); } else { res.-weight: 500;">status(503).json({ -weight: 500;">status: 'not ready' }); }
});
app.get('/health', (req, res) => res.json({ -weight: 500;">status: 'healthy' })); app.get('/ready', (req, res) => { if (databaseConnected) { res.json({ -weight: 500;">status: 'ready' }); } else { res.-weight: 500;">status(503).json({ -weight: 500;">status: 'not ready' }); }
});
app.get('/health', (req, res) => res.json({ -weight: 500;">status: 'healthy' })); app.get('/ready', (req, res) => { if (databaseConnected) { res.json({ -weight: 500;">status: 'ready' }); } else { res.-weight: 500;">status(503).json({ -weight: 500;">status: 'not ready' }); }
});
apiVersion: v1
kind: ConfigMap
metadata: name: demo-app-config
data: PORT: "3000" NODE_ENV: "production" LOG_LEVEL: "info"
apiVersion: v1
kind: ConfigMap
metadata: name: demo-app-config
data: PORT: "3000" NODE_ENV: "production" LOG_LEVEL: "info"
apiVersion: v1
kind: ConfigMap
metadata: name: demo-app-config
data: PORT: "3000" NODE_ENV: "production" LOG_LEVEL: "info"
envFrom:
- configMapRef: name: demo-app-config
envFrom:
- configMapRef: name: demo-app-config
envFrom:
- configMapRef: name: demo-app-config
-weight: 500;">kubectl create secret generic demo-app-secrets \ --from-literal=DB_PASSWORD=supersecret
-weight: 500;">kubectl create secret generic demo-app-secrets \ --from-literal=DB_PASSWORD=supersecret
-weight: 500;">kubectl create secret generic demo-app-secrets \ --from-literal=DB_PASSWORD=supersecret
envFrom:
- secretRef: name: demo-app-secrets
envFrom:
- secretRef: name: demo-app-secrets
envFrom:
- secretRef: name: demo-app-secrets
strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1
strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1
strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1
-weight: 500;">kubectl rollout undo deployment/demo-app
-weight: 500;">kubectl rollout history deployment/demo-app
-weight: 500;">kubectl rollout undo deployment/demo-app
-weight: 500;">kubectl rollout history deployment/demo-app
-weight: 500;">kubectl rollout undo deployment/demo-app
-weight: 500;">kubectl rollout history deployment/demo-app
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: name: demo-app-hpa
spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: demo-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: name: demo-app-hpa
spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: demo-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: name: demo-app-hpa
spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: demo-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
-weight: 500;">brew -weight: 500;">install kompose # macOS
# Linux: download from GitHub releases
kompose convert
-weight: 500;">brew -weight: 500;">install kompose # macOS
# Linux: download from GitHub releases
kompose convert
-weight: 500;">brew -weight: 500;">install kompose # macOS
# Linux: download from GitHub releases
kompose convert
version: '3.8'
services: app: build: . ports: - "3000:3000" environment: - PORT=3000 - NODE_ENV=production -weight: 500;">restart: unless-stopped redis: image: redis:7-alpine ports: - "6379:6379" -weight: 500;">restart: unless-stopped
version: '3.8'
services: app: build: . ports: - "3000:3000" environment: - PORT=3000 - NODE_ENV=production -weight: 500;">restart: unless-stopped redis: image: redis:7-alpine ports: - "6379:6379" -weight: 500;">restart: unless-stopped
version: '3.8'
services: app: build: . ports: - "3000:3000" environment: - PORT=3000 - NODE_ENV=production -weight: 500;">restart: unless-stopped redis: image: redis:7-alpine ports: - "6379:6379" -weight: 500;">restart: unless-stopped
-weight: 500;">kubectl get pods
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
-weight: 500;">kubectl logs -l app=demo-app
-weight: 500;">kubectl exec -it <pod-name> -- /bin/sh
-weight: 500;">kubectl port-forward pod/<pod-name> 3000:3000
-weight: 500;">kubectl get pods
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
-weight: 500;">kubectl logs -l app=demo-app
-weight: 500;">kubectl exec -it <pod-name> -- /bin/sh
-weight: 500;">kubectl port-forward pod/<pod-name> 3000:3000
-weight: 500;">kubectl get pods
-weight: 500;">kubectl describe pod <pod-name>
-weight: 500;">kubectl logs <pod-name>
-weight: 500;">kubectl logs -f <pod-name>
-weight: 500;">kubectl logs -l app=demo-app
-weight: 500;">kubectl exec -it <pod-name> -- /bin/sh
-weight: 500;">kubectl port-forward pod/<pod-name> 3000:3000 - Container runtime (Docker, containerd): Runs individual containers on a single machine
- Orchestration platform (Kubernetes): Manages containers across multiple machines - Install Docker Desktop
- Open Docker Desktop → Settings → Kubernetes → Enable Kubernetes
- Wait a few minutes for the cluster to -weight: 500;">start - You need high availability across multiple servers
- You're scaling horizontally
- You want zero-downtime deployments
- Multiple developers deploy simultaneously - helm -weight: 500;">install prometheus prometheus-community/prometheus
- helm -weight: 500;">install grafana grafana/grafana
- Configure Prometheus as a Grafana data source
- Import the "Kubernetes Cluster Monitoring" dashboard - You're running on multiple servers and need workload distribution
- Downtime costs you money — you need automatic failover and rolling updates
- You're scaling a team — multiple developers deploying independently
- You need fine-grained resource control and autoscaling - Your app fits on one server
- You don't have time to learn Kubernetes properly
- You're optimizing for simplicity over resilience