Docker Containerization Deployment - Complete Production Guide
Docker has revolutionized how we build, ship, and run applications. This comprehensive tutorial will teach you everything you need to know about containerizing applications and deploying them in production environments using Docker and related technologies.
What You'll Learn
By the end of this tutorial, you will be able to:
- Understand Docker concepts and architecture
- Create and manage Docker containers
- Write efficient Dockerfiles
- Build and manage Docker images
- Deploy containerized applications
- Implement container security best practices
- Use Docker Compose for multi-container applications
- Deploy to production environments
Prerequisites
Before starting this tutorial, you should have:
- Basic knowledge of Linux command line
- Understanding of application development
- Docker installed on your system
- Basic knowledge of networking concepts
Docker Fundamentals
1. What is Docker?
Docker is a containerization platform that allows you to package applications and their dependencies into lightweight, portable containers. These containers can run consistently across different environments.
2. Key Concepts
- Container: A running instance of a Docker image
- Image: A read-only template used to create containers
- Dockerfile: A text file containing instructions to build an image
- Registry: A storage and distribution system for Docker images
- Docker Hub: The default public registry for Docker images
3. Docker Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Docker Client │ │ Docker Daemon │ │ Docker Host │
│ │ │ │ │ │
│ docker build │───▶│ Build Images │ │ ┌───────────┐ │
│ docker run │ │ Run Containers │ │ │ Container │ │
│ docker push │ │ Manage Images │ │ │ Container │ │
└─────────────────┘ └─────────────────┘ │ │ Container │ │
└───────────┘ │
└─────────────────┘
Getting Started with Docker
1. Installation
Ubuntu/Debian
# Update package index
sudo apt-get update
# Install Docker
sudo apt-get install docker.io
# Start Docker service
sudo systemctl start docker
sudo systemctl enable docker
# Add user to docker group
sudo usermod -aG docker $USER
macOS
# Install using Homebrew
brew install --cask docker
# Or download Docker Desktop from docker.com
Windows
Download Docker Desktop from the official Docker website.
2. Verify Installation
# Check Docker version
docker --version
# Run hello-world container
docker run hello-world
# List running containers
docker ps
# List all containers
docker ps -a
Working with Images
1. Pulling Images
# Pull latest Ubuntu image
docker pull ubuntu:latest
# Pull specific version
docker pull nginx:1.21
# Pull from different registry
docker pull registry.example.com/myapp:latest
2. Listing Images
# List all images
docker images
# List images with specific format
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Search for images
docker search nginx
3. Removing Images
# Remove specific image
docker rmi nginx:1.21
# Remove unused images
docker image prune
# Remove all unused images
docker image prune -a
Working with Containers
1. Running Containers
# Run container in foreground
docker run ubuntu echo "Hello World"
# Run container in background
docker run -d nginx
# Run with port mapping
docker run -d -p 8080:80 nginx
# Run with volume mounting
docker run -d -v /host/path:/container/path nginx
# Run with environment variables
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql
2. Container Management
# List running containers
docker ps
# List all containers
docker ps -a
# Stop container
docker stop container_id
# Start stopped container
docker start container_id
# Restart container
docker restart container_id
# Remove container
docker rm container_id
# Remove all stopped containers
docker container prune
3. Interacting with Containers
# Execute command in running container
docker exec -it container_id bash
# View container logs
docker logs container_id
# Follow logs in real-time
docker logs -f container_id
# Inspect container
docker inspect container_id
Creating Dockerfiles
1. Basic Dockerfile Structure
# Use official Node.js runtime as base image
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Define startup command
CMD ["npm", "start"]
2. Multi-stage Builds
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["npm", "start"]
3. Best Practices for Dockerfiles
# Use specific versions
FROM node:18.4.0-alpine
# Use non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Use .dockerignore
COPY . .
# .dockerignore should contain:
# node_modules
# .git
# .env
# *.log
# Use multi-stage builds for smaller images
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine AS runner
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Use health checks
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Use proper signal handling
STOPSIGNAL SIGTERM
# Set proper labels
LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL description="My application"
Building and Managing Images
1. Building Images
# Build image with tag
docker build -t myapp:latest .
# Build with specific Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
# Build with build arguments
docker build --build-arg NODE_ENV=production -t myapp:prod .
# Build without cache
docker build --no-cache -t myapp:latest .
2. Tagging and Pushing
# Tag image
docker tag myapp:latest myregistry.com/myapp:v1.0
# Push to registry
docker push myregistry.com/myapp:v1.0
# Login to registry
docker login myregistry.com
3. Image Optimization
# Analyze image layers
docker history myapp:latest
# Use dive tool for detailed analysis
dive myapp:latest
# Build with BuildKit for better caching
DOCKER_BUILDKIT=1 docker build -t myapp:latest .
Docker Compose
1. Basic docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
depends_on:
- db
- redis
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:6-alpine
ports:
- "6379:6379"
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
volumes:
postgres_data:
2. Advanced Docker Compose
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile.prod
args:
NODE_ENV: production
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:password@db:5432/myapp
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- app-network
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
networks:
- app-network
volumes:
postgres_data:
networks:
app-network:
driver: bridge
Production Deployment
1. Environment Configuration
# .env file
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://user:password@db:5432/myapp
REDIS_URL=redis://redis:6379
JWT_SECRET=your-secret-key
2. Production Dockerfile
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Automatically leverage output traces to reduce image size
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
3. Nginx Configuration
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream app {
server web:3000;
}
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
}
Container Security
1. Security Best Practices
# Use specific versions
FROM node:18.4.0-alpine
# Run as non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
# Use multi-stage builds
FROM node:18-alpine AS deps
# ... build dependencies
FROM node:18-alpine AS runner
# ... copy only necessary files
# Scan for vulnerabilities
RUN npm audit --audit-level high
# Use .dockerignore
COPY . .
2. Security Scanning
# Scan image for vulnerabilities
docker scan myapp:latest
# Use Trivy for security scanning
trivy image myapp:latest
# Use Snyk for vulnerability scanning
snyk container test myapp:latest
3. Runtime Security
# docker-compose.yml with security settings
version: '3.8'
services:
web:
build: .
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /var/cache/nginx
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
Monitoring and Logging
1. Container Monitoring
# Monitor container stats
docker stats
# Monitor specific container
docker stats container_id
# Use cAdvisor for detailed monitoring
docker run -d \
--name=cadvisor \
-p 8080:8080 \
-v /:/rootfs:ro \
-v /var/run:/var/run:ro \
-v /sys:/sys:ro \
-v /var/lib/docker/:/var/lib/docker:ro \
google/cadvisor:latest
2. Logging Configuration
# docker-compose.yml with logging
version: '3.8'
services:
web:
build: .
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Deployment Strategies
1. Blue-Green Deployment
# Deploy new version (green)
docker-compose -f docker-compose.green.yml up -d
# Test green environment
curl http://green.your-domain.com/health
# Switch traffic to green
# Update load balancer configuration
# Stop blue environment
docker-compose -f docker-compose.blue.yml down
2. Rolling Updates
# Update service with rolling strategy
docker service update --image myapp:v2.0 myapp-service
# Update with specific parameters
docker service update \
--image myapp:v2.0 \
--update-parallelism 2 \
--update-delay 10s \
myapp-service
Troubleshooting
1. Common Issues
# Container won't start
docker logs container_id
# Check container status
docker inspect container_id
# Debug container
docker exec -it container_id sh
# Check resource usage
docker stats container_id
2. Performance Issues
# Check image size
docker images
# Analyze image layers
docker history myapp:latest
# Check container resource limits
docker inspect container_id | grep -i memory
Summary
This comprehensive tutorial covered:
- Docker Fundamentals: Understanding containers, images, and Dockerfile
- Container Management: Creating, running, and managing containers
- Image Building: Writing efficient Dockerfiles and building images
- Docker Compose: Managing multi-container applications
- Production Deployment: Deploying containerized applications
- Security: Implementing container security best practices
- Monitoring: Monitoring and logging containerized applications
Next Steps
Further Reading and Resources
Official Documentation
- Docker Official Documentation - Complete Docker guide
- Docker Hub - Official Docker image registry
- Docker Compose Documentation - Multi-container applications
Development Tools
- Docker Desktop - Docker GUI for development
- Portainer - Docker management UI
- Docker VS Code Extension - Docker integration for VS Code
Learning Resources
- Docker Best Practices - Official best practices guide
- Container Security Best Practices - Security guidelines
- Docker Production Guide - Production deployment guide
Community and Forums
- Docker Community - Official Docker community
- Docker Forums - Community discussions
- Stack Overflow Docker - Docker Q&A community
Security and Monitoring
- Trivy - Vulnerability scanner for containers
- Snyk - Security platform for containers
- cAdvisor - Container monitoring tool
This tutorial is part of the DevOps Mastery series by syscook.dev