Docker_best_practices
Chapter 10: Docker Best Practices
Section titled “Chapter 10: Docker Best Practices”This chapter covers best practices for building secure, efficient, and maintainable Docker images and containers.
Image Best Practices
Section titled “Image Best Practices”1. Use Specific Tags
Section titled “1. Use Specific Tags”# Bad - Using latestFROM node
# Good - Using specific versionFROM node:18-alpine
# Better - Pin to exact versionFROM node:18.17.0-alpine3.182. Use Minimal Base Images
Section titled “2. Use Minimal Base Images”┌─────────────────────────────────────────────────────────────────────────────┐│ Image Size Comparison │├─────────────────────────────────────────────────────────────────────────────┤│ ││ Image Size Reduction ││ ───────────────────────────────────────────────────────────────────── ││ ubuntu:22.04 ~77 MB (baseline) ││ ubuntu:22.04-slim ~29 MB 62% smaller ││ alpine:3.18 ~7 MB 91% smaller ││ ││ node:18 ~1 GB ││ node:18-alpine ~180 MB 82% smaller ││ │└─────────────────────────────────────────────────────────────────────────────┘3. Use Multi-stage Builds
Section titled “3. Use Multi-stage Builds”# Build stageFROM node:18 AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build
# Production stageFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesUSER nodeCMD ["node", "dist/index.js"]4. Order Instructions for Caching
Section titled “4. Order Instructions for Caching”# Bad - Cache invalidated on every changeCOPY . .RUN npm install
# Good - Cache-friendly orderCOPY package*.json ./RUN npm installCOPY . .5. Use .dockerignore
Section titled “5. Use .dockerignore”# Git.git.gitignore
# IDE.vscode.idea*.swp
# Dependenciesnode_modulesnpm-debug.log
# Build artifactsdistbuild
# Testscoverage*.test.js
# Documentation*.mddocs/
# Environment.env.env.localSecurity Best Practices
Section titled “Security Best Practices”1. Don’t Run as Root
Section titled “1. Don’t Run as Root”# Create non-root userRUN addgroup -g 1000 -S appgroup && \ adduser -u 1000 -S appuser -G appgroup
# Set ownershipCOPY --chown=appuser:appgroup . .
# Switch to userUSER appuser2. Use HEALTHCHECK
Section titled “2. Use HEALTHCHECK”# For web applicationsHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1
# For databasesHEALTHCHECK --interval=10s --timeout=5s --retries=5 \ CMD pg_isready -U postgres || exit 13. Scan for Vulnerabilities
Section titled “3. Scan for Vulnerabilities”# Use Docker Scoutdocker scout cves myimage:latest
# Use Trivytrivy image myimage:latest
# Use Clairdocker scan myimage:latest4. Use Secrets Properly
Section titled “4. Use Secrets Properly”# Build stage (bad - secrets in image)FROM nodeENV API_KEY=secret123
# Better - Use runtime secrets# Don't include secrets in the image# Pass secrets at runtime via:# - Docker secrets (Swarm)# - Kubernetes secrets# - Environment variables (external)5. Enable Docker Content Trust
Section titled “5. Enable Docker Content Trust”# Enable content trustexport DOCKER_CONTENT_TRUST=1
# Pull signed images onlydocker pull nginxImage Optimization
Section titled “Image Optimization”1. Minimize Layers
Section titled “1. Minimize Layers”# Bad - Multiple RUN layersRUN apt-get updateRUN apt-get install -y nginxRUN apt-get cleanRUN rm -rf /var/lib/apt/lists/*
# Good - Single RUN layerRUN apt-get update && \ apt-get install -y nginx && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*2. Combine Related Operations
Section titled “2. Combine Related Operations”# BadRUN wget https://example.com/file1.tarRUN tar xf file1.tarRUN rm file1.tar
# GoodRUN wget -q https://example.com/file1.tar && \ tar xf file1.tar && \ rm file1.tar3. Use Build Arguments for Flexibility
Section titled “3. Use Build Arguments for Flexibility”ARG VERSION=latestARG BUILD_DATE
# Use in buildLABEL version="${VERSION}"LABEL build-date="${BUILD_DATE}"Container Best Practices
Section titled “Container Best Practices”1. Use Read-Only Root Filesystem
Section titled “1. Use Read-Only Root Filesystem”docker run --read-only myapp2. Limit Capabilities
Section titled “2. Limit Capabilities”# Drop all capabilities, add only what's neededdocker run --cap-drop all --cap-add NET_BIND_SERVICE myapp3. Use tmpfs for Sensitive Data
Section titled “3. Use tmpfs for Sensitive Data”# Store sensitive data in memorydocker run --tmpfs /app/secrets:rw,size=10m myapp4. Set Resource Limits
Section titled “4. Set Resource Limits”docker run \ --memory 512m \ --memory-reservation 256m \ --cpus 1.0 \ --restart unless-stopped \ myappDevelopment vs Production
Section titled “Development vs Production”Development
Section titled “Development”services: app: build: . volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development ports: - "3000:3000"Production
Section titled “Production”services: app: build: . environment: - NODE_ENV=production restart: unless-stopped deploy: resources: limits: memory: 512M cpus: '0.5' healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3Monitoring and Logging
Section titled “Monitoring and Logging”1. Use json-file Logging Driver
Section titled “1. Use json-file Logging Driver”docker run \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ myapp2. Use Docker Stats
Section titled “2. Use Docker Stats”# Real-time statsdocker stats
# All containers with no streamingdocker stats --no-streamChecklist
Section titled “Checklist”┌─────────────────────────────────────────────────────────────────────────────┐│ Docker Best Practices Checklist │├─────────────────────────────────────────────────────────────────────────────┤│ ││ Images ││ □ Use specific version tags ││ □ Use minimal base images (Alpine) ││ □ Use multi-stage builds ││ □ Optimize layer caching ││ □ Add .dockerignore file ││ □ Scan for vulnerabilities ││ ││ Security ││ □ Don't run as root ││ □ Add health checks ││ □ Use read-only filesystem when possible ││ □ Limit container capabilities ││ □ Enable Docker Content Trust ││ ││ Operations ││ □ Set resource limits ││ □ Configure appropriate restart policy ││ □ Use proper logging configuration ││ □ Monitor container health ││ ││ Development/Production ││ □ Separate configurations ││ □ Use Docker Compose for orchestration ││ □ Implement proper secrets management ││ │└─────────────────────────────────────────────────────────────────────────────┘Summary
Section titled “Summary”In this chapter, you learned:
- Image optimization best practices
- Security best practices
- Container best practices
- Development vs production considerations
- Monitoring and logging
Docker Fundamentals Complete!
Section titled “Docker Fundamentals Complete!”You’ve completed the Docker Fundamentals section. Now let’s move to Kubernetes.