Dockerizing React Applications with Multi-Stage Builds0%

Dockerizing React Applications with Multi-Stage Builds

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Dockerizing React Applications with Multi-Stage Builds

Containerization guarantees that a React application builds and runs identically across local development, staging environments, and production Kubernetes clusters. A naive Docker build copies all source code and node_modules into the final image, resulting in massive container images (>1.5 GB) riddled with security vulnerabilities. Multi-Stage Docker Builds isolate the Node.js build tools and compile static HTML/JS/CSS assets into a lightweight, ultra-secure Nginx container (<25 MB).


1. Multi-Stage Build Architecture

Output
Stage 1: Build Environment (Node.js Alpine) - ~450 MB
├── Installs npm dependencies
├── Compiles TypeScript
├── Runs vite build
└── Generates /app/dist static folder
│
│ (Copies ONLY the compiled /dist folder!)
▼
Stage 2: Production Runtime (Nginx Alpine) - ~25 MB
├── Lightweight high-performance web server
├── No Node.js runtime, no npm, no source code!
└── Serves pre-compressed static assets at 10,000 req/sec

2. Production Dockerfile

DOCKERFILE
# ==========================================
# STAGE 1: Build Environment
# ==========================================
FROM node:20-alpine AS builder
 
WORKDIR /app
 
# Install dependencies first (leverages Docker layer caching)
COPY package.json package-lock.json ./
RUN npm ci --prefer-offline --no-audit
 
# Copy source files and compile
COPY . .
RUN npm run build
 
# ==========================================
# STAGE 2: Production Nginx Server
# ==========================================
FROM nginx:1.25-alpine AS runner
 
# Remove default nginx static html
RUN rm -rf /usr/share/nginx/html/*
 
# Copy compiled static assets from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html
 
# Copy custom enterprise Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
 
# Expose standard HTTP port
EXPOSE 80
 
# Run nginx in foreground
CMD ["nginx", "-g", "daemon off;"]

3. Production Nginx Configuration (nginx.conf)

Single Page Applications require routing all non-file URL requests back to index.html to allow React Router to handle client-side routing. Without try_files $uri $uri/ /index.html, refreshing /dashboard returns a 404 Not Found!

NGINX
server {
listen 80;
server_name localhost;
 
root /usr/share/nginx/html;
index index.html;
 
# Enable Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
 
# SPA Fallback: Direct all unknown paths to index.html for client-side routing
location / {
try_files $uri $uri/ /index.html;
}
 
# Long-term immutable caching for hashed static assets
location /assets/ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
access_log off;
}
 
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

4. Dockerignore Configuration (.dockerignore)

Prevent copying local build artifacts and sensitive files into the Docker context:

Output
node_modules
dist
.git
.env
.env.local
npm-debug.log
.DS_Store

5. Building and Running the Container

Bash / Terminal
# Build optimized image tagged as enterprise-react:latest
docker build -t enterprise-react:latest .
 
# Run container on port 8080
docker run -d -p 8080:80 --name react-app enterprise-react:latest

Inspect the final image with docker images: notice the image size is under 25 MB, with zero Node.js vulnerabilities!


Interactive Quiz

Practice Quiz

Question 1
What is the primary advantage of Multi-Stage Docker builds for React applications?
Question 2
Why is try_files $uri $uri/ /index.html mandatory in an Nginx SPA configuration?
Question 3
Why is COPY package*.json ./ followed by RUN npm ci placed before COPY . . in the Dockerfile?
Question 4
Why is npm ci preferred over npm install in Docker builds?
Question 5
What security benefit is achieved by discarding the Node.js runtime from the final production container?
Next Lesson

Automated CI/CD Pipelines with GitHub Actions

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext