Docker & Containers 🐳
Containerize your Angular applications with Docker for consistent, portable, and scalable deployments. Learn Docker best practices, multi-stage builds, and container orchestration.
🎯 Why Docker for Angular?
Section titled “🎯 Why Docker for Angular?”Benefits:
- 🔄 Consistency - Same environment everywhere
- 📦 Portability - Run anywhere Docker runs
- ⚡ Isolation - No dependency conflicts
- 🚀 Scalability - Easy horizontal scaling
- 🔧 DevOps Ready - CI/CD integration
Use Cases:
- Production deployments
- Development environments
- Microservices architecture
- Cloud-native applications
- Kubernetes deployments
🚀 Basic Dockerfile
Section titled “🚀 Basic Dockerfile”Simple Production Dockerfile
Section titled “Simple Production Dockerfile”# Stage 1: Build the Angular applicationFROM node:20-alpine AS build
WORKDIR /app
# Copy package filesCOPY package*.json ./
# Install dependenciesRUN npm ci
# Copy source codeCOPY . .
# Build for productionRUN npm run build -- --configuration production
# Stage 2: Serve with NginxFROM nginx:alpine
# Copy built app to nginxCOPY --from=build /app/dist/your-app-name/browser /usr/share/nginx/html
# Copy nginx configurationCOPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose portEXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Nginx Configuration
Section titled “Nginx Configuration”server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html;
# Gzip compression gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;
# Cache static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; }
# Angular routing location / { try_files $uri $uri/ /index.html; add_header Cache-Control "no-cache"; }
# Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always;}🎨 Optimized Multi-Stage Build
Section titled “🎨 Optimized Multi-Stage Build”Production-Ready Dockerfile
Section titled “Production-Ready Dockerfile”# Stage 1: BuildFROM node:20-alpine AS builder
# Set working directoryWORKDIR /app
# Copy package filesCOPY package*.json ./
# Install dependencies with clean installRUN npm ci --only=production && \ npm cache clean --force
# Copy sourceCOPY . .
# Build with production configurationRUN npm run build -- --configuration production --output-hashing=all
# Stage 2: ProductionFROM nginx:1.25-alpine
# Install curl for health checksRUN apk add --no-cache curl
# Copy custom nginx configCOPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy built applicationCOPY --from=builder /app/dist/your-app-name/browser /usr/share/nginx/html
# Add non-root userRUN chown -R nginx:nginx /usr/share/nginx/html && \ chmod -R 755 /usr/share/nginx/html
# Health checkHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost/ || exit 1
# Expose portEXPOSE 80
# Run as non-root userUSER nginx
CMD ["nginx", "-g", "daemon off;"]🎨 Real-World Examples
Section titled “🎨 Real-World Examples”Note: Always use multi-stage builds to minimize image size.
1. Development Docker Setup
Section titled “1. Development Docker Setup”Let’s create a Docker setup for development with hot reload.
FROM node:20-alpine
WORKDIR /app
# Install dependenciesCOPY package*.json ./RUN npm install
# Copy sourceCOPY . .
# Expose portEXPOSE 4200
# Start development serverCMD ["npm", "start", "--", "--host", "0.0.0.0", "--poll", "2000"]docker-compose.yml for Development:
version: '3.8'
services: angular-app: build: context: . dockerfile: Dockerfile.dev ports: - "4200:4200" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development command: npm start -- --host 0.0.0.0 --poll 2000Usage:
# Start development environmentdocker-compose up
# Rebuild and startdocker-compose up --build
# Stopdocker-compose down2. Production Docker Compose
Section titled “2. Production Docker Compose”Let’s create a complete production setup with nginx and backend.
version: '3.8'
services: frontend: build: context: . dockerfile: Dockerfile ports: - "80:80" environment: - NODE_ENV=production restart: unless-stopped networks: - app-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s
backend: image: your-backend-image:latest ports: - "3000:3000" environment: - DATABASE_URL=${DATABASE_URL} - JWT_SECRET=${JWT_SECRET} restart: unless-stopped networks: - app-network depends_on: - database
database: image: postgres:15-alpine volumes: - postgres-data:/var/lib/postgresql/data environment: - POSTGRES_DB=myapp - POSTGRES_USER=user - POSTGRES_PASSWORD=${DB_PASSWORD} restart: unless-stopped networks: - app-network
networks: app-network: driver: bridge
volumes: postgres-data:3. Environment-Specific Builds
Section titled “3. Environment-Specific Builds”Let’s create Dockerfiles for different environments.
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./RUN npm ci
COPY . .
# Build for stagingRUN npm run build -- --configuration staging
FROM nginx:alpine
COPY --from=build /app/dist/your-app-name/browser /usr/share/nginx/htmlCOPY nginx.staging.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Build Script:
#!/bin/bashENV=${1:-production}
case $ENV in development) docker build -f Dockerfile.dev -t myapp:dev . ;; staging) docker build -f Dockerfile.staging -t myapp:staging . ;; production) docker build -f Dockerfile -t myapp:prod . ;; *) echo "Usage: ./build-docker.sh [development|staging|production]" exit 1 ;;esac
echo "✅ Built image: myapp:$ENV"4. Docker with Build Arguments
Section titled “4. Docker with Build Arguments”Let’s use build arguments for flexible configurations.
# Dockerfile with build argsARG NODE_VERSION=20FROM node:${NODE_VERSION}-alpine AS build
ARG CONFIGURATION=productionARG API_URLARG APP_VERSION
WORKDIR /app
COPY package*.json ./RUN npm ci
COPY . .
# Pass build args to AngularRUN npm run build -- \ --configuration ${CONFIGURATION} \ --base-href / \ --deploy-url /
# Replace environment variables in built filesRUN sed -i "s|API_URL_PLACEHOLDER|${API_URL}|g" /app/dist/*/browser/main*.js
FROM nginx:alpine
LABEL version="${APP_VERSION}"LABEL description="Angular Application"
COPY --from=build /app/dist/your-app-name/browser /usr/share/nginx/htmlCOPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Build with Arguments:
# Build with custom argumentsdocker build \ --build-arg NODE_VERSION=20 \ --build-arg CONFIGURATION=production \ --build-arg API_URL=https://api.example.com \ --build-arg APP_VERSION=1.0.0 \ -t myapp:1.0.0 \ .5. Kubernetes Deployment
Section titled “5. Kubernetes Deployment”Let’s create Kubernetes manifests for deploying the containerized app.
apiVersion: apps/v1kind: Deploymentmetadata: name: angular-app labels: app: angular-appspec: replicas: 3 selector: matchLabels: app: angular-app template: metadata: labels: app: angular-app spec: containers: - name: angular-app image: your-registry/angular-app:latest ports: - containerPort: 80 resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m" livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 5---apiVersion: v1kind: Servicemetadata: name: angular-app-servicespec: selector: app: angular-app ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: angular-app-ingress annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prodspec: tls: - hosts: - app.example.com secretName: angular-app-tls rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: angular-app-service port: number: 80✅ Best Practices
Section titled “✅ Best Practices”1. Use Multi-Stage Builds
Section titled “1. Use Multi-Stage Builds”# ✅ Good - Multi-stage buildFROM node:20-alpine AS build# Build stage...
FROM nginx:alpineCOPY --from=build /app/dist /usr/share/nginx/html
# ❌ Avoid - Single stage with build toolsFROM node:20RUN npm install && npm run build# Includes unnecessary build dependencies2. Minimize Image Size
Section titled “2. Minimize Image Size”# ✅ Good - Alpine base, clean cacheFROM node:20-alpineRUN npm ci && npm cache clean --force
# ❌ Avoid - Full node imageFROM node:20RUN npm install3. Use .dockerignore
Section titled “3. Use .dockerignore”node_modulesdist.git.gitignore*.md.angular.vscodecoveragee2e4. Security Best Practices
Section titled “4. Security Best Practices”# ✅ Good - Run as non-root userFROM nginx:alpineRUN addgroup -g 1001 -S appuser && \ adduser -u 1001 -S appuser -G appuserUSER appuser
# ✅ Good - Health checksHEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 15. Optimize Layer Caching
Section titled “5. Optimize Layer Caching”# ✅ Good - Copy package files firstCOPY package*.json ./RUN npm ciCOPY . .
# ❌ Avoid - Copy everything firstCOPY . .RUN npm ci🎯 Docker Commands Cheat Sheet
Section titled “🎯 Docker Commands Cheat Sheet”# Build imagedocker build -t myapp:latest .
# Run containerdocker run -p 8080:80 myapp:latest
# Run in backgrounddocker run -d -p 8080:80 --name myapp myapp:latest
# View logsdocker logs myappdocker logs -f myapp # Follow logs
# Stop containerdocker stop myapp
# Remove containerdocker rm myapp
# Remove imagedocker rmi myapp:latest
# Execute command in containerdocker exec -it myapp sh
# View running containersdocker ps
# View all containersdocker ps -a
# Clean updocker system prune -a🎓 Learning Checklist
Section titled “🎓 Learning Checklist”- Understand Docker basics
- Create multi-stage Dockerfiles
- Optimize image size
- Configure nginx for Angular
- Use docker-compose
- Implement health checks
- Deploy to Kubernetes
- Follow security best practices
🚀 Next Steps
Section titled “🚀 Next Steps”- CI/CD Pipelines - Automate Docker builds
- Deployment Strategies - Choose deployment approach
- Performance Optimization - Optimize before containerizing
Pro Tip: Always use multi-stage builds to keep images small! Use Alpine-based images, implement health checks, and run containers as non-root users for security! 🐳