
Docker Containerization: From Development to Production
Md Nayeem Hossain
Author
Md Nayeem Hossain
Author
Docker Containerization for Developers
"It works on my machine" is a phrase every developer hates hearing. Docker solves this by packaging your application and all its dependencies into a standard unit called a container.
In this guide, I'll explain how to Dockerize a Node.js application properly, from a development setup with hot-reloading to an optimized production build.
The Dockerfile
The Dockerfile is the blueprint for your container. A common mistake is including unnecessary files in the final image, making it huge. We can use Multi-stage Builds to fix this.
We compile and build the app in a "builder" stage, and then copy *only* the necessary artifacts to a final, slim "production" stage.
# Stage 1: Builder
# We use a larger image with all build tools
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production
# We use a clean, small image
FROM node:20-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
# Security: Don't run as root!
USER node
# Copy only what we need from the builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]Docker Compose for Development
Running containers manually is tedious. Docker Compose allows you to define your entire stack (App, Database, Redis) in one file.
This setup below mounts your local code into the container, so when you save a file, the app updates instantly (Hot Reloading), just like running it locally!
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
# This volume mapping enables hot-reloading
volumes:
- .:/app
- /app/node_modules
environment:
- DATABASE_URL=mongodb://mongo:27017/myapp
depends_on:
- mongo
mongo:
image: mongo:7
ports:
- "27017:27017"
volumes:
- mongo_data:/data/db
volumes:
mongo_data:Production Best Practices
:latest in production. Use specific versions (e.g., node:20.9.0-alpine) to ensure your build is reproducible.HEALTHCHECK instruction so Docker (or Kubernetes) knows if your app is stuck or crashing.# Add this to your Dockerfile
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

