Files
docker-templates/node/Dockerfile
Greg Hendrickson df5ea66906 feat(node): add production-ready Node.js Dockerfile templates with pnpm
- Multi-stage build with Node.js 22 slim base
- PNPM package manager via corepack (2x faster than npm)
- Build cache mounts for fast rebuilds
- Non-root user (appuser:1000) for security
- Health check using native fetch API
- Alpine variant for size optimization (~130MB)
- Distroless variant for maximum security (~110MB)
- Comprehensive .dockerignore for clean builds
- Full documentation with framework-specific guidance
2026-02-07 18:04:24 +00:00

96 lines
2.8 KiB
Docker

# syntax=docker/dockerfile:1.7
#
# Node.js Multi-Stage Dockerfile with PNPM
# Features: Fast builds, minimal image, non-root, security hardened
#
# Build args:
# NODE_VERSION - Node.js version (default: 22)
#
# Usage:
# docker build -t myapp:latest .
# docker run --rm -p 3000:3000 myapp:latest
# =============================================================================
# Stage 1: Install dependencies
# =============================================================================
ARG NODE_VERSION=22
FROM node:${NODE_VERSION}-slim AS deps
# Enable corepack for pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
# Copy dependency files only (layer caching)
COPY package.json pnpm-lock.yaml* ./
# Fetch dependencies to pnpm store
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm fetch --frozen-lockfile
# Install production dependencies only
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile --prod
# =============================================================================
# Stage 2: Build application (if needed)
# =============================================================================
FROM node:${NODE_VERSION}-slim AS builder
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
# Copy dependencies from deps stage
COPY --from=deps /app/node_modules ./node_modules
COPY package.json pnpm-lock.yaml* ./
# Install all dependencies (including devDependencies for build)
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
# Copy source code
COPY . .
# Build application (TypeScript, bundler, etc.)
RUN pnpm build
# Prune dev dependencies after build
RUN pnpm prune --prod
# =============================================================================
# Stage 3: Production runtime
# =============================================================================
FROM node:${NODE_VERSION}-slim AS runtime
# Security: Create non-root user
RUN groupadd --gid 1000 appgroup && \
useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser
WORKDIR /app
# Copy production dependencies
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
# Copy built application
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
# Node.js production optimizations
ENV NODE_ENV=production \
NODE_OPTIONS="--max-old-space-size=512"
# Switch to non-root user
USER appuser
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1)).catch(() => process.exit(1))"
# Start application
CMD ["node", "dist/index.js"]