Docs / Containers & Docker / Dockerfile Best Practices for Production

Dockerfile Best Practices for Production

By Admin · Feb 25, 2026 · Updated Apr 23, 2026 · 60 views · 2 min read

Use Official Base Images

# Good: specific, slim base image
FROM node:20-slim

# Avoid: generic, large images
# FROM ubuntu:latest

Multi-Stage Builds

Keep final images small by using build stages:

# Build stage
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

Layer Caching

Order instructions from least to most frequently changed:

FROM python:3.12-slim

# Rarely changes — cached
RUN apt-get update && apt-get install -y --no-install-recommends gcc && rm -rf /var/lib/apt/lists/*

# Changes when dependencies change
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Changes with every code update
COPY . .

CMD ["python", "app.py"]

Security Best Practices

# Run as non-root user
RUN addgroup --system app && adduser --system --ingroup app app
USER app

# Don't store secrets in the image
# Use --secret flag at build time or environment variables at runtime

# Scan for vulnerabilities
# docker scout cves myimage:latest

.dockerignore

node_modules
.git
.env
*.log
Dockerfile
docker-compose*.yml
README.md

Health Checks

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget -q --spider http://localhost:3000/health || exit 1

Key Rules

  • One process per container
  • Use .dockerignore to exclude unnecessary files
  • Pin dependency versions
  • Minimize the number of layers
  • Clean up in the same RUN instruction (apt-get install && rm -rf /var/lib/apt/lists/*)

Was this article helpful?