Use Official Base Images
# Good: specific, slim base image
FROM node:20-slim
# Avoid: generic, large images
# FROM ubuntu:latestMulti-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.mdHealth Checks
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -q --spider http://localhost:3000/health || exit 1Key Rules
- One process per container
- Use
.dockerignoreto 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/*)