Docker Best Practices for Production

3 min read
Docker
Best Practices
Production
Security
Performance
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!

Back to Blog
Published on January 26, 2025