13.1 Hosting topology & environment matrix
ภาพรวม — ระบบผสมระหว่าง cloud และ on-prem
ระบบ VTRC ไม่ได้รันอยู่บนแพลตฟอร์มเดียว แต่ผสมระหว่าง GCP สำหรับ container runtime และ on-prem สำหรับ database และ identity service (LDAP/AD)
┌─────────────────────────────────────────────────────┐
│ GCP project: vtrc-nonprod (container registry) │
│ gcr.io/vtrc-nonprod/... │
└─────────────────────────────────────────────────────┘
│ docker pull
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Production VM │
│ │
│ nginx (443/80) ──┬── vtrc-api replica ×4 (APP_NO=1,2,3,5) port 8081 │
│ ├── vtrc-web nginx serve build/ │
│ └── cu-central-api replica ×3 (APP_NO=1,2,3) │
│ │
│ Redis 6379 (container) │
│ │
│ ※ centralize-api (NestJS :3000) มีใน workspace แต่ยังไม่ยืนยันว่าอยู่ใน │
│ path ของ nginx production (ดู E-08 ด้านล่าง) │
└─────────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ On-prem │
│ ├── MariaDB — schema vtrc + vtrc-centralize │
│ ├── MSSQL — HRMI (HR data) │
│ └── LDAP/AD — sso.redcross.or.th (10.188.128.213) │
└─────────────────────────────────────────────────────────────────────────────────┘โดเมนที่ใช้งาน
ระบบเลือก endpoint ของ GraphQL ตามโดเมนที่ผู้ใช้เข้าถึง — กลไกนี้ฝังอยู่ใน vtrc-web/src/config/apollo.js (รายละเอียดเต็มใน Volume 6)
| Origin | GraphQL endpoint | สภาพแวดล้อม |
|---|---|---|
https://vtrc.redcross.or.th/ | https://vtrcapi.redcross.or.th/api/graphql | production |
https://vtrcbackoffice.redcross.or.th/ | https://vtrcapi.redcross.or.th/api/graphql | production |
https://uat-vtrc.redcross.or.th/ | https://uat-vtrcapi.redcross.or.th/api-uat/graphql | UAT |
https://uat-vtrcbackoffice.redcross.or.th/ | https://uat-vtrcapi.redcross.or.th/api-uat/graphql | UAT |
http://localhost:3000/ | ชี้ไป UAT | พัฒนาเครื่อง local |
โดเมนที่ nginx รู้จัก (จาก server_name ใน config):
| โดเมน | ไฟล์ nginx | จุดประสงค์ |
|---|---|---|
vtrcapi.redcross.or.th | vtrc-api/nginx/default.conf:43,57 | API endpoint (หลัก) |
vtrc.redcross.or.th | vtrc-api/nginx/default.conf:51,211 | เว็บ end-user |
centralizeapi.redcross.or.th | cu-central-api/nginx/default.conf:66,110 | centralize / cu-central gateway |
sso.redcross.or.th, ssoapi.redcross.or.th | cu-central-api/docker-compose.yml:55 | LDAP/AD on-prem |
กลยุทธ์ GCP + on-prem แบบผสม
จาก docker-compose และ Dockerfile ของทั้งระบบ พบว่า:
Container image เก็บใน GCR —
cu-central-api/docker-compose.yml:39อ้างถึงgcr.io/vtrc-nonprod/cu-centralize-api:latestและ Bitbucket Pipelines push image ไปยัง$GCP_REGISTRY_HOSTNAME/$GCP_PROJECT_ID/...(vtrc-api/bitbucket-pipelines.yml:56)Container runtime รันบน VM (ไม่ใช่ GKE) — ไม่มีไฟล์ Kubernetes manifest, ไม่มี
Deployment.yaml, ไม่มีService.yamlทุก service ใช้docker-compose.yml—network_mode: hostใส่เฉพาะ service nginx (vtrc-web-proxy/rc-web-proxy) ไม่ใช่ทุก container (vtrc-api/docker-compose.yml:34,cu-central-api/docker-compose.yml:35)Database และ LDAP อยู่ on-prem —
cu-central-api/docker-compose.yml:54-55กำหนดextra_hostsสำหรับsso.redcross.or.thชี้ไป IP10.188.128.213(private IP on-prem) เพื่อให้ container ใน GCP เรียก LDAP ได้ผ่านทาง network ที่เชื่อมระหว่างกันไม่มี workload identity, ไม่มี KMS —
vtrc-api/vtrc-gcp-sa-key.jsonเป็น GCP service account key ที่ commit ลง repository (รายละเอียดใน Volume 9 บทที่ 5)
Environment matrix
| สภาพแวดล้อม | vtrc-api | cu-central-api | centralize-api | vtrc-web | vtrc-rc-backoffice |
|---|---|---|---|---|---|
| Production | docker-compose.yml, 4 replicas | docker-compose.yml, 3 replicas | docker-compose.yml, 1 replica | nginx serve build | nginx serve build |
| UAT | docker-compose.dev.yml | docker-compose-dev.yml | docker-compose.yml (target: dev) | build เดียวกัน ใช้ URL เป็นตัวเลือก | build เดียวกัน ใช้ URL เป็นตัวเลือก |
| พัฒนาเครื่อง local | npm run (nodemon) | npm run (nodemon) | yarn start:dev | npm start | npm start |
จุดสังเกต:
- Frontend ทั้งสองตัว (vtrc-web, vtrc-rc-backoffice) ไม่มีการ build แยก production/UAT — ตัวเลือก environment ฝังอยู่ใน
checkLinkURL()ที่อ่านwindow.location.hrefในขณะรัน (รายละเอียดเต็มใน Volume 6 และ Volume 7) - centralize-api ใช้ docker-compose เดียวกันทั้ง dev และ prod โดยต่างกันที่
target: developหรือtarget: production(centralize-api/docker-compose.yml:5-6,18-19)
โครงสร้าง timezone
ทุก service ตั้งค่า timezone เป็น Asia/Bangkok ผ่าน environment variable:
vtrc-api/docker-compose.yml:55,68,81,94—TZ=Asia/Bangkokสำหรับทุก replicacu-central-api/docker-compose.yml:46,65,82— เช่นเดียวกันcentralize-api/Dockerfile:5—ENV TZ="Asia/Bangkok"vtrc-api/api/.env.example:10—TIME_ZONE = 'Asia/Bangkok'
ส่วน front-end ใช้ locale พ.ศ. (พุทธศักราช) — รายละเอียดอยู่ใน Volume 6 บทที่ 8
E-08 · NestJS centralize-api กับ production nginx
centralize-api (NestJS, port 3000) มีใน workspace และมี docker-compose.yml ของตัวเอง แต่ cu-central-api/nginx/default.conf upstream centralized-api ชี้เฉพาะ localhost:8000, 8002, 8003 (cu-central GraphQL replicas) — ไม่มี upstream ไป NestJS :3000
ดังนั้นเอกสารนี้ ไม่ยืนยัน ว่า NestJS อยู่ใน path ของ nginx production ของ centralizeapi.redcross.or.th — ต้องสอบถามทีมปฏิบัติการก่อนสมมติว่า traffic จากโดเมนนั้นไปถึง NestJS
สรุปประเด็นสำคัญ
- ระบบไม่ได้อยู่บน Kubernetes — ใช้ docker-compose บน VM; nginx ใช้
network_mode: hostเพื่อ upstream ไปlocalhost:PORTของ Node replica — การเพิ่ม/ลด replica ต้องแก้ docker-compose.yml เอง - database และ LDAP อยู่นอก GCP — ทำให้มีจุดเชื่อม network ระหว่าง cloud กับ on-prem ที่ต้องดูแลเป็นพิเศษ
- Frontend เลือก environment จาก URL — ทำให้ build หนึ่งรอบใช้ได้ทั้ง prod และ UAT แต่ก็หมายความว่าไม่สามารถบังคับ environment จากฝั่ง build ได้
- NestJS
centralize-apiยังไม่ยืนยันใน nginx production path (E-08)