Skip to main content
โšก Calmops

Deployment: Docker, Kubernetes, Cloud

Deployment: Docker, Kubernetes, Cloud

Deployment is critical for getting applications to production. This article covers containerization and orchestration.

Introduction

Deployment provides:

  • Containerization
  • Orchestration
  • Scalability
  • Reliability
  • Automation

Understanding deployment helps you:

  • Containerize applications
  • Orchestrate containers
  • Deploy to cloud
  • Scale applications
  • Automate deployments

Docker Containerization

Dockerfile

# โœ… Good: Multi-stage Dockerfile
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

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY --from=builder /app/dist ./dist

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js

CMD ["node", "dist/index.js"]

# โœ… Good: .dockerignore
node_modules
npm-debug.log
.git
.env
.DS_Store
dist
coverage

Docker Compose

# โœ… Good: docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: mongodb://db:27017/myapp
      REDIS_URL: redis://redis:6379
    depends_on:
      - db
      - redis
    restart: unless-stopped
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    image: mongo:5
    volumes:
      - mongo-data:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
    restart: unless-stopped
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    networks:
      - app-network

volumes:
  mongo-data:

networks:
  app-network:
    driver: bridge

Kubernetes Deployment

Kubernetes Manifests

# โœ… Good: Deployment manifest
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: myapp:1.0.0
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: database-url
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

# โœ… Good: Service manifest
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: LoadBalancer

# โœ… Good: ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  CACHE_TTL: "3600"

# โœ… Good: Secret
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
stringData:
  database-url: mongodb://user:password@db:27017/myapp
  jwt-secret: your-secret-key

Kubernetes Commands

# โœ… Good: Deploy application
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

# โœ… Good: Check deployment status
kubectl get deployments
kubectl get pods
kubectl get services

# โœ… Good: View logs
kubectl logs deployment/app-deployment
kubectl logs pod-name

# โœ… Good: Scale deployment
kubectl scale deployment app-deployment --replicas=5

# โœ… Good: Update image
kubectl set image deployment/app-deployment app=myapp:2.0.0

# โœ… Good: Rollback
kubectl rollout undo deployment/app-deployment

# โœ… Good: Delete resources
kubectl delete deployment app-deployment
kubectl delete service app-service

Cloud Deployment

AWS Deployment

# โœ… Good: Deploy to Elastic Beanstalk
eb init -p node.js-18 my-app
eb create production
eb deploy

# โœ… Good: Deploy to ECS
aws ecs create-cluster --cluster-name my-cluster
aws ecs register-task-definition --cli-input-json file://task-definition.json
aws ecs create-service --cluster my-cluster --service-name my-service --task-definition my-task:1 --desired-count 3

# โœ… Good: Deploy to Lambda
zip -r lambda-function.zip .
aws lambda create-function --function-name my-function --runtime nodejs18.x --role arn:aws:iam::123456789012:role/lambda-role --handler index.handler --zip-file fileb://lambda-function.zip

Google Cloud Deployment

# โœ… Good: Deploy to Cloud Run
gcloud run deploy my-app --source . --platform managed --region us-central1

# โœ… Good: Deploy to App Engine
gcloud app deploy

# โœ… Good: Deploy to GKE
gcloud container clusters create my-cluster
gcloud container clusters get-credentials my-cluster
kubectl apply -f deployment.yaml

Azure Deployment

# โœ… Good: Deploy to App Service
az webapp up --name my-app --resource-group my-group

# โœ… Good: Deploy to Container Instances
az container create --resource-group my-group --name my-container --image myapp:1.0.0 --ports 3000

# โœ… Good: Deploy to AKS
az aks create --resource-group my-group --name my-cluster
az aks get-credentials --resource-group my-group --name my-cluster
kubectl apply -f deployment.yaml

CI/CD Pipelines

GitHub Actions

# โœ… Good: GitHub Actions workflow
name: Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: Install dependencies
      run: npm ci

    - name: Run tests
      run: npm test

    - name: Build
      run: npm run build

    - name: Build Docker image
      run: docker build -t myapp:${{ github.sha }} .

    - name: Push to Docker Hub
      run: |
        echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
        docker push myapp:${{ github.sha }}

    - name: Deploy to Kubernetes
      run: |
        kubectl set image deployment/app-deployment app=myapp:${{ github.sha }}

GitLab CI

# โœ… Good: GitLab CI pipeline
stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: node:18
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  image: node:18
  script:
    - npm ci
    - npm test

deploy:
  stage: deploy
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t myapp:$CI_COMMIT_SHA .
    - docker push myapp:$CI_COMMIT_SHA
    - kubectl set image deployment/app-deployment app=myapp:$CI_COMMIT_SHA
  only:
    - main

Monitoring and Logging

Application Monitoring

// โœ… Good: Health check endpoint
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    timestamp: new Date(),
    uptime: process.uptime()
  });
});

// โœ… Good: Readiness check
app.get('/ready', async (req, res) => {
  try {
    await checkDatabaseConnection();
    res.json({ ready: true });
  } catch (err) {
    res.status(503).json({ ready: false });
  }
});

// โœ… Good: Metrics endpoint
app.get('/metrics', (req, res) => {
  res.json({
    memory: process.memoryUsage(),
    uptime: process.uptime(),
    requests: requestCount
  });
});

Logging

// โœ… Good: Structured logging
const winston = require('winston');

const logger = winston.createLogger({
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

logger.info('Application started', {
  version: '1.0.0',
  environment: process.env.NODE_ENV
});

logger.error('Database connection failed', {
  error: err.message,
  timestamp: new Date()
});

Best Practices

  1. Use multi-stage builds:

    # โœ… Good: Multi-stage
    FROM node:18 AS builder
    RUN npm ci && npm run build
    
    FROM node:18
    COPY --from=builder /app/dist ./dist
    
    # โŒ Bad: Single stage
    FROM node:18
    COPY . .
    RUN npm ci
    
  2. Set resource limits:

    # โœ… Good: Resource limits
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"
    
    # โŒ Bad: No limits
    
  3. Use health checks:

    # โœ… Good: Health checks
    livenessProbe:
      httpGet:
        path: /health
        port: 3000
      initialDelaySeconds: 30
    
    # โŒ Bad: No health checks
    

Summary

Deployment is essential. Key takeaways:

  • Containerize with Docker
  • Orchestrate with Kubernetes
  • Deploy to cloud platforms
  • Implement CI/CD pipelines
  • Monitor applications
  • Use health checks
  • Set resource limits
  • Automate deployments

Next Steps

Comments