Docker Best Practices for Production
DodaTech
2 min read
In this tutorial, you'll learn about Docker Best Practices for Production. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
What You'll Learn
Production-ready Docker practices — security hardening, image optimization, resource management, health checks, and deployment patterns used by real teams.
Why It Matters
A Dockerfile written for local dev won't cut it in production. Poorly configured containers pose security risks and waste resources at scale.
Real-World Use
Running thousands of containers reliably, passing security audits, and keeping image sizes under 200MB for fast deployments.
1. Minimal Base Images
# ❌ Avoid: Full OS images
FROM ubuntu:22.04 # ~200MB
# ✅ Preferred: Alpine or Distroless
FROM node:20-alpine # ~125MB
FROM python:3.12-slim # ~150MB
FROM gcr.io/distroless/nodejs20 # ~50MB
2. Run as Non-Root
# ❌ Avoid: Default root user
FROM node:20-alpine
COPY . .
RUN npm install
CMD ["node", "app.js"] # Runs as root!
# ✅ Add a non-root user
FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
USER app
COPY --chown=app:app . .
RUN npm install
CMD ["node", "app.js"]
3. Health Checks
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
4. Resource Limits
# Always set limits
docker run -d \
--memory="256m" \
--memory-reservation="128m" \
--cpus="0.5" \
--pids-limit=100 \
my-app
# In Docker Compose:
services:
app:
deploy:
resources:
limits:
cpus: "0.5"
memory: 256M
reservations:
cpus: "0.25"
memory: 128M
5. Logging Best Practices
# Write logs to stdout/stderr (don't use files)
# Docker collects stdout/stderr automatically
# ❌ Avoid
RUN mkdir /var/log/myapp
CMD ["node", "app.js"] # App writes to /var/log/myapp/app.log
# ✅ Write to stdout
CMD ["node", "app.js"] # App logs to stdout
6. Security Scanning
# Scan images for vulnerabilities
docker scout quick my-app
# Integrate into CI/CD
trivy image my-app:latest
7. Image Tags
# ❌ Avoid: latest
FROM node:latest
# ✅ Use specific versions
FROM node:20.11.0-alpine3.19
# Use Git SHA or build number in tags
docker build -t my-app:$(git rev-parse --short HEAD) .
8. Build Context Optimization
# .dockerignore
node_modules
.git
*.md
.gitignore
.env
.DS_Store
Production Dockerfile Template
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --chown=app:app . .
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "server.js"]
Production Checklist
□ Use minimal base image
□ Run as non-root user
□ Set resource limits
□ Add health check
□ Configure logging to stdout
□ Scan for vulnerabilities
□ Pin base image versions
□ Use .dockerignore
□ Multi-stage builds
□ Read-only root filesystem
□ No sensitive env vars in image
□ Set restart policy
← Previous
Docker Volumes and Data Persistence Explained
Next →
Docker Compose Production: Reverse Proxy, SSL & Scaling
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro