# Multi-stage build for a Node.js application
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files first (leverage layer caching)
COPY package.json package-lock.json ./
RUN npm ci --only=production
# Copy source code (changes more frequently)
COPY src/ ./src/
COPY tsconfig.json ./
RUN npm run build
# Stage 2: Production
FROM node:20-alpine AS production
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# Copy only production artifacts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
# Set ownership
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
#!/bin/bash
# Essential Docker commands
# Build an image
docker build -t myapp:1.0.0 .
docker build -t myapp:1.0.0 -f Dockerfile.prod .
# Run a container
docker run -d --name myapp -p 8080:3000 myapp:1.0.0
docker run -d --name myapp -p 8080:3000 -e NODE_ENV=production -e DATABASE_URL=postgres://db:5432/app -v /host/data:/app/data --restart unless-stopped myapp:1.0.0
# Container management
docker ps # List running containers
docker ps -a # List all containers
docker logs -f myapp # Follow logs
docker exec -it myapp /bin/sh # Shell into container
docker stop myapp # Graceful stop
docker rm myapp # Remove container
# Image management
docker images # List images
docker image prune -a # Remove unused images
docker tag myapp:1.0.0 registry.example.com/myapp:1.0.0
docker push registry.example.com/myapp:1.0.0
# Inspect and debug
docker inspect myapp # Full container details
docker stats # Live resource usage
docker top myapp # Running processes
docker diff myapp # Filesystem changes
# Cleanup
docker system prune -a --volumes # Remove everything unused
Docker packages applications into lightweight, portable containers. A Dockerfile defines build instructions—each instruction creates an immutable layer. The FROM directive sets the base image. COPY and ADD bring files into the image. RUN executes commands during build. CMD and ENTRYPOINT define the container's startup command. The docker build command creates images from Dockerfiles. docker run starts containers from images. Layer caching dramatically speeds up builds—order instructions from least to most frequently changing. Multi-stage builds reduce final image size by separating build and runtime dependencies. Use .dockerignore to exclude unnecessary files. Tag images with semantic versions, never rely solely on latest. Understanding the image layer system is key to writing efficient Dockerfiles.