Skip to main content
Case Studies

เบื้องหลัง CI/CD Pipeline ของ Enersys — จาก git push ถึงเว็บไซต์ Live ใน 5 นาที

เปิดเบื้องหลังวิธีที่เราส่งมอบเว็บไซต์ enersys.co.th ขึ้น Production — ตั้งแต่ Pull Request, Docker Multi-Stage Build, DigitalOcean Registry จนถึง Kubernetes Rolling Update บน Self-Hosted Runner

13 มี.ค. 20268 นาที
CI/CDDevOpsDockerKubernetesGitHub ActionsSelf-Hosted Runner

ทำไมต้องเล่าเรื่อง Pipeline ของตัวเอง?

เวลาเราพูดเรื่อง CI/CD กับลูกค้า คำถามที่ได้ยินบ่อยที่สุดคือ "แล้วพวกคุณเองใช้อะไร?"

เราเชื่อว่าวิธีที่ดีที่สุดในการพิสูจน์ความเชี่ยวชาญคือการโชว์ว่าเราใช้สิ่งที่เราแนะนำกับตัวเองด้วย บทความนี้จะเปิดเบื้องหลัง Pipeline จริงที่ส่งมอบเว็บไซต์ enersys.co.th — ตั้งแต่นักพัฒนากด push จนถึงเว็บไซต์ Live

CI/CD Pipeline Overview — จาก Git Push ถึง Kubernetes Deploy


ภาพรวม: จาก Code สู่ Production

Pipeline ของเราแบ่งเป็น 2 เส้นทางหลัก ที่ trigger จากเหตุการณ์ต่างกัน:

  1. PR Validation — ทุกครั้งที่เปิด Pull Request ระบบจะ Build และทดสอบอัตโนมัติ
  2. Release & Deploy — เมื่อ Tag version ใหม่ ระบบจะ Build, Push, และ Deploy ขึ้น Production

ทั้งสอง Pipeline รันบน Self-Hosted Runner ที่ตั้งอยู่บนเครื่อง Ubuntu ของเราเอง — ไม่ใช่ GitHub-hosted runner ที่ต้องเสียเวลา provision VM ใหม่ทุกครั้ง


เส้นทางที่ 1: PR Validation

ทุกครั้งที่นักพัฒนาเปิด Pull Request จะมี 2 Workflow ทำงานพร้อมกัน:

PR Validation Pipeline — Build และ Lighthouse ทำงานคู่ขนาน

Build Validation

Workflow แรกทดสอบว่า Docker Image ทั้ง 2 ตัว (Web และ API) สามารถ Build สำเร็จหรือไม่ — แต่ ไม่ Push ไปที่ Registry เป็นการตรวจสอบว่าโค้ดใหม่ไม่ทำให้ Build พัง

สิ่งที่น่าสนใจคือเราใช้ Docker Buildx Cache ที่เก็บไว้บน Self-Hosted Runner — ครั้งถัดไปที่ Build, Layer ที่ไม่เปลี่ยนจะถูกข้ามไปทันที ทำให้ Build ที่ปกติใช้เวลาหลายนาที เหลือแค่ไม่กี่วินาที

Lighthouse Performance Audit

Workflow ที่สองจริงจังกว่า — มันจะ Build เว็บไซต์ทั้งหมด แล้ว Serve ขึ้นมาจริงๆ บน localhost เพื่อรัน Lighthouse Audit 3 รอบ

เกณฑ์ที่ต้องผ่าน:

  • Performance ≥ 60% — ถ้าต่ำกว่านี้ PR จะ Fail ทันที
  • Accessibility ≥ 80% — เราให้ความสำคัญกับการเข้าถึง
  • SEO ≥ 80% — เว็บไซต์ต้องพร้อมสำหรับ Search Engine
  • Best Practices ≥ 80% — มาตรฐานพื้นฐาน

ผลลัพธ์ถูกเก็บเป็น Artifact ไว้ดูย้อนหลังได้ 30 วัน ทำให้เราติดตามได้ว่า Performance เปลี่ยนแปลงอย่างไรในแต่ละ PR


เส้นทางที่ 2: Release & Deploy

เมื่อ PR ผ่านการ Review และ Merge แล้ว ขั้นตอนถัดไปคือการ Tag version เช่น v1.1.178 — นี่คือ Trigger ที่ทำให้ทุกอย่างเกิดขึ้น:

Release & Deploy Pipeline — จาก Tag ถึง Kubernetes Rolling Update

ขั้นตอนที่ 1: Docker Multi-Stage Build

หัวใจของ Pipeline คือ Docker Build แบบ Multi-Stage — เทคนิคที่ทำให้ Production Image เล็กและปลอดภัยที่สุดเท่าที่จะทำได้:

Docker Multi-Stage Build — 3 ขั้นสำหรับ Web, 2 ขั้นสำหรับ API

Web Frontend (3 Stages):

Stage แรกติดตั้ง Dependencies ทั้งหมดที่ต้องใช้ใน Monorepo Stage ที่สองรัน Build เพื่อ Export เว็บไซต์เป็น Static HTML/CSS/JS และ Stage สุดท้ายคือตัว Production จริง — Nginx Alpine ที่เสิร์ฟเฉพาะ Static Files ไม่มี Node.js ไม่มี Source Code ไม่มี Dependencies ที่ไม่จำเป็น

ผลลัพธ์คือ Image ขนาดประมาณ 22 MB ที่เบาและเร็ว

API Backend (2 Stages):

Stage แรก Compile TypeScript เป็น JavaScript พร้อม Generate Prisma Client Stage สุดท้ายเก็บเฉพาะ Compiled Code, Prisma Client และ Production Dependencies — ลบ Dev Dependencies, Source Code และ Build Tools ออกทั้งหมด

ขั้นตอนที่ 2: Push ไป Container Registry

Image ทั้ง 2 ตัวถูก Push ไปที่ DigitalOcean Container Registry พร้อม 2 Tags:

  • Tag เฉพาะ version เช่น v1.1.178 — สำหรับ Rollback ถ้าจำเป็น
  • Tag latest — สำหรับ Reference ล่าสุด

ขั้นตอนที่ 3: Kubernetes Deployment

Pipeline จัดการ Kubernetes แบบครบวงจร:

Secrets & Configuration — สร้าง Secrets สำหรับ Database Connection, API Keys ต่างๆ (Mailgun, LINE Messaging, Google Forms) ทั้งหมดจัดการผ่าน GitHub Secrets ไม่มีค่า Sensitive ใดถูก Hardcode

Rolling Update — Kubernetes จะค่อยๆ เปลี่ยน Pod ทีละตัว:

  • Pod ใหม่เริ่มทำงานและรอให้ Readiness Probe ผ่าน (ตรวจสอบ /healthz ทุก 5 วินาที)
  • เมื่อ Pod ใหม่พร้อม Traffic จะถูกเปลี่ยนเส้นทาง
  • Pod เก่าถูก Drain อย่างสุภาพ
  • ไม่มี Downtime แม้แต่วินาทีเดียว

ขั้นตอนที่ 4: Autopublish

หลัง Deploy สำเร็จ Pipeline จะ Commit Kubernetes Manifest ที่อัปเดตแล้วกลับไปที่ main — ทำให้ Git Repository เป็น Single Source of Truth เสมอ ดูจาก Manifest ก็รู้ว่า Production กำลังรันอะไร Version อะไร


ตัวเลขจริงจาก GitHub Actions: ก่อน vs หลัง Self-Hosted Runner

เราไม่ได้แค่รู้สึกว่า "เร็วขึ้น" — เรามีข้อมูลจาก 49 Release ที่ผ่านมาพิสูจน์ได้ชัดเจน

ภาพรวมเปรียบเทียบ

Metric ubuntu-latest (48 runs) Self-Hosted (v1.1.179+)
เวลาเฉลี่ย 8.5 นาที 5.3 นาที
เร็วสุด 6.7 นาที 5.3 นาที
ช้าสุด 19.0 นาที 5.3 นาที

ลดลง 38% ตั้งแต่ Release แรกที่รันบน Self-Hosted Runner และที่สำคัญกว่าตัวเลขเฉลี่ยคือ — ไม่มี Spike ที่ 15-19 นาที อีกต่อไป

เจาะลึก: เวลาแต่ละขั้นตอน

เปรียบเทียบ Release จริง 2 ตัว — v1.1.177 (ubuntu-latest ตัวสุดท้าย) กับ v1.1.179 (self-hosted ตัวแรก):

ขั้นตอน ubuntu-latest (v1.1.177) Self-Hosted (v1.1.179) ผลต่าง
Build Web Image 219 วินาที 100 วินาที -54%
Build API Image 131 วินาที 121 วินาที -8%
Deploy to K8s 45 วินาที 34 วินาที -24%
รวมทั้งหมด 7.1 นาที 5.3 นาที -25%

ความแตกต่างที่ใหญ่ที่สุดอยู่ที่ Web Image Build — เร็วขึ้นกว่าเท่าตัว เพราะ Docker Layer Cache บน Self-Hosted Runner คงอยู่ข้าม Run ได้ ขณะที่ ubuntu-latest ต้อง Build ใหม่ทุกครั้ง

ทำไม ubuntu-latest ถึง Spike ไป 19 นาที?

ข้อมูลจาก 48 runs บน ubuntu-latest แสดงให้เห็นว่าส่วนใหญ่จบใน 7-8 นาที แต่มี 3 ครั้งที่พุ่งไป 15-19 นาที — สาเหตุหลักคือ GitHub-hosted runner ต้อง Provision VM ใหม่ทุกครั้ง บางครั้งเจอคิวรอ หรือ Network ระหว่าง Runner กับ Registry ช้าลงชั่วคราว

Self-Hosted Runner ตัดปัญหาเหล่านี้ออกทั้งหมด เพราะเครื่องรันพร้อมตลอด Cache พร้อม Network path เดิม


ทำไมเลือก Self-Hosted Runner?

สรุปจากตัวเลขข้างบน เหตุผลที่เราเปลี่ยนมาใช้ Self-Hosted Runner บนเครื่อง Ubuntu ของเราเองมี 3 ข้อ:

ความเร็วที่คาดเดาได้ — ไม่ใช่แค่เร็วขึ้นเฉลี่ย 38% แต่ที่สำคัญกว่าคือ ไม่มี Outlier อีกต่อไป ทุก Deploy จบภายในเวลาที่คาดเดาได้

Docker Cache ที่คงอยู่ — Web Image Build ลดจาก 219 วินาทีเหลือ 100 วินาที (-54%) เพราะ Layer Cache ไม่หายไปหลัง Job จบ

ต้นทุน — ลดการใช้ GitHub Actions Minutes โดยเฉพาะสำหรับ Job ที่รันบ่อย (เรา Deploy มากกว่า 10 ครั้งต่อวัน)


Nginx Configuration — รายละเอียดเล็กๆ ที่สร้างความแตกต่าง

Production Web Server ของเราไม่ใช่แค่ "เสิร์ฟ Static Files" แต่ถูก Optimize อย่างละเอียด:

  • Gzip Compression ระดับ 6 — บีบอัดทุกไฟล์ที่ใหญ่กว่า 256 bytes
  • Font Caching 1 ปี — ฟอนต์ไม่เปลี่ยนบ่อย Cache ยาวได้เลย
  • Image Caching 30 วัน — สมดุลระหว่าง Performance กับการอัปเดต
  • Next.js Hashed Assets 1 ปี — ไฟล์ที่มี Hash ใน URL เปลี่ยนชื่อเมื่อเนื้อหาเปลี่ยน Cache ยาวได้อย่างปลอดภัย
  • SPA Routing — จัดการ Client-side Navigation ให้ทำงานได้ถูกต้อง
  • Security Headers — ปิด Server Tokens ไม่เปิดเผยข้อมูลที่ไม่จำเป็น

Health Checks — ระบบที่ดูแลตัวเอง

ทุก Service มี Health Check ที่ Kubernetes ใช้ตัดสินใจ:

Service Endpoint Readiness Liveness
Web /healthz ทุก 5 วิ (3 ครั้งก่อน Fail) ทุก 30 วิ
API /health ทุก 10 วิ (3 ครั้งก่อน Fail) ทุก 30 วิ
PostgreSQL pg_isready Built-in Built-in

ถ้า Health Check ล้มเหลว Kubernetes จะ:

  • Readiness Fail → หยุดส่ง Traffic ไปที่ Pod นั้น
  • Liveness Fail → Restart Pod อัตโนมัติ

ไม่ต้องมีคนมานั่งเฝ้า ระบบดูแลตัวเองได้


ผลลัพธ์ที่ได้

Pipeline นี้ทำให้เรา:

  • Deploy ได้ทุกเมื่อ — ไม่มีขั้นตอน Manual ที่ต้องรอ
  • มั่นใจทุก Deploy — ทุก PR ผ่าน Build Test และ Lighthouse ก่อนถึง Production
  • Rollback ได้ทันที — ทุก Version ถูก Tag ไว้ กลับไป Version ก่อนได้ใน 1 คำสั่ง
  • Zero Downtime — Rolling Update ทำให้ผู้ใช้ไม่รู้สึกถึงการ Deploy
  • ติดตามได้ — Manifest ใน Git บอกสถานะ Production ได้เสมอ

ทั้งหมดนี้เกิดขึ้นใน ราว 5 นาที จาก git push --tags ถึง Live บน enersys.co.th — ลดลง 38% จากค่าเฉลี่ย 8.5 นาทีบน GitHub-hosted runner และไม่มี Spike 15-19 นาทีอีกต่อไป


แหล่งข้อมูล

บทความที่เกี่ยวข้อง

ซื้อ AI + ERP แพงหูฉี่ แต่ได้แค่ 10% ของ Value — ปัญหา "Last Mile" ที่ไม่มีใครพูดถึง

90% ของโปรเจกต์ AI ในองค์กรล้มเหลว ไม่ใช่เพราะเทคโนโลยีห่วย แต่เพราะคนไม่ยอมเปลี่ยน — HBR และ erp.today เปิดโปงปัญหา Last Mile ที่ทำให้บริษัทเสียเงินฟรีปีละหลายล้าน

ธุรกิจ Analog ตายสนิท — UTCC เปิดลิสต์ Rising Stars vs Falling Stars เศรษฐกิจไทย 2026

หอการค้าไทยชี้ชัด: ร้านเน็ต สิ่งพิมพ์ ร้านหนังสือ กำลังจมหาย ขณะที่ Cloud, Cybersecurity, Creator Economy พุ่งทะยาน GDP ดิจิทัลโต 4.2% เร็วกว่า GDP ประเทศ 2 เท่า — ธุรกิจคุณอยู่ฝั่งไหน?

พาทัวร์ Enersys — เปิดประตูทุกห้องของ software house ไทย: ใครทำอะไร อยู่ตรงไหน และ AI ช่วยแต่ละ role อย่างไรในยุค 2026

ลูกค้าและพาร์ทเนอร์ถามบ่อย — Enersys ทำอะไรกันแน่ และคนในบริษัทมีหน้าที่อะไรบ้าง บทความนี้พาทัวร์ทั้ง 14 ห้อง (เลขมงคล) ของ software house เปิดประตูทีละแผนก ตั้งแต่ front desk, engineering floor จนถึง Executive Office บอกว่าใครรับผิดชอบอะไร AI ตัวไหนเข้ามาช่วย และทำไม mix ของคนกับ AI ในยุค 2026 ทำให้ส่งงานคุณภาพได้เร็วและคุ้มขึ้น

"Empowering Innovation,
Transforming Futures."

ติดต่อเราเพื่อทำให้โปรเจกต์ของคุณเป็นจริง