Containers have revolutionized how we build, ship, and run applications. Docker provides the packaging, while Kubernetes handles orchestration at scale. This guide covers everything from writing efficient Dockerfiles to deploying production-ready Kubernetes clusters.
Writing Production-Ready Dockerfiles
A well-optimized Dockerfile is crucial for fast builds and small images. Use multi-stage builds to separate build dependencies from runtime, leverage layer caching effectively, and always use specific base image tags instead of 'latest'.
dockerfile
# Multi-stage build for Node.js application
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files first for better layer caching
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# Copy source and build
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:20-alpine AS production
# Create non-root user for security
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
WORKDIR /app
# Copy only production files
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => r.statusCode === 200 ? process.exit(0) : process.exit(1))"
CMD ["node", "dist/server.js"]Kubernetes Deployment Basics
Kubernetes uses declarative configuration to manage containerized workloads. The key resources are Deployments (for stateless apps), Services (for networking), and ConfigMaps/Secrets (for configuration). Understanding these primitives is essential for any modern developer.
yaml
# kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myregistry/myapp:v1.2.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database-url78%Use K8s in production
60%Smaller images with multi-stage
99.9%Uptime with rolling updates
3xFaster deployments