GitHub Actions: สร้าง CD Pipeline Deploy ไปยัง Cloud VPS อัตโนมัติ

ในยุคของการพัฒนาซอฟต์แวร์สมัยใหม่ การทำ Continuous Deployment (CD) ผ่าน GitHub Actions ได้กลายเป็นเครื่องมือที่จำเป็นสำหรับทีมพัฒนา ช่วยให้การปล่อยรุ่นโปรแกรมเกิดขึ้นอัตโนมัติและลดข้อผิดพลาดที่มาจากการจัดการด้วยตนเอง บทความนี้จะแนะนำวิธีการสร้าง CD Pipeline ด้วย GitHub Actions เพื่อ Deploy ไปยัง Cloud VPS ของ ผู้ให้บริการโฮสติ้ง อย่างอัตโนมัติ

CD Pipeline คืออะไร และเหตุใดจึงสำคัญ

Continuous Deployment (CD) Pipeline เป็นกระบวนการอัตโนมัติที่ทำให้โค้ดใหม่สามารถปล่อยไปยังเซิร์ฟเวอร์ Production ได้อย่างรวดเร็วและปลอดภัย เมื่อมีการ Push โค้ดขึ้น GitHub แล้ว Pipeline จะทำการทดสอบและ Deploy โดยไม่ต้องแทรกแซงจากมนุษย์

  • ความเร็ว: ลดเวลาในการปล่อย Feature ใหม่จากหลายชั่วโมงเหลือเพียงนาที
  • ความปลอดภัย: ลดความเสี่ยงจากข้อผิดพลาดของมนุษย์ผ่านการทดสอบอัตโนมัติ
  • ความเสถียร: มี Rollback อย่างรวดเร็วหากเกิดปัญหา
  • เหมาะสมกับ Cloud VPS: เหมาะกับบริการ Cloud VPS ของ ผู้ให้บริการโฮสติ้ง ที่ให้ความยืดหยุ่นสูง

ตั้งค่า SSH Key สำหรับ Deploy

ขั้นตอนแรกในการสร้าง CD Pipeline คือการตั้งค่า SSH Key ที่ใช้สำหรับการเชื่อมต่อและ Deploy ไปยัง Cloud VPS ของคุณ ซึ่งเป็นวิธีที่ปลอดภัยที่สุด

# สร้าง SSH Key pair บน Cloud VPS
ssh-keygen -t ed25519 -f github-deploy-key -N ""

# เพิ่ม Public Key ไปยัง authorized_keys
cat github-deploy-key.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# ดูเนื้อหา Private Key (นำไปใส่ใน GitHub Secrets)
cat github-deploy-key

GitHub Secrets: การจัดการข้อมูลอย่างปลอดภัย

GitHub Secrets เป็นวิธีที่ปลอดภัยในการเก็บข้อมูลที่มีความสำคัญ เช่น SSH Keys, Passwords, และ API Tokens ไปที่ Repository Settings > Secrets and variables > Actions เพื่อเพิ่ม Secrets เหล่านี้:

  • DEPLOY_PRIVATE_KEY — Private SSH Key สำหรับการเชื่อมต่อ
  • DEPLOY_HOST — IP Address หรือ Domain ของ Cloud VPS
  • DEPLOY_USER — Username สำหรับ SSH
  • DEPLOY_PATH — Path สำหรับ Deploy บน Server

สร้าง GitHub Actions Workflow สำหรับ Deploy ผ่าน SSH

สร้างไฟล์ .github/workflows/deploy.yml ใน Repository:

name: CD Pipeline - Deploy to Cloud VPS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup SSH key
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy to Cloud VPS
        run: |
          ssh -i ~/.ssh/deploy_key ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF'
          cd ${{ secrets.DEPLOY_PATH }}
          git pull origin main
          npm install --production
          npm run build
          pm2 restart app
          EOF

      - name: Cleanup SSH key
        if: always()
        run: rm -f ~/.ssh/deploy_key

Deploy ด้วย rsync: วิธีที่มีประสิทธิภาพสูง

rsync เหมาะสำหรับการ Deploy ที่ต้องการความแม่นยำละเอียดไฟล์ ต้องการประหยัด Bandwidth หรือแอป Pre-built:

name: Deploy with rsync

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build application
        run: |
          npm ci
          npm run build

      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy with rsync
        run: |
          rsync -avz --delete \
            -e "ssh -i ~/.ssh/deploy_key" \
            ./dist/ \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/

      - name: Restart service
        run: |
          ssh -i ~/.ssh/deploy_key \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \
            "systemctl restart myapp"

      - name: Cleanup
        if: always()
        run: rm -f ~/.ssh/deploy_key

Docker Deployment Workflow

สำหรับแอพพลิเคชันที่ใช้ Docker ให้สร้าง Workflow ที่ Build Image และ Deploy ได้อย่างอัตโนมัติ:

name: Docker CD Pipeline

on:
  push:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

      - name: Deploy to Cloud VPS
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
          
          ssh -i ~/.ssh/deploy_key \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF'
          docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
          docker-compose down && docker-compose up -d
          EOF
          
          rm -f ~/.ssh/deploy_key

Environment Protection Rules

GitHub มี Environment Protection Rules ที่ช่วยควบคุมการ Deploy ไปยัง Production ไปที่ Repository Settings > Environments และสร้าง Environment ชื่อ "production":

  • Required reviewers: เลือกสมาชิกที่ต้องอนุมัติการ Deploy
  • Deployment branches: จำกัดให้เฉพาะ Branch "main" เท่านั้น
  • Environment secrets: Secrets เฉพาะสำหรับ Production

Rollback Strategy: แผนการสำรองเมื่อเกิดปัญหา

การมี Rollback Strategy ที่ดีจึงเป็นสิ่งสำคัญใน CD Pipeline สามารถ Rollback ได้โดยใช้ workflow_dispatch:

name: Rollback Deployment

on:
  workflow_dispatch:
    inputs:
      commit:
        description: 'Commit SHA to rollback to'
        required: true
        type: string

jobs:
  rollback:
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Checkout specific commit
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit }}

      - name: Deploy previous version
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
          
          ssh -i ~/.ssh/deploy_key \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF'
          cd ${{ secrets.DEPLOY_PATH }}
          git fetch --all
          git checkout ${{ github.event.inputs.commit }}
          npm install --production && npm run build
          pm2 restart app
          EOF
          
          rm -f ~/.ssh/deploy_key

ตัวอย่าง Complete CI/CD Workflow

ตัวอย่าง Workflow ครบวงจรที่รวมทั้ง CI และ CD ด้วยกัน:

name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  # Phase 1: CI - Test
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm test

  # Phase 2: CD - Deploy (only on main branch push)
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production

    steps:
      - uses: actions/checkout@v4
      
      - name: Build
        run: |
          npm ci
          npm run build

      - name: Deploy to ผู้ให้บริการโฮสติ้ง Cloud VPS
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
          
          rsync -avz --delete \
            -e "ssh -i ~/.ssh/deploy_key" \
            ./dist/ \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/
          
          ssh -i ~/.ssh/deploy_key \
            ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \
            "pm2 restart myapp"
          
          rm -f ~/.ssh/deploy_key

      - name: Notify on success
        if: success()
        run: echo "Deploy completed successfully!"

ข้อปฏิบัติที่ดีสำหรับ CD Pipeline

  • ตั้งค่า Branch Protection: ใช้ Branch Protection Rules เพื่อให้ต้องผ่าน CI/CD ก่อน Merge
  • ทำการทดสอบอัตโนมัติ: เพิ่ม Test Step ก่อน Deploy เสมอ
  • จัดการ Secrets อย่างปลอดภัย: ไม่เคยใส่ Secrets ลงใน Workflow file โดยตรง
  • Health Check: ตรวจสอบหลัง Deploy ว่าแอพตอบสนองเป็นปกติ
  • Notification: ติดตั้ง Slack หรือ Email เพื่อแจ้งสถานะการ Deploy

สรุป

การสร้าง CD Pipeline ด้วย GitHub Actions สำหรับ Deploy ไปยัง Cloud VPS ของ ผู้ให้บริการโฮสติ้ง เป็นวิธีที่มีประสิทธิภาพในการเพิ่มความเร็วและความปลอดภัยในการปล่อยโปรแกรม ด้วยการตั้งค่า SSH Key อย่างถูกต้อง จัดการ GitHub Secrets อย่างปลอดภัย และสร้าง Workflow ที่เหมาะสม คุณจะสามารถ Deploy โปรแกรมของคุณได้อย่างอัตโนมัติและเชื่อถือได้

ผู้ให้บริการโฮสติ้ง Cloud VPS มอบความยืดหยุ่นและการควบคุมเต็มรูปแบบที่จำเป็นสำหรับการสร้าง CD Pipeline ที่มีประสิทธิภาพ สามารถติดตั้ง Software ใดๆ และตั้งค่าได้ตามต้องการ พร้อมทีม Support ที่พร้อมช่วยเหลือ