← กลับ
GitHub ActionsCI/CDTutorial

ตั้ง GitHub Actions ครั้งแรกใน 30 นาที

ทำตามทีละขั้น push code ปุ๊บ deploy ขึ้น server ปั๊บ ไม่ต้อง SSH เอง ไม่ต้องสวดมนต์ก่อน restart

2025-09-05อ่าน 5 นาทีใหม่

ที่ต้องเตรียมก่อนเริ่ม

  • โปรเจค Node.js หรือ Next.js ที่อยู่บน GitHub แล้ว
  • VPS หรือ server ที่ SSH เข้าได้ (ใน example นี้ใช้ Ubuntu)
  • โดเมน + SSH key สำหรับ login server (หรือใช้ password ก็ได้แต่ไม่แนะนำ)

ถ้ายังไม่มี VPS อ่าน Deploy Node.js ขึ้น VPS ก่อน

โครงสร้างที่เราจะทำ

Workflow จะเป็นแบบนี้:

push ขึ้น main
    ↓
GitHub Actions runner เริ่ม
    ↓
checkout code
    ↓
รัน test
    ↓ (ถ้าผ่าน)
SSH เข้า server
    ↓
git pull + build + restart pm2

ทั้งหมดอัตโนมัติ ใช้เวลา 1-3 นาทีต่อ deploy

ขั้นที่ 1: สร้างไฟล์ workflow

ในโปรเจคของคุณสร้าง path นี้:

.github/
└── workflows/
    └── deploy.yml

ชื่อไฟล์ตั้งอะไรก็ได้ ขอให้นามสกุลเป็น .yml หรือ .yaml

ขั้นที่ 2: เขียน workflow

name: CI/CD

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

jobs:
  # Job 1: รัน test
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run lint
        run: npm run lint

      - name: Run tests
        run: npm test

  # Job 2: deploy (รันต่อหลัง test ผ่าน + เฉพาะตอน push main)
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'

    steps:
      - name: Deploy to server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            set -e
            cd /var/www/myapp
            git pull origin main
            npm ci --omit=dev
            npm run build
            pm2 reload ecosystem.config.js --update-env

จุดที่ควรเข้าใจ:

  • npm ci ดีกว่า npm install เพราะใช้ lockfile แม่นกว่า เร็วกว่า เหมาะกับ CI
  • cache: 'npm' ช่วยให้ run ครั้งที่สองเร็วขึ้นมาก (cache node_modules)
  • needs: test หมายความว่า job deploy รอ test ผ่านก่อน
  • if: ทำให้ deploy รันแค่ตอน push เข้า main ไม่ใช่ตอน open PR

ขั้นที่ 3: ตั้ง Secrets

ไปที่ repo → SettingsSecrets and variablesActionsNew repository secret

ใส่ 3 ตัวนี้:

| Secret | ค่า | |---|---| | SERVER_HOST | IP หรือ domain ของ server เช่น 203.0.113.10 | | SERVER_USER | username login ssh เช่น ubuntu หรือ deploy | | SSH_PRIVATE_KEY | private key ทั้งไฟล์ (รวม -----BEGIN ... -----END) |

สำคัญ: private key ที่ใส่นี้ต้องมี public key คู่กันอยู่ในไฟล์ ~/.ssh/authorized_keys บน server

วิธีสร้าง key คู่ใหม่:

# สร้าง key คู่ใหม่ (อย่าใส่ passphrase)
ssh-keygen -t ed25519 -f deploy_key -N ""

# copy public key ขึ้น server
cat deploy_key.pub | ssh ubuntu@your-server \
  "cat >> ~/.ssh/authorized_keys"

# เนื้อหาในไฟล์ deploy_key (private) → ใส่ใน secret SSH_PRIVATE_KEY
cat deploy_key

อย่าใช้ key ที่ใช้กับเครื่องตัวเอง — สร้าง key ใหม่เฉพาะสำหรับ deploy

ขั้นที่ 4: เตรียม server

บน server ต้องมี:

# clone repo (ครั้งแรกเท่านั้น)
cd /var/www
sudo git clone https://github.com/your-org/myapp.git
sudo chown -R $USER:$USER myapp
cd myapp

# ติดตั้งทุกอย่าง
npm ci
npm run build

# start ด้วย pm2
pm2 start ecosystem.config.js
pm2 save

# ตั้ง pm2 ให้ start ตอน reboot
pm2 startup

ไฟล์ ecosystem.config.js ตัวอย่าง:

module.exports = {
  apps: [{
    name: 'myapp',
    script: 'npm',
    args: 'start',
    cwd: '/var/www/myapp',
    env: {
      NODE_ENV: 'production',
      PORT: 3000,
    },
    max_memory_restart: '500M',
  }]
}

ขั้นที่ 5: ทดสอบ

git add .github/workflows/deploy.yml
git commit -m "ci: add deploy workflow"
git push origin main

เปิด GitHub repo → tab Actions จะเห็น workflow กำลังรัน

ถ้าผ่านหมด — เข้า server ดู pm2 list ควรเห็น app uptime เป็นเลขเล็กๆ (เพิ่ง restart)

ปัญหาที่เจอบ่อย

SSH connection timeout → ตรวจสอบว่า:

  • ใส่ port ถ้า server ใช้ port อื่นที่ไม่ใช่ 22 (เพิ่ม port: 2222 ใน step)
  • IP ของ GitHub Actions runner ไม่ได้ block ใน firewall (Actions ใช้ IP range หลายช่วง อย่าใส่ allow-list ลงไป)

Permission denied (publickey) → 99% เกิดจาก private key ใน secret ไม่ตรงกับ public key บน server

git pull ขอ password → ตอน clone ครั้งแรกใช้ HTTPS แล้วต้องเปลี่ยน remote เป็น SSH:

git remote set-url origin [email protected]:your-org/myapp.git

npm ci ฟ้อง package-lock ไม่ตรง → อย่าลืม commit package-lock.json

ขยายต่อ

ลอง enhancement พวกนี้เพิ่มทีหลัง:

  • Slack notification — ใช้ action slackapi/slack-github-action แจ้งเตือนเมื่อ deploy เสร็จ
  • Health check หลัง deploycurl -f https://yourdomain.com/health || exit 1
  • Rollback — เก็บ commit hash ก่อน deploy ใน file ถ้าพังก็ checkout กลับ
  • Multi-environment — แยก workflow deploy-staging.yml กับ deploy-prod.yml

ต่อไปเรามี CI/CD ที่ใช้งานได้จริงแล้ว ทุกครั้งที่ push code ขึ้น main ระบบจะ deploy ให้เอง ตื่นนอนเขียน feature ก่อนนอนกด push พรุ่งนี้ลูกค้าได้ใช้เลย

← ดูบทความอื่น