TL;DR
Docker containerizes applications, ensuring consistent environments from development to production. It facilitates deployment, scaling and infrastructure management. Here's how to use Docker in 2026.
Who is this for
- Developers wanting to standardize environments
- DevOps engineers managing infrastructure
- Companies planning to scale applications
Keywords (SEO)
docker, containerization, docker compose, kubernetes, container deployment
What is Docker?
Docker is a containerization platform:
- Isolated environments (containers)
- Consistency between environments
- Lightweight (vs virtual machines)
- Fast startup
Container vs VM:
- VM: full OS, slower, more resources
- Container: shared OS, faster, fewer resources
Benefits:
- "Works on my machine" → solved
- Faster deployments
- Easier scaling
- Better resource utilization
Docker Basics
Dockerfile
Basic example:
# Base image
FROM node:18-alpine
# Working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Start application
CMD ["npm", "start"]Build and Run
Build image:
docker build -t my-app:latest .Run container:
docker run -p 3000:3000 my-app:latestRun in background:
docker run -d -p 3000:3000 --name my-app my-app:latestDockerfile Best Practices
1. Multi-stage Builds
Reduce image size:
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]2. Layer Caching
Optimal order:
# 1. Dependencies (rarely change)
COPY package*.json ./
RUN npm ci
# 2. Application code (often changes)
COPY . .3. Use .dockerignore
.dockerignore:
node_modules
npm-debug.log
.git
.env
dist
*.md4. Minimal Base Images
Alpine Linux:
FROM node:18-alpine # ~5MB vs ~150MB for node:18Distroless (even smaller):
FROM gcr.io/distroless/nodejs18-debian115. Non-root User
Security:
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjsDocker Compose
Basic Configuration
docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
- redis
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:Running
Start all services:
docker-compose up -dLogs:
docker-compose logs -f appStop:
docker-compose downKubernetes
Basic Concepts
Pod:
- Smallest unit
- One or more containers
- Shared resources (network, storage)
Deployment:
- Manages Pod replicas
- Rolling updates
- Rollback
Service:
- Expose Pods as network
- Load balancing
- Service discovery
Basic Deployment
deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Service:
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancerApply:
kubectl apply -f deployment.yaml
kubectl apply -f service.yamlScaling
Horizontal Pod Autoscaler (HPA)
Automatic scaling:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70Manual Scaling
kubectl scale deployment my-app --replicas=5Monitoring and Logging
Health Checks
In Dockerfile:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1In Kubernetes:
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5Logging
Docker logs:
docker logs my-app
docker logs -f my-app # FollowKubernetes logs:
kubectl logs deployment/my-app
kubectl logs -f deployment/my-appSecurity Best Practices
1. Scan Images
docker scan my-app:latest2. Minimal Permissions
USER nonroot3. Secrets Management
Not in Dockerfile:
# ❌ Bad
ENV API_KEY=secret123Use secrets:
# Kubernetes
apiVersion: v1
kind: Secret
metadata:
name: api-secret
data:
api-key: <base64-encoded>4. Regular Updates
Update base images:
FROM node:18-alpine # Use latest versionCI/CD with Docker
GitHub Actions example:
- name: Build Docker image
run: docker build -t my-app:${{ github.sha }} .
- name: Push to registry
run: |
docker tag my-app:${{ github.sha }} my-registry/my-app:latest
docker push my-registry/my-app:latest
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/my-app app=my-registry/my-app:latestFAQ
Is Docker Needed for Small Projects?
Not always, but worth it. Facilitates deployment, ensures environment consistency and prepares for scaling.
Docker vs Kubernetes?
Docker: containerization of applications. Kubernetes: container orchestration (for larger systems).
How Often to Update Base Images?
Regularly (monthly). Use tools like Dependabot for automatic updates.
Want to Containerize Your Application?
About the author
We build fast websites, web/mobile apps, AI chatbots and hosting setups — with a focus on SEO and conversion.
Recommended links
From theory to production — Branchly, our hosting stack and shipped work.
