Docker Best Practices for Production

Docker Best Practices for Production
Docker has revolutionized how we build, ship, and run applications. However, moving from development to production requires following specific best practices to ensure security, performance, and maintainability.
1. Use Official Base Images
Always start with official base images from Docker Hub when possible:
# Good
FROM node:18-alpine
# Avoid
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nodejs npm
Official images are regularly updated, security-patched, and optimized.
2. Minimize Image Layers
Each instruction in a Dockerfile creates a new layer. Combine commands to reduce layers:
# Good
RUN apt-get update && \
apt-get install -y curl wget && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Avoid
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN apt-get clean
3. Use Multi-Stage Builds
Multi-stage builds help create smaller production images:
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
4. Don't Run as Root
Create and use a non-root user:
FROM node:18-alpine
# Create app user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Set ownership and switch user
COPY --chown=nextjs:nodejs . .
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]
5. Use .dockerignore
Create a .dockerignore
file to exclude unnecessary files:
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.cache
6. Set Resource Limits
Always set memory and CPU limits:
docker run -d \
--memory="512m" \
--cpus="0.5" \
--name myapp \
myapp:latest
7. Use Health Checks
Implement health checks for better container management:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
8. Scan for Vulnerabilities
Regularly scan your images for security vulnerabilities:
# Using Docker Scout
docker scout cves myapp:latest
# Using Trivy
trivy image myapp:latest
9. Use Specific Tags
Avoid using latest
tags in production:
# Good
FROM node:18.17.0-alpine
# Avoid
FROM node:latest
10. Optimize for Caching
Order your Dockerfile instructions from least to most frequently changing:
FROM node:18-alpine
# Copy package files first (changes less frequently)
COPY package*.json ./
RUN npm ci --only=production
# Copy source code last (changes more frequently)
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Conclusion
Following these Docker best practices will help you build more secure, efficient, and maintainable containerized applications. Remember that containerization is just one part of your DevOps pipeline – combine these practices with proper CI/CD, monitoring, and infrastructure management for the best results.
What Docker practices have you found most valuable in your projects? Let me know in the comments!