Node.js8 min read

Docker for Node.js Applications

Containerize Node.js apps with Docker. Learn Dockerfile, docker-compose, and deployment best practices.

Sarah Chen
December 19, 2025
0.0k0

Docker for Node.js Applications

Docker packages your app with its dependencies. Works on my machine = works everywhere.

Basic Dockerfile

```dockerfile # Dockerfile FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm ci --only=production

COPY . .

EXPOSE 3000

CMD ["node", "server.js"] ```

Build and Run

```bash # Build image docker build -t my-app .

Run container docker run -p 3000:3000 my-app

Run with environment variables docker run -p 3000:3000 -e NODE_ENV=production my-app

Run in background docker run -d -p 3000:3000 my-app ```

Optimized Dockerfile

```dockerfile # Use specific version FROM node:20-alpine AS builder

WORKDIR /app

Copy package files first (better caching) COPY package*.json ./

Install all dependencies for build RUN npm ci

Copy source COPY . .

Build if needed (TypeScript, etc.) RUN npm run build

Production stage FROM node:20-alpine

WORKDIR /app

Copy package files COPY package*.json ./

Install production dependencies only RUN npm ci --only=production && npm cache clean --force

Copy built files from builder COPY --from=builder /app/dist ./dist

Security: run as non-root user USER node

EXPOSE 3000

CMD ["node", "dist/server.js"] ```

.dockerignore

``` node_modules npm-debug.log .git .gitignore .env .env.* Dockerfile docker-compose.yml .dockerignore README.md .nyc_output coverage ```

Docker Compose

```yaml # docker-compose.yml version: '3.8'

services: app: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=mongodb://mongo:27017/myapp - REDIS_URL=redis://redis:6379 depends_on: - mongo - redis restart: unless-stopped

mongo: image: mongo:6 volumes: - mongo-data:/data/db restart: unless-stopped

redis: image: redis:7-alpine restart: unless-stopped

volumes: mongo-data: ```

Run with Compose

```bash # Start all services docker-compose up

Start in background docker-compose up -d

View logs docker-compose logs -f app

Stop all docker-compose down

Stop and remove volumes docker-compose down -v ```

Development with Docker

```yaml # docker-compose.dev.yml version: '3.8'

services: app: build: context: . dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - .:/app - /app/node_modules # Don't override node_modules environment: - NODE_ENV=development command: npm run dev ```

```dockerfile # Dockerfile.dev FROM node:20-alpine

WORKDIR /app

COPY package*.json ./ RUN npm install

COPY . .

CMD ["npm", "run", "dev"] ```

Health Checks

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

```javascript // Express health endpoint app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); ```

Multi-Stage for TypeScript

```dockerfile FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY --from=builder /app/dist ./dist USER node EXPOSE 3000 CMD ["node", "dist/index.js"] ```

Common Commands

```bash # List containers docker ps

Stop container docker stop <container_id>

Remove container docker rm <container_id>

List images docker images

Remove image docker rmi <image_id>

Shell into container docker exec -it <container_id> sh

View logs docker logs <container_id> ```

Key Takeaway

Docker ensures consistent environments. Use multi-stage builds for smaller images. Use docker-compose for multi-service apps. Include health checks. Use non-root user for security. Keep images small with Alpine.

#Node.js#Docker#DevOps#Deployment#Advanced