Skip to main content
10 Docker Best Practices for Production-Ready Applications

10 Docker Best Practices for Production-Ready Applications

DevOpsDecember 17, 202512 min read1 views
DockerDevOpsContainersBest PracticesProductionSecurity
Share:

10 Docker Best Practices for Production-Ready Applications

Docker has revolutionized how we build and deploy applications. Here are 10 essential best practices to ensure your containers are production-ready.

1. Use Official Base Images

Always start with official images from Docker Hub.

# Good ✅ FROM node:20-alpine # Bad ❌ FROM some-random-user/node

Why? Official images are:

  • Regularly updated
  • Security patched
  • Well documented
  • Optimized for size

2. Minimize Layer Count

Each RUN, COPY, and ADD creates a new layer. Combine commands when possible.

# Good ✅ RUN apt-get update && apt-get install -y curl git && apt-get clean && rm -rf /var/lib/apt/lists/* # Bad ❌ RUN apt-get update RUN apt-get install -y curl RUN apt-get install -y git

3. Use .dockerignore

Prevent unnecessary files from bloating your image.

# .dockerignore node_modules npm-debug.log .git .env .DS_Store *.md dist coverage

4. Run as Non-Root User

Never run containers as root in production.

# Create user RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 # Switch to user USER nextjs # Run application CMD ["node", "server.js"]

5. Use Multi-Stage Builds

Reduce final image size dramatically.

# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:20-alpine AS runner WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules CMD ["node", "dist/server.js"]

6. Set Proper Health Checks

Enable automatic container health monitoring.

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 CMD node healthcheck.js || exit 1

7. Use Specific Image Tags

Never use 'latest' in production.

# Good ✅ FROM node:20.10.0-alpine3.18 # Bad ❌ FROM node:latest

8. Optimize Layer Caching

Place frequently changing files at the end.

# Copy package files first (rarely change) COPY package*.json ./ RUN npm ci # Copy source code last (changes frequently) COPY . . RUN npm run build

9. Set Resource Limits

Prevent containers from consuming all resources.

# docker-compose.yml services: app: image: myapp:1.0 deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M

10. Scan for Vulnerabilities

Regularly scan images for security issues.

# Using Docker Scout docker scout cves myapp:1.0 # Using Trivy trivy image myapp:1.0 # Using Snyk snyk container test myapp:1.0

Complete Example

Here's a production-ready Dockerfile incorporating all best practices:

# Multi-stage build FROM node:20.10.0-alpine3.18 AS builder # Set working directory WORKDIR /app # Copy package files COPY package*.json ./ # Install dependencies RUN npm ci --only=production && npm cache clean --force # Copy source COPY . . # Build application RUN npm run build # Production stage FROM node:20.10.0-alpine3.18 AS runner # Install dumb-init for proper signal handling RUN apk add --no-cache dumb-init # Create non-root user RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 # Set working directory WORKDIR /app # Copy built files COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/package.json ./ # Switch to non-root user USER nextjs # Expose port EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=3s CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" # Use dumb-init to handle signals ENTRYPOINT ["dumb-init", "--"] # Start application CMD ["node", "dist/server.js"]

Conclusion

Following these Docker best practices will result in:

  • 🔒 More secure containers
  • 🚀 Faster builds and deployments
  • 💾 Smaller image sizes
  • 🛡️ Better reliability
  • 📊 Easier debugging

Start implementing these today for production-ready containers! 🐋

Let's Connect

Ready to build something amazing together?

Send us a message

🚀

Let's Chat.

Tell me about your project.

Let's create something together 🤝

Visit my social profile and get connected