Bablu Kumar Singh
Back to Blog
DevOps
7 min read
June 6, 2026

Docker Deployment for Node.js Applications: A Production Guide

Docker Deployment for Node.js Applications: A Production Guide

Docker transforms the classic "works on my machine" problem into a solved one. A container packages your Node.js application with its exact runtime, dependencies, and configuration — ensuring identical behavior from a developer's laptop to a production cluster. Here is how I containerize Node.js applications for production.

The Naive Dockerfile (and Why It Is Bad)

Most tutorials start here:

dockerfile Code Block
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "dist/index.js"]

Problems:

  • Copies node_modules, .git, and other junk into the image.
  • Installs devDependencies in production.
  • Uses the full Node.js image (1 GB+).
  • No layer caching — every code change reinstalls all dependencies.

Multi-Stage Build (Production-Ready)

A multi-stage build separates the build environment from the production runtime:

dockerfile Code Block
# Stage 1: Install dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production

# Stage 2: Build TypeScript
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json tsconfig.json ./
COPY --from=deps /app/node_modules ./node_modules
COPY src ./src
RUN npm run build

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

# Create non-root user
RUN addgroup --system appgroup && adduser --system appuser --ingroup appgroup

COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

USER appuser
EXPOSE 3000
ENV NODE_ENV=production

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

Results:

  • Final image size: ~150 MB (vs. 1 GB+ with the naive approach).
  • No devDependencies, no source code, no build tools in production.
  • Runs as a non-root user for security.

The .dockerignore File

Just as critical as the Dockerfile. Prevent unnecessary files from entering the build context:

javascript Code Block
node_modules
.git
.env
.env.*
dist
*.md
.vscode
coverage
tests

A smaller build context means faster docker build commands.

Environment Variables

Never bake secrets into the image. Pass them at runtime:

bash Code Block
docker run -d \
  -e DATABASE_URL="mongodb://..." \
  -e REDIS_URL="redis://..." \
  -e JWT_SECRET="super-secret" \
  -p 3000:3000 \
  my-app:latest

For complex setups, use a .env file with Docker Compose (never commit it to Git).

Docker Compose for Development

Docker Compose orchestrates multi-container setups. A typical backend stack:

yaml Code Block
# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - '3000:3000'
    environment:
      - DATABASE_URL=mongodb://mongo:27017/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - mongo
      - redis
    volumes:
      - ./src:/app/src  # hot reload in dev

  mongo:
    image: mongo:7
    ports:
      - '27017:27017'
    volumes:
      - mongo_data:/data/db

  redis:
    image: redis:7-alpine
    ports:
      - '6379:6379'

volumes:
  mongo_data:

Start everything with one command:

bash Code Block
docker compose up -d

Health Checks in Docker

Add a health check so Docker and orchestrators know when your app is ready:

dockerfile Code Block
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:3000/api/health || exit 1

Layer Caching Strategy

Docker caches layers from top to bottom. Structure your Dockerfile so frequently changing layers are at the bottom:

1. Base image (rarely changes)

2. COPY package.json and npm ci (changes when dependencies change)

3. COPY src and npm run build (changes on every code push)

This way, a code change does not trigger a full npm ci — only the build step runs.

Production Deployment Checklist

  • [ ] Use multi-stage builds to minimize image size.
  • [ ] Run as a non-root user.
  • [ ] Never bake secrets into images.
  • [ ] Add a health check endpoint and Docker health check.
  • [ ] Set NODE_ENV=production explicitly.
  • [ ] Use npm ci instead of npm install for deterministic builds.
  • [ ] Tag images with Git SHA, not latest, for traceability.
  • [ ] Scan images for vulnerabilities with docker scout or Trivy.

Key Takeaways

  • Multi-stage builds are non-negotiable for production Node.js images.
  • Docker Compose gives you a one-command development environment.
  • Structure Dockerfiles for maximum layer cache efficiency.
  • Always run containers as non-root and scan for vulnerabilities.

Docker is the foundation of modern deployment workflows. Master it, and you unlock CI/CD pipelines, Kubernetes orchestration, and cloud-native architecture.

#Docker#Deployment#DevOps#Node.js
Bablu Kumar Singh
Written by

Bablu Kumar Singh

Backend-Focused Full Stack Developer

Backend-Focused Full Stack Developer specializing in Node.js, MongoDB, PostgreSQL, Redis, RabbitMQ, AWS, Docker, System Design, and React Native.

You May Also Like

Building SaaS Platforms with Node.js: Architecture to Payment Integration
Backend Development
8 min read

Building SaaS Platforms with Node.js: Architecture to Payment Integration

End-to-end guide for building multi-tenant SaaS applications with Node.js — covering tenant isolation, subscription billing with Stripe, webhook handling, and production deployment.

May 19, 2026Read
AWS for Backend Developers: Essential Services and Architecture Patterns
DevOps
7 min read

AWS for Backend Developers: Essential Services and Architecture Patterns

A backend developer's guide to essential AWS services — covering EC2, RDS, S3, SQS, CloudFront, and building a production-ready deployment architecture with Auto Scaling and load balancing.

Jun 9, 2026Read
Authentication Systems in Node.js: JWT, Refresh Tokens, and Security
Backend Development
7 min read

Authentication Systems in Node.js: JWT, Refresh Tokens, and Security

Build a production-grade authentication system in Node.js — covering JWT access tokens, refresh token rotation, password hashing with bcrypt, and common security pitfalls to avoid.

May 28, 2026Read