Docker Production Deployment: Best Practices and Patterns
Docker makes deployment consistent, but production deployments require more than just containerization. This guide covers multi-stage builds, security hardening, health checks, and orchestration patterns.
Multi-Stage Builds
Multi-stage builds reduce image size and improve security by excluding build tools from production images. Use separate stages for building and running.
# Build stage FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:18-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY package*.json ./ CMD ["node", "dist/index.js"]
Security Hardening
Run containers as non-root users, use minimal base images (Alpine), scan for vulnerabilities, and keep images updated. Never include secrets in images—use environment variables or secret management.
Health Checks
Implement health check endpoints and configure Docker HEALTHCHECK instructions. This enables automatic container restart by the runtime (Docker, Kubernetes) and seamless load balancer integration. A well-designed health check validates not just that your process is running, but that your application can actually serve requests — checking database connectivity and cache availability where relevant.
Key Takeaways
- Always use multi-stage builds to keep production images small — a 50MB image deploys faster and has a smaller attack surface than a 500MB development image.
- Run containers as non-root users and use read-only file systems wherever possible to limit the impact of a potential container escape.
- Tag images with the git commit SHA, not just
latest, so you can always identify exactly what code is running and roll back to any previous version. - Never store secrets in Dockerfiles or image layers — use environment variables passed at runtime, or a dedicated secrets manager like AWS Secrets Manager or HashiCorp Vault.
- Health check endpoints should verify your full application stack (database, cache, external dependencies) so orchestrators can detect partial failures, not just process crashes.
Ready to Ship Your SaaS?
Stop writing the same boilerplate code. Browse our production-ready SaaS templates — each includes authentication, Stripe billing, database setup, and deployment configs so you can launch in days instead of months.
Check out our straightforward pricing, see how we compare to ShipFast and MakerKit, or read the documentation to understand exactly what you get. Questions? Learn about our team and mission, or catch up on our engineering blog.