Home/Blog/software engineering
Back to all articles
software engineering#Docker#DevOps#Next.js Docker

Production Docker Containerization: Multi-Stage Builds, Next.js 15 & Docker Compose

RB
Rajput BhavinArchitect
Founder, Rajput Bhavin Engineering
24 August 2026•10 min read

Quick Answer: Production Docker Containerization#

⚡ Quick Answer / Executive Summary
Production Docker containerization packages an application alongside its exact runtime dependencies, operating system libraries, and configuration files into an immutable container image. By using Multi-Stage Builds, developers reduce final image sizes by up to 90% (under 120MB), eliminate build-time tooling from production images, enforce non-root security execution (USER node), and orchestrate databases, caches, and APIs seamlessly using Docker Compose.

The "Works on My Machine" Problem: Why Docker is Essential#

Without containerization, deploying software across development, staging, and production environments creates severe configuration drift:

  1. ✓Host OS Inconsistencies: Node.js, OpenSSL, or glibc version mismatches between developer macOS laptops and production Linux Ubuntu cloud servers.
  2. ✓Bloated Production Images: Shipping 800MB+ node_modules folders containing development compilers, TypeScript type definitions, and testing frameworks directly to production servers.
  3. ✓Security Vulnerabilities: Running container processes as the default root superuser, allowing remote code execution (RCE) attacks to compromise the host operating system.


Production Next.js 15 Multi-Stage Dockerfile (output: "standalone")#

Below is the production Dockerfile engineered by Rajput Bhavin Engineering for Next.js 15 applications:

Dockerfile
Production Code
# Stage 1: Dependency Installation
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json pnpm-lock.yaml* ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile

# Stage 2: Application Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production

RUN corepack enable pnpm && pnpm build

# Stage 3: Minimal Production Runtime
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

# Enforce Non-Root Security
RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nextjs

# Copy only compiled standalone assets
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

CMD ["node", "server.js"]
Performance Impact: Standard Next.js Docker images weigh ~1.2GB. This multi-stage standalone image weighs under 115MB and boots in under 80 milliseconds.

Local Development Orchestration with Docker Compose#

Create a self-contained local development environment with Next.js, PostgreSQL, and Redis:

YAML Config
Production Code
version: '3.8'

services:
  app:
    build:
      context: .
      target: runner
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:secret123@db:5432/app_db?schema=public
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: secret123
      POSTGRES_DB: app_db
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

4 Container Security & Performance Best Practices#

  1. ✓Leverage Layer Caching: Copy package.json and install dependencies before copying the rest of your application code. Docker will reuse the cached dependency layer unless dependencies change.
  2. ✓Never Run as Root: Always create an unprivileged user (USER nextjs / USER node) in the final runtime stage.
  3. ✓Use .dockerignore: Explicitly exclude .git, node_modules, .env.local, and build artifacts from being sent in the Docker build context.
  4. ✓Scan for Vulnerabilities: Integrate docker scout or trivy into your GitHub Actions CI/CD to detect unpatched CVEs in base images automatically.

Modern DevOps & Infrastructure with Rajput Bhavin Engineering#

Build containerized, cloud-native architectures that deploy seamlessly to AWS ECS, Google Cloud Run, or Kubernetes.

Software Engineering Consultation

Need help architecting your modern software stack?

Rajput Bhavin Engineering provides hands-on systems architecture, codebase reviews, and custom cloud software development for technology teams in India and worldwide.

RB

Rajput Bhavin

Systems Architect

Founder and Systems Architect at Rajput Bhavin Engineering in Gota, Ahmedabad. Specializes in high-concurrency cloud software, Next.js web applications, multi-tenant SaaS architecture, and autonomous AI systems.

Connect Now