How to Containerize a Node.js App with Docker

The Dockerfile patterns that produce small, secure, production-ready images.

Most Dockerfiles found in Node.js tutorials are wrong in ways that matter in production: single-stage builds that ship devDependencies, running as root, no health checks, image sizes over 1GB. This guide covers the multi-stage Dockerfile that you'd actually ship.

No fluff. Production-grade answers from engineers who build this every day.

The Multi-Stage Dockerfile That Works in Production

Single-stage Node.js Dockerfiles ship everything: devDependencies, build tools, source maps, TypeScript compiler. The result is a 1.2GB image that takes 3 minutes to pull. A multi-stage build produces a 120MB image with only the compiled output and production dependencies. The pattern: stage 1 (builder) installs all deps and compiles TypeScript. Stage 2 (runner) starts from a minimal base, copies only the dist/ folder and node_modules, runs as a non-root user.

At Valletta Software, we focus on:

Base image: node:20-alpine for the runner stage - not node:20 (saves 200MB+)

Multi-stage build: builder stage compiles runner stage runs - no source code in production

Non-root user: RUN addgroup app && adduser -S -G app app - never run as root in prod

.dockerignore: node_modules .git *.log coverage/ .env files - never baked in

Layer caching: COPY package files first RUN npm ci then COPY source - cache npm install

Health check: HEALTHCHECK every 30s CMD wget to health endpoint

Environment variables: runtime injection via env not ARG baked at build time

Docker Compose for Local Development

The compose file that matches production without requiring a Kubernetes cluster locally.

We give you more than just people. We give you top performers who drive results.

services: app postgres redis - mirrors production topology
volumes: named volumes for DB data persistence across restarts
environment: .env file mounted not hardcoded in compose
depends_on with condition: service_healthy - wait for DB ready not just started
Networks: internal bridge network - services communicate by name not localhost
Hot reload: nodemon or ts-node-dev with volume mount for development only
Override files: docker-compose.override.yml for dev settings base file stays prod-safe

Write boilerplate and scaffolding 3x faster with AI

Generate tests, migrations, and config automatically

Document architecture decisions as you build

Ship production-grade code - not just demos

How to Containerize a Node.js App with Docker - With Engineers Who Do It Properly

Our engineers ship multi-stage non-root health-checked images. Every time. Not 1GB tutorial Dockerfiles.

Our engineers are trained in today's most powerful tools - Copilot, Claude, Cursor, and AI-assisted tooling - and use them daily to move faster without cutting corners.

Choose from a solo dev, mini team, or full squad. All powered by AI and ready to build from day one.

Let's keep it simple.

Our engineers write multi-stage, non-root, health-checked Dockerfiles as the default. No 1GB tutorial images in production.

Need This Done? Don't Build It Alone.

Our engineers have done this before - on real products, under real deadlines.

Free consultation • No commitment required • Response within 24 hours