OwlTheEngineer

DevOps & Containerization

Production Dockerfile & Compose Generator

Generate hardened, secure, multi-stage Dockerfiles, complete docker-compose.yml environments, and optimized .dockerignore files for Node.js, Go, Python, and Rust.

# ==========================================
# Multi-Stage Node.js (pnpm) Production Dockerfile
# ==========================================

# 1. Dependencies Stage
FROM node:22-alpine AS deps
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# 2. Build Stage
FROM node:22-alpine AS builder
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate

COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build

# 3. Production Runner Stage
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000

USER node

COPY --from=builder --chown=node:node /app/package.json ./
COPY --from=builder --chown=node:node /app/node_modules ./node_modules
COPY --from=builder --chown=node:node /app/dist ./dist

# Container health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

EXPOSE 3000
CMD ["node", "dist/index.js"]

The 5 Commandments of Production Docker Containers

1. Always Use Multi-Stage Builds

Building in the same image that runs your app leaves compilers, build tools, development headers, and caches in production images. Multi-stage builds separate the builder environment from a minimal runner image, shrinking container sizes from 1.2GB down to <90MB.

2. Never Run as Root

By default, container processes run with root privileges (UID 0). If an application vulnerability allows remote code execution, an attacker has full root escalation potential. Specifying USER node or USER nonroot confines the process to unprivileged sandbox execution.

3. Leverage Docker Layer Caching Order

Always copy package manifest lockfiles (package.json, pnpm-lock.yaml, go.mod) and install dependencies before copying application source code (COPY . .). This ensures rebuilds are near-instant when only code changes.