Exclusive Discount Deal
Upto 50% OFF
Offer ends in:
24 DAYS
|
21 HOURS
|
37 MINS
|
04 SECS
Home / Blog / Docker Multi-Stage Builds: Reducing Container Size by 80%
DevOps & Cloud • Oct 7, 2026

Docker Multi-Stage Builds: Reducing Container Size by 80%

Step-by-step optimization strategies for stripping build dependencies, hardening non-root runtime environments, and trimming production container footprints for Node.js and PHP applications.

UPTO 50% OFF
Trending:
BrickTry

Requirement Scope

AI is analyzing your requirement...

Generating custom modules, implementation options, and dynamic clarification questions.

Add Custom Requirement or Module

Add your own specific features, integrations, or components. AI will incorporate them to dynamically generate the next relevant options.

1. Progressive Clarifications

Click to expand & answer

2. Scope Modules & Features (/ Selected)

Click row to expand details · Customize options
✓
✕
Completeness:

Bloated container images remain an unaddressed vulnerability in modern software supply chains. When developers ship a Node.js or PHP production container that still contains devDependencies, compiler toolchains, package manager caches, and unstripped debugging symbols, they introduce unnecessary operational risk. A standard single-stage Node.js container often balloons to over 1.2 GB. In production, this increases image pull latency, inflates cloud storage costs, and significantly expands the attack surface for Common Vulnerabilities and Exposures (CVEs).

Multi-stage Docker builds solve this systemic issue by decoupling the compilation and build environment from the final execution runtime. By leveraging multiple FROM instructions within a single Dockerfile, engineering teams can copy only the essential compiled binaries, production node modules, and static assets into an immutable, minimal runtime image. This article details practical optimization strategies to strip build dependencies, harden non-root environments, and achieve an 80% reduction in production container footprints for enterprise-grade Node.js and PHP workloads.


The Architectural Anatomy of Multi-Stage Containers

To understand the footprint reduction, examine how standard single-stage builds compare to isolated multi-stage architectures. In a monolithic build, every package manager artifact, source map, and build-time utility persists in the final layer stack.

The following matrix contrasts single-stage antipatterns with optimized multi-stage design patterns across critical production vectors:

Architectural Metric Single-Stage Monolith Multi-Stage Optimized Security & Operational Impact
Final Image Size 900MB – 1.5GB 80MB – 180MB Reduces container registry storage and network pull times by ~85%.
Build Tooling Footprint gcc, make, python3 present Stripped entirely Eliminates remote code execution vectors relying on compiler toolchains.
Package Dependencies Includes devDependencies Production-only (--omit=dev) Removes testing frameworks and vulnerable transitive packages.
Runtime User Often defaults to root Strict non-root UID/GID Mitigates container breakout exploits and host kernel escalation.
Caching Granularity Monolithic cache invalidation Independent stage caching Speeds up CI/CD pipeline build times via parallel layer reuse.

Optimizing Node.js 22 Workloads with Alpine and Distroless

Node.js applications require a TypeScript compiler, type definitions, and build tools during development, but none of these elements are required to execute the compiled JavaScript emitter (dist/main.js).

The following production-ready Dockerfile demonstrates a three-stage build pattern. It isolates dependency installation, compiles the TypeScript codebase, strips development artifacts, and deposits the output into a hardened node:22-alpine runtime image.

# ==========================================
# Stage 1: Dependency Caching Stage
# ==========================================
FROM node:22-alpine AS deps
WORKDIR /app

# Copy package manifests to leverage Docker layer caching
COPY package.json package-lock.json ./
RUN npm ci --only=production && \
    cp -R node_modules /tmp/prod_modules

# Install all dependencies (including devDependencies for building)
RUN npm ci

# ==========================================
# Stage 2: Compilation Stage
# ==========================================
FROM node:22-alpine AS builder
WORKDIR /app

COPY --from=deps /app/node_modules ./node_modules
COPY tsconfig.json ./
COPY src/ ./src

# Compile TypeScript to JavaScript
RUN npm run build

# ==========================================
# Stage 3: Production Runtime Stage
# ==========================================
FROM node:22-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV PORT=3080

# Create a non-privileged system user and group
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001 -G nodejs

# Copy pruned production node_modules and compiled output
COPY --from=deps /tmp/prod_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

# Enforce non-root execution
USER nodejs

EXPOSE 3080
CMD ["node", "dist/main.js"]

Key Architectural Takeaways:

  1. Pruned Module Staging: By caching /tmp/prod_modules in Stage 1, we avoid reinstalling packages for the final runtime while ensuring devDependencies like TypeScript and Jest never cross into Stage 3.
  2. Alpine Minimization: Using Alpine Linux keeps the core C library (musl) footprint under 10MB, contrasting sharply with Debian-based base images exceeding 100MB.

Optimizing PHP 8.4 and Laravel Applications

PHP applications present a unique containerization challenge: composer dependency management requires PHP extensions, git binaries, and zip utilities, whereas the production application server (PHP-FPM or FrankenPHP) only requires the application source tree, vendor directory, and execution extensions.

The multi-stage pattern below compiles Composer dependencies separately before merging them into a lean PHP-FPM runtime image with strict file permissions.

# ==========================================
# Stage 1: Composer Build Stage
# ==========================================
FROM composer:2.8 AS vendor-builder
WORKDIR /app

COPY composer.json composer.lock ./

# Install production dependencies without dev scripts
RUN composer install \
    --no-dev \
    --no-interaction \
    --no-plugins \
    --no-scripts \
    --prefer-dist \
    --optimize-autoloader

COPY . .
RUN composer dump-autoload --optimize

# ==========================================
# Stage 2: Production PHP-FPM Runtime
# ==========================================
FROM php:8.4-fpm-alpine AS production
WORKDIR /var/www/html

# Install essential system extensions
RUN apk add --no-cache \
    libpng-dev \
    libzip-dev \
    oniguruma-dev && \
    docker-php-ext-install pdo_mysql mbstring zip exif pcntl

# Copy production vendor directory and source code from Stage 1
COPY --from=vendor-builder /app /var/www/html

# Set correct permissions for web server execution
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

USER www-data

EXPOSE 9000
CMD ["php-fpm"]

By decoupling Composer from the final runtime image, we eliminate git, curl, temporary build archives, and composer configuration caches from production, cutting the image footprint by over 70% while improving security compliance.


How BrickTry Accelerates & Powers This

Implementing, testing, and maintaining optimized container architectures across dozens of microservices demands deep operational overhead. BrickTry eliminates this friction through an integrated ecosystem designed for senior engineering teams and technical founders:

  • Interactive Browser Lab Sandbox (/lab): Test, benchmark, and debug multi-stage Dockerfiles instantly inside an isolated zero-setup in-browser virtual container runtime. Measure image layers, inspect AST structures, and profile container startup performance in real time without local environment clutter.
  • AI-Human Dev Pairing: BrickTry’s autonomous AI scaffolding instantly generates production-grade multi-stage Dockerfiles, CI/CD pipelines, and Kubernetes manifests tailored to your exact tech stack (Node.js, Laravel, Go, or Python). Concurrently, dedicated senior full-stack engineering pods review your architecture for security vulnerabilities, memory leaks, and container optimization opportunities.
  • Automated AST Security Auditing: Every build undergoes static analysis and AST scanning to identify outdated base images, vulnerable transitive dependencies, and misconfigured non-root user permissions before code ever reaches a production registry.
  • Unified Importer: Seamlessly import existing GitHub repositories or legacy CodeCanyon/monolithic scripts. BrickTry refactors monolithic codebases into clean architecture standards and automatically generates optimized multi-stage build scripts.
  • 100% Source Code Ownership: Retain absolute ownership of your repositories, Docker configurations, infrastructure-as-code scripts, and database schemas with zero vendor lock-in. Scale confidently knowing your entire infrastructure remains fully exportable and under your direct control.

Build, Test, and Scale This on BrickTry

BrickTry pairs you with autonomous AI scaffolding supervised by dedicated senior full-stack software engineers in an interactive in-browser development sandbox. Test, build, and deploy production-grade software with 100% source code ownership and zero vendor lock-in.

Launch Interactive Requirement Builder →

❤️

Support BrickTry Platform & Engineering Development

Help us build, maintain, and advance our AI engineering platform. Every donation fuels open-source tooling, infrastructure, and continuous improvements.

$
Donor Details
Promote Your Brand / Link Wall

UPI / Credit & Debit Cards / Netbanking
Razorpay
Secure 256-bit encrypted checkout
View Leaderboard & Wall

Hey!

Welcome, Let's chat —
start a new conversation
below.

Recent conversations
See all

Hi ,We’d like to inform you that the Integ...

Abhishek A Agrawal • 1d ago

Abhishek A Agrawal

Back in a few hours