Container Deployment using CI/CD
CI/CD คืออะไร
CICD ย่อมาจาก Continuous Integration and Continuous Delivery อธิบายแบบสั้น ๆ ก็คือการทำให้โปรเจ็คของเราทำงานแบบอัตโนมัติทั้งหมด ตั้งแต่การ Build, Test, Packing ไปจน Deploy หรือใครจะมี flow แบบอื่นก็แล้วแต่จะใส่เข้าไป ซึ่งจะช่วยให้ developer สะดวกสะบายมากยิ่งขึ้น
สำหรับใครที่ต้องการเรียนรู้เนื้อหาเกี่ยวกับ CI/CD มากขึ้น สามารถรับชมคอร์ส AtlasX DevOps ได้ที่นี่
Build Pipeline
ในส่วนของ Build pipeline ที่ทางทีม AtlasX ได้ setup ไว้จะเป็นไปตามรูปนี้

- Developer เขียนโค้ดแล้ว push ไปยัง GitLab repository
- Jenkins รับรู้ว่ามี code ใหม่ push เข้ามา และจะทำกระบวนการต่าง ๆ ที่อยู่ใน pipeline ซึ่งทำตั้งแต่สแกน code จนถึง build image และ scan image ด้วย trivy
- เมื่อ build และ scan สำเร็จ จะทำการ push image ไปยัง registry ที่กำหนดไว้
- จากนั้นก็ทำการ deploy container ด้วย Portainer ซึ่งสามารถทำได้ 2 รูปแบบคือ
- ดำเนินการด้วย Portainer โดยสามารถ Deploy ได้ผ่านทางหน้าเว็บ โดยติดต่อทีม technology เพื่อช่วยในการ deploy
- ใช้วิธีการ GitOps ซึ่งจะต้องมีการสร้าง repository สำหรับเก็บ manifest ของ Docker Compose และทำการ deploy ผ่านทาง Jenkins และ Portainer
- Portainer จะทำการ deploy container ตามที่กำหนดไว้ใน Docker Compose
- Docker จะทำการ pull image จาก registry มาใช้งาน ตาม tag ที่กำหนดเอาไว้
Using Jenkinsfile
- ติดต่อทีม AtlasX สำหรับการทำ CI/CD และ Gitlab webhooks
- ดาวน์โหลด Jenkinsfile สำหรับ Docker ที่หน้า Download จากนั้นนำมาแทนที่ไฟล์เก่า หรือตั้งชื่อใหม่ว่า
Jenkinsfile_Docker - แก้ไขคอนฟิกใน
Jenkinsfileให้เรียบร้อย - สร้าง Branch ใหม่ชื่อ
jenkinsและ Checkout ไปที่jenkinsจากนั้นทำการ Push ไปยังorigin - ยกถ้วยกาแฟขึ้นแล้วก็จิบ ☕️
Jenkinsfile Parameters
| Parameter | Description |
|---|---|
IMAGE_NAME | ชื่อ container image ตาม standard คือ {registry}/{org}/{project}/{app_name} เช่น atlasx-registry.cdg.co.th/ptt/ngr-cc/webapp |
IMAGE_TAG | tag ของ image เช่น latest, v1.0, v1.1 |
PROJECT_KEY | ชื่อโปรเจกต์สำหรับระบุในรายงานของ SonarQube report และควรเป็นชื่อที่ไม่ซ้ำ (เช่น AtlasX.Web.Application). |
PROJECT_VERSION | เวอร์ชั่นของโปรเจกต์ที่เอาไว้ระบุในรายงานของ SonarQube report |
REGISTRY_URL | Url ของ Docker Registry ที่จะนำ image ไปเก็บ |
BASE_HREF | Angular base href เฉพาะ angular project |
Best Practice
1. GitOps Approach
ในกระบวนการ deployment แนะนำให้สร้าง GitLab repository สำหรับเก็บไฟล์ manifest เช่น docker-compose.yml แยกจาก GitLab repository ของโปรเจ็ค เพื่อใช้งานสำหรับการ deploy เท่านั้น เนื่องจาก Docker เป็นการรัน container ขึ้นมาจาก image นั่นจึงเป็นเหตุผลที่ไม่จำเป็นต้องนำ source code ไปเก็บบน production server อีก
2. Use Environment Variable for Secret
ในการเก็บ config ต่าง ๆ ที่เกี่ยวกับ Credentials หรือ secret ต่าง ๆ ให้ใช้ Environment Variable แล้ว inject เข้าไปในไฟล์ docker-compose.yml แทนการเก็บไว้ในไฟล์ docker-compose.yml โดยตรง ซึ่งการเก็บ Environment Variable สามารถทำได้หลายวิธี ไม่ว่าจะเป็น
2.1 ใช้ไฟล์ .env
วิธีนี้ใช้งานได้ง่ายที่สุด สามารถเก็บไฟล์ไว้บนเครื่อง production ได้เลย แต่ห้ามนำไฟล์ .env ไปเก็บไว้บน GitLab repository ของโปรเจ็คเด็ดขาด (แนะนำให้เก็บเป็น example.env สำหรับกำหนด template)
2.2 ใช้ Secret Manager
Secret Manager เป็นวิธีการเก็บ secret ไว้บน server ที่มีความปลอดภัยสูง สามารถกำหนดสิทธิ์การเข้าถึง secret ได้ รวมถึงข้อมูลรั่วไหลได้ยากขึ้น ซึ่งทางทีม AtlasX ได้นำ HashiCorp Vault มาใช้เป็น Secret Manager ในการเก็บ secret ของโปรเจ็ค ซึ่งสามารถเข้าถึง secret ได้ผ่าน API หรือ CLI ที่มีการเข้ารหัสแล้ว และสามารถกำหนดสิทธิ์การเข้าถึงได้