22 Deployment Docker
title: Docker Deployment for Node.js REST APIs weight: 32 date: 2026-06-28 lastmod: 2026-06-28 description: Deploy Node.js REST APIs with Docker including multi-stage builds, Docker Compose for local development, production optimization, and CI/CD pipeline integration. tags: [api-development, nodejs]
Docker deployment for Node.js REST APIs containerizes the application with multi-stage builds for optimized images, Docker Compose for multi-service environments (app, database, Redis), and production-ready configuration.
```mermaid
flowchart TD
A[Node.js App] --> B[Dockerfile]
B --> C[Docker Image]
C --> D[Container]
D --> E[Production]
B --> F[Multi-stage Build]
F --> G[Stage 1: Install deps]
F --> H[Stage 2: Build]
F --> I[Stage 3: Production]
style A fill:#e1f5fe
style B fill:#c8e6c9
style F fill:#fff9c4
Multi-stage builds separate dependency installation, building, and production runtime. The final image contains only production dependencies and the compiled code. Docker Compose orchestrates your API server, database, Redis, and other services.
Think of Docker like a shipping container for your application. The container has everything the app needs to run (Node.js, dependencies, config). It works the same on a developer's laptop, a test server, or a production cluster.
Example: Multi-Stage Dockerfile
# 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 stage
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 3: Production
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nodeuser
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/package.json ./
USER nodeuser
EXPOSE 3000
ENV NODE_ENV=production
ENV PORT=3000
CMD ["node", "dist/app.js"]
Example: Docker Compose for Development
version: '3.8'
services:
app:
build:
context: .
target: deps
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- DATABASE_URL=mongodb://mongo:27017/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- mongo
- redis
command: npx nodemon src/app.js
mongo:
image: mongo:7
volumes:
- mongo_data:/data/db
ports:
- "27017:27017"
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
ports:
- "6379:6379"
volumes:
mongo_data:
redis_data:
Example: Production Docker Compose
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=mongodb://mongo:27017/myapp
- REDIS_URL=redis://redis:6379
- JWT_SECRET=${JWT_SECRET}
depends_on:
- mongo
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
mongo:
image: mongo:7
volumes:
- mongo_data:/data/db
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
mongo_data:
redis_data:
Common Mistakes
- Running Node.js as root in containers — Containers running as root are a security risk. Create a non-root user in the Dockerfile.
- Installing devDependencies in production images — Production images should only contain production dependencies. Use npm ci --only=production.
- Binding to 0.0.0.0 instead of localhost — Express defaults to localhost. In Docker, bind to 0.0.0.0 so the container accepts external connections.
- Not using .dockerignore — Without .dockerignore, node_modules, .env, and logs are copied into the build context, slowing builds and increasing image size.
- Hard-coding environment variables in Dockerfile — Use ARG for build-time variables and ENV for runtime defaults. Never hard-code secrets.
Practice Questions
- What is the benefit of multi-stage Docker builds?
- Why should you use a non-root user in containers?
- What is the purpose of volumes in Docker Compose?
- How do you handle health checks for Docker containers?
- Challenge: Create a complete Docker deployment for a Node.js REST API with MongoDB and Redis. Include: multi-stage Dockerfile, development docker-compose with hot reload, production docker-compose with Nginx reverse proxy, health checks, and non-root user. Test the deployment locally.
FAQ
Mini Project
Create a complete Docker deployment pipeline for a Node.js REST API. Include: multi-stage Dockerfile (deps, build, production), Docker Compose for development (app, mongo, redis), Docker Compose for production (app, nginx, mongo, redis), health checks, non-root user, .dockerignore, and a CI/CD script that builds and pushes the image.
What's Next
Now learn about environment configuration in Building REST APIs with Node.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro