How to containerize Node.js with Docker
Containerizing Node.js applications with Docker ensures consistent environments across development, testing, and production. With over 12 years of Node.js experience since 2014 and as the creator of CoreUI, I’ve Dockerized numerous production Node.js services. Docker containers package applications with their dependencies, making deployment reliable and portable across different environments. This approach simplifies deployment, scaling, and environment management for Node.js applications.
Use Docker multi-stage builds to create optimized, secure Node.js containers for production deployment.
Basic Dockerfile:
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
Multi-stage build:
# Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production
# Production stage
FROM node:20-alpine
WORKDIR /app
# Copy only necessary files
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
ENV NODE_ENV=production
EXPOSE 3000
# Run as non-root user
USER node
CMD ["node", "dist/index.js"]
Docker Compose:
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/myapp
depends_on:
- db
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: myapp
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
.dockerignore:
node_modules
npm-debug.log
.env
.git
.gitignore
README.md
.vscode
coverage
.nyc_output
dist
build
Development Dockerfile:
# Dockerfile.dev
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
Best Practice Note
Use Alpine images for smaller container size. Implement multi-stage builds to reduce final image size. Copy package files first to leverage Docker layer caching. Run as non-root user for security. Use .dockerignore to exclude unnecessary files. This is how we containerize CoreUI Node.js services—optimized Docker images with multi-stage builds ensuring small, secure, production-ready containers.



