导航菜单

08 - Docker Production Best Practices

Docker Production Best Practices

In earlier tutorials, we covered Docker basics: concepts, commands, image building, data management, networking, and Docker Compose. These are enough for development, but production deployments require more: security, reliability, performance, and maintainability. This article shares Docker best practices for production.

Security best practices

1. Use minimal base images

Use minimal images like Alpine or Distroless to reduce the attack surface.

# Use Alpine as a base image
FROM alpine:3.14

# Or use an official lightweight image
FROM node:16-alpine

2. Do not run containers as root

Create a non-root user in the Dockerfile and run the app as that user.

# Create a non-root user
RUN addgroup -g 1000 appuser && \
    adduser -u 1000 -G appuser -s /bin/sh -D appuser

# Switch to that user
USER appuser

# Run the app
CMD ["node", "app.js"]

3. Scan images for vulnerabilities

Use tools like Trivy, Clair, or Docker Scout to scan images.

# Scan an image with Trivy
trivy image myapp:1.0

4. Use content trust and image signing

Enable Docker Content Trust to ensure only signed images run.

# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# Push a signed image
docker push myapp:1.0

5. Limit container resources

Restrict CPU, memory, and other resources to prevent DoS impact.

docker run -d \
  --name myapp \
  --memory="512m" \
  --memory-swap="512m" \
  --cpu-shares=512 \
  myapp:1.0

6. Use read-only filesystems

Set the container filesystem to read-only and mount volumes only where writes are needed.

docker run -d \
  --name myapp \
  --read-only \
  --tmpfs /tmp \
  -v logs:/app/logs \
  myapp:1.0

Monitoring and logging

1. Centralized log management

Use log drivers to send container logs to centralized systems like ELK, Graylog, or Fluentd.

# Use json-file with log rotation
docker run -d \
  --name myapp \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  myapp:1.0

# Or use the syslog driver
docker run -d \
  --name myapp \
  --log-driver syslog \
  --log-opt syslog-address=udp://logserver:514 \
  myapp:1.0

2. Container health checks

Add HEALTHCHECK in the Dockerfile or configure at runtime.

# HEALTHCHECK in Dockerfile
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost/health || exit 1
# HEALTHCHECK at runtime
docker run -d \
  --name myapp \
  --health-cmd="curl -f http://localhost/health || exit 1" \
  --health-interval=30s \
  --health-retries=3 \
  --health-timeout=3s \
  myapp:1.0

3. Use monitoring tools

Use Prometheus, Grafana, cAdvisor, etc., to monitor resource usage and performance.

# docker-compose.yml example with Prometheus and Grafana
version: '3'

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    depends_on:
      - prometheus

Performance optimization

1. Optimize image size

  • Use multi-stage builds
  • Combine RUN instructions to reduce layers
  • Clean unnecessary files and caches
# Multi-stage build example
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

2. Use volumes to improve I/O performance

For I/O-heavy apps, use volumes to boost performance.

docker run -d \
  --name db \
  -v db-data:/var/lib/postgresql/data \
  postgres:13

3. Set resource limits appropriately

Set CPU and memory limits according to app needs to avoid contention.

docker run -d \
  --name myapp \
  --cpus=2 \
  --memory=2g \
  myapp:1.0

High availability and scalability

1. Use an orchestrator

In production, use Kubernetes, Docker Swarm, or Nomad to manage containers.

# Initialize Docker Swarm
docker swarm init

# Deploy a service
docker service create \
  --name myapp \
  --replicas 3 \
  --publish 8080:80 \
  myapp:1.0

2. Service discovery and load balancing

Leverage built-in discovery and load balancing from orchestrators, or tools like Traefik/Nginx.

# docker-compose.yml example using Traefik as reverse proxy
version: '3'

services:
  traefik:
    image: traefik:v2.5
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  webapp:
    image: myapp:1.0
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`example.com`)"
      - "traefik.http.routers.webapp.entrypoints=web"

3. Auto scaling containers

Adjust replica counts based on load.

# Auto scaling in Docker Swarm
docker service update \
  --replicas-max 10 \
  --replicas-min 2 \
  myapp

Backup and disaster recovery

1. Regularly back up data volumes

# Back up a data volume
docker run --rm \
  -v db-data:/source \
  -v $(pwd):/backup \
  alpine \
  tar -czf /backup/db-backup-$(date +%Y%m%d).tar.gz -C /source .

2. Auto-restart containers

docker run -d \
  --name myapp \
  --restart unless-stopped \
  myapp:1.0

3. Multi-region deployments

Deploy across regions for high availability and disaster recovery.

CI/CD best practices

1. Automate build and test

Use CI/CD tools (Jenkins, GitHub Actions, GitLab CI) to build and test images automatically.

# GitHub Actions workflow example
name: Build and Test

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Build the Docker image
      run: docker build -t myapp:${{ github.sha }} .
    - name: Test the Docker image
      run: docker run --rm myapp:${{ github.sha }} npm test

2. Blue-green or canary releases

Use blue-green or canary strategies to reduce deployment risk.

# Blue-green deployment example (Docker Swarm)
# Deploy new version (green)
docker service create \
  --name myapp-green \
  --replicas 3 \
  myapp:2.0

# After validation, update routing
docker service update \
  --publish-add 8080:80 \
  myapp-green

# Remove old version (blue)
docker service rm myapp-blue

Summary

We covered Docker production best practices spanning security, monitoring, performance, high availability, and CI/CD. By following these guidelines you can build a more stable, secure, and efficient Docker environment. Choose strategies and tools based on your scenario. In the next tutorial, we’ll look at common Docker issues and troubleshooting techniques.

搜索