Multi-Environment Pipeline: Deploy ไป Dev → Staging → Production บน VPS

Multi-Environment Pipeline เป็นแนวปฏิบัติที่ดีในการ deploy applications ผ่าน multiple environments เช่น Development, Staging และ Production โดยแต่ละ environment มี configuration ที่แตกต่างกัน ช่วยให้คุณ test changes อย่างล้วนลึกก่อนนำไปยัง production บน Cloud VPS ของ ผู้ให้บริการโฮสติ้ง บทความนี้จะอธิบายวิธีการสร้าง pipeline ที่มี multiple environments

Multi-Environment Pipeline คืออะไร

Multi-Environment Pipeline คือการจัดการ deployment ไปยัง environments ต่างๆ ในลำดับที่กำหนด โดยปกติจะเป็น Dev → Staging → Production แต่ละ environment มีค่า configuration ต่างกัน เช่น database URLs API endpoints และ feature flags ด้วยการมี multiple environments คุณสามารถ test code ใน safe environment ก่อนนำไปยัง production ลดความเสี่ยงของ bugs หรือ breaking changes

สถาปัตยกรรมของ Dev, Staging, Production

Development Environment: บน local machine หรือ development server ของคุณ ใช้สำหรับ testing features ใหม่ และ debugging staging Environment: ใกล้เคียงกับ production configuration เพื่อทำการ final testing ก่อน release Production Environment: โลก real ที่ end users ใช้งาน ต้อง stable, secure และ high availability

# ตัวอย่าง GitHub Actions workflow สำหรับ multi-environment
name: Multi-Environment Deploy

on:
  push:
    branches:
      - main
      - staging
      - develop

env:
  REGISTRY: ghcr.io

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      image_tag: ${{ steps.meta.outputs.tags }}
    steps:
      - uses: actions/checkout@v3
      
      - name: Build Docker image
        uses: docker/build-push-action@v4
        with:
          context: .
          push: false
          tags: ${{ env.REGISTRY }}/myapp:${{ github.sha }}

  deploy-dev:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'
    environment: development
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Dev
        env:
          DEPLOY_KEY: ${{ secrets.DEV_DEPLOY_KEY }}
          DEPLOY_HOST: dev.myapp.local
          DB_HOST: dev-db.myapp.local
          DB_NAME: myapp_dev
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh -i ~/.ssh/deploy_key deploy@$DEPLOY_HOST \
            "cd /var/www/myapp && docker pull ${{ needs.build.outputs.image_tag }} && docker-compose up -d"

  deploy-staging:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/staging'
    environment: staging
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Staging
        env:
          DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
          DEPLOY_HOST: staging.myapp.com
          DB_HOST: staging-db.myapp.com
          DB_NAME: myapp_staging
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh -i ~/.ssh/deploy_key deploy@$DEPLOY_HOST \
            "cd /var/www/myapp && docker pull ${{ needs.build.outputs.image_tag }} && docker-compose up -d"

  deploy-prod:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Production
        env:
          DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}
          DEPLOY_HOST: app.myapp.com
          DB_HOST: prod-db.myapp.com
          DB_NAME: myapp_prod
        run: |
          mkdir -p ~/.ssh
          echo "$DEPLOY_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh -i ~/.ssh/deploy_key deploy@$DEPLOY_HOST \
            "cd /var/www/myapp && docker pull ${{ needs.build.outputs.image_tag }} && docker-compose up -d"

Environment Variables และ Configuration Management

แต่ละ environment ต้องมี configuration ที่แตกต่างกัน เช่น database URLs API keys และ feature flags ส่วนใหญ่จะใช้ environment variables เพื่อจัดการค่า configuration ใน CI/CD pipeline คุณสามารถตั้งค่า environment variables สำหรับแต่ละ environment ใน GitHub Environments

# Docker Compose file ที่ใช้ environment variables
version: '3.8'

services:
  app:
    image: myapp:latest
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - API_KEY=${API_KEY}
      - REDIS_URL=${REDIS_URL}
      - LOG_LEVEL=${LOG_LEVEL}
      - FEATURE_FLAG_NEW_UI=${FEATURE_FLAG_NEW_UI}
    ports:
      - "${APP_PORT}:8080"
    depends_on:
      - db
      - redis

  db:
    image: postgres:14
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data

  redis:
    image: redis:7
    ports:
      - "${REDIS_PORT}:6379"

volumes:
  db_data:

# ไฟล์ .env.dev
DATABASE_URL=postgres://postgres:dev_pass@localhost/myapp_dev
API_KEY=dev_api_key_123
REDIS_URL=redis://localhost:6379/0
LOG_LEVEL=debug
FEATURE_FLAG_NEW_UI=false
APP_PORT=3000
DB_NAME=myapp_dev
DB_USER=postgres
DB_PASSWORD=dev_pass
REDIS_PORT=6379

# ไฟล์ .env.staging
DATABASE_URL=postgres://postgres:staging_pass@staging-db/myapp_staging
API_KEY=staging_api_key_456
REDIS_URL=redis://staging-redis:6379/0
LOG_LEVEL=info
FEATURE_FLAG_NEW_UI=true
APP_PORT=80
DB_NAME=myapp_staging
DB_USER=postgres
DB_PASSWORD=staging_pass
REDIS_PORT=6379

Approval Gates และ Manual Approvals

ความเสี่ยงของการ deploy ไปยัง production นั้นสูง ดังนั้นคุณควรตั้งค่า approval gates เพื่อให้ทีมทำการ review และ approve deployment ก่อนนำไปยัง production GitHub Actions support environment protection rules ซึ่งสามารถตั้งค่า approval ได้

# ตั้งค่า approval gate สำหรับ production
# 1. ไปที่ Repository Settings > Environments
# 2. สร้าง environment "production"
# 3. ใน Deployment protection rules
# 4. เลือก "Required reviewers"
# 5. เลือก users ที่ต้อง approve

# ในตัว workflow
jobs:
  deploy-prod:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://myapp.com
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Production
        run: |
          echo "Deploying to production..."
          # deployment steps

Rollback Strategy และ Health Checks

เมื่อเกิดปัญหาหลังจาก deploy ต้องมีวิธีการ rollback ไปยัง version ก่อนหน้า ด้วยการเก็บ version tags ของ Docker images คุณสามารถ rollback ได้อย่างรวดเร็ว นอกจากนี้ต้องมี health checks เพื่อ verify ว่า application กำลังทำงานได้ดี

# Health check ในการ deploy
- name: Health Check
  run: |
    for i in {1..30}; do
      if curl -f http://localhost:3000/health; then
        echo "Application is healthy"
        exit 0
      fi
      sleep 10
    done
    echo "Application failed health check"
    exit 1

# Rollback script
#!/bin/bash
set -e

DEPLOY_HOST="$1"
PREVIOUS_VERSION="$2"

echo "Rolling back to version $PREVIOUS_VERSION"
ssh deploy@$DEPLOY_HOST \
  "cd /var/www/myapp && \
   docker pull myapp:$PREVIOUS_VERSION && \
   docker-compose down && \
   docker tag myapp:$PREVIOUS_VERSION myapp:latest && \
   docker-compose up -d"

echo "Rollback completed successfully"

สรุป

Multi-Environment Pipeline ช่วยให้คุณจัดการการ deploy ไปยัง environments ต่างๆ อย่างเป็นระบบ ลดความเสี่ยงของ bugs และ breaking changes ในการ deploy ผ่าน GitHub Actions คุณสามารถจัดการ multiple environments ได้อย่างมีประสิทธิภาพ พร้อมสำหรับ approval gates, rollback strategy และ health checks Cloud VPS ของ ผู้ให้บริการโฮสติ้ง เป็น platform ที่เหมาะสำหรับการ host multi-environment deployments ด้วยความยืดหยุ่นและ reliability