1. Overview
โปรเจกต์นี้ใช้รูปแบบ microservice stack ที่มี portal เป็นหน้าแรก และให้แต่ละ app อยู่ใต้
/projects/<app>/. nginx เป็นประตูหน้า, Docker Compose เป็นตัวจัด service,
ส่วนแต่ละ app ต้องประกาศ route, port, env และ base path ให้ตรงกัน.
วิธีเรียน Handbook: พื้นฐาน > Dev > Quality > Deploy > Maintenance
คู่มือนี้ควรเรียนแบบไล่ระดับ ไม่ควรกระโดดไป deploy ตั้งแต่ยังไม่เข้าใจ base path, service boundary และ API contract. ให้ใช้ roadmap นี้เป็นลำดับอ่านและลำดับฝึกงานจริงของ Jr Dev.
เส้นทาง 5 วันสำหรับ Jr Dev
| วัน | หัวข้อ | ผลลัพธ์ที่ต้องทำได้ |
|---|---|---|
| Day 1 | Foundation | อธิบาย portal, nginx, Docker Compose, base path และ service route ได้ |
| Day 2 | Frontend + BFF | แก้ link/fetch ให้ไม่หลุด subpath และเรียก BFF ได้ถูกต้อง |
| Day 3 | Backend + DB | เพิ่ม endpoint, migration, audit log และ error response format ได้ |
| Day 4 | AI/API Integration | ทำ AI suggestion/API job แบบ explainable และส่ง OpenAPI/Postman ได้ |
| Day 5 | Deploy/Operate | SSH เข้า EC2, ดู Docker/log, deploy, verify, commit git และ rollback ขั้นพื้นฐานได้ |
2. Architecture Map
ภาพรวม production flow ที่ควรจำ: browser เข้า nginx, nginx ส่งเข้า portal/app, FE คุย BFF, BFF คุย BE/AI/ERP, BE คุย DB.
| Layer | หน้าที่ | ตัวอย่าง |
|---|---|---|
| Portal | รวม entry point ของทุก app | /, card ไป /projects/demo1/ |
| FE | หน้าจอ user และ API client | Next.js, Vue, Nuxt |
| BFF | รวมข้อมูล/ซ่อน internal BE จาก browser | /projects/demo2/api/* |
| BE | business logic และ database transaction | Go, FastAPI, NestJS |
| AI API | ห่อ OCR/STT/TTS/model engine เป็น API | /api/v1/ocr/jobs |
| ERP | ระบบภายนอกที่ต้องขอหรือเปิด API ให้เชื่อม | HR, payroll, inventory, finance |
Mermaid Sequence & Component Diagrams
Diagram ชุดนี้ใช้เป็น source of truth สำหรับอธิบายให้ Jr Dev และทีม production เห็นว่าแต่ละ service ส่งต่อข้อมูลให้ใครเรียกใช้.
Component Diagram: Demo 1 Microservice Case
flowchart LR
Browser["Browser / User"] --> Nginx["nginx reverse proxy"]
Nginx --> Portal["Portal / handbook.html"]
Nginx --> Web["Next.js FE + BFF<br/>/projects/demo1-ms"]
subgraph WebLayer["Browser-facing service"]
Web --> BFF["BFF route handlers<br/>/api/*"]
end
subgraph BackendLayer["Internal backend services"]
BFF --> GoAPI["Go BE<br/>worker + assignment manager"]
BFF --> AIAPI["Python FastAPI AI API"]
GoAPI --> Postgres["PostgreSQL<br/>workers, assignments, audit"]
AIAPI --> AIJobs["AI jobs<br/>suggestion + field capture"]
AIAPI --> Postgres
end
subgraph ExternalLayer["Future integration"]
GoAPI -. request/provide API .-> ERP["ERP / HR / Payroll"]
AIAPI -. model adapter .-> Models["OCR / STT / TTS / Detection engines"]
end
Sequence Diagram: Worker Suggestion
sequenceDiagram
autonumber
actor Foreman
participant FE as Next.js FE
participant BFF as Next.js BFF
participant AI as FastAPI AI API
participant BE as Go Worker BE
participant DB as PostgreSQL
Foreman->>FE: เลือกงาน + zone + required skills
FE->>BFF: POST /api/ai/worker-suggestions
BFF->>AI: POST /api/v1/ai/worker-suggestions<br/>user role + site scope + requestId
AI->>BE: Read worker context / history
BE->>DB: Query workers, assignments, preferences
DB-->>BE: Worker context
BE-->>AI: Candidate workers
AI-->>BFF: Suggestions with score, reasons, warnings
BFF-->>FE: Browser-safe response
FE-->>Foreman: แสดงคำแนะนำ ไม่ auto assign
Foreman->>FE: Confirm / override
FE->>BFF: POST assignment command
BFF->>BE: Create assignment with selected reason
BE->>DB: Insert assignment + audit event
Sequence Diagram: Field Capture AI
sequenceDiagram
autonumber
actor User as Foreman / HR
participant FE as Next.js FE
participant BFF as Next.js BFF
participant AI as FastAPI AI API
participant Model as Detection Adapter
participant BE as Go BE
participant DB as PostgreSQL
User->>FE: Upload image / scan QR / namecard
FE->>BFF: POST /api/ai/barcode-detection/jobs
BFF->>AI: POST /api/v1/barcode-detection/jobs
AI->>DB: Insert field_capture_events queued
AI->>Model: Run barcode/namecard/face detection
Model-->>AI: Draft result / confidence / warnings
AI->>DB: Save detection result as evidence
AI-->>BFF: 202 jobId
BFF-->>FE: jobId + requestId
FE->>User: Show result for human confirmation
User->>FE: Confirm final action
FE->>BFF: Submit confirmed command
BFF->>BE: site-in / worker draft / evidence link
BE->>DB: Write business command + audit event
Demo 1 Microservice Source Contract
ก่อน dev ทุกครั้งให้ยึด Demo 1 เดิมเป็น product source of truth แล้วค่อยแตก service. เป้าหมายไม่ใช่ทำ dashboard ใหม่ แต่คือย้าย use case โฟร์แมนจริงจาก Demo 1 ไปเป็น architecture ที่ FE, BE, AI แยกกันทำงานได้.
ดูจาก services/projects/demo1 โดยเฉพาะ Foreman Today, worker search, task assignment, Daily Close, Audit Feed, pending sync และ base-path helper.
components/demo/ForemanTodayDemo.tsx
app/foreman/page.tsx
app/demo/1/page.tsx
components/shared/*
lib/base-path.ts
ใช้ไฟล์ analysis เป็น requirement หลัก ไม่ invent feature เองก่อนอ่าน context.
public/foreman-ba-analysis.html
public/foreman-data-business-analysis.html
public/foreman-executive-analysis.html
public/foreman-sa-analysis.html
public/foreman-user-journey-analysis.html
public/foreman-uxui-analysis.html
public/plan.html
Subagent / Service Boundary
| Track | เจ้าของ | ส่งมอบให้ใคร | ห้ามทำแทน |
|---|---|---|---|
| BA | use case, KPI, role, business rule | SA, FE, BE, AI | ไม่เขียน endpoint ก่อน requirement ชัด |
| SA | component, sequence, API contract, DB boundary | FE, BE, AI, DevOps | ไม่ให้ browser เรียก internal service ตรง |
| FE / BFF | Foreman workflow, base path, browser-safe API | BE command, AI suggestion | ไม่เขียน assignment ลง DB เอง |
| Go BE | worker manager, assignment command, audit/activity log, DB transaction | FE/BFF, report, production team | ไม่ให้ AI สร้าง assignment อัตโนมัติ |
| FastAPI AI | worker suggestion, reason autocomplete, OCR/STT/TTS/field capture evidence | FE/BFF และ Go BE ผ่าน confirmation | ไม่ตัดสินใจแทน user หรือ payroll/attendance |
Development Sequence
sequenceDiagram
autonumber
participant BA as BA subagent
participant SA as SA subagent
participant FE as FE/BFF subagent
participant BE as Go BE subagent
participant AI as AI subagent
participant DB as PostgreSQL
BA->>SA: Demo 1 use case + KPI + role scope
SA->>FE: Screen flow + API contract + base path rule
SA->>BE: Command contract + DB/migration/audit boundary
SA->>AI: AI allowed/disallowed use cases
FE->>BE: fe > be task assignment command
FE->>AI: fe > ai feature request
AI-->>FE: suggestion/evidence only
FE->>BE: confirmed assignment + reason + requestId
BE->>DB: transaction + audit/activity log
3. Local vs Production URL
Local และ production ต้องใช้ path pattern เดียวกัน ต่างกันแค่ domain/protocol.
http://localhost/projects/demo1/
http://localhost/projects/demo2/
http://localhost/projects/demo3/
https:///projects/demo1/
https:///projects/demo2/
https:///projects/demo3/
/portal/plan ใน app ที่อยู่ใต้ subpath เพราะจะหลุดไป http://localhost/portal/plan.
Public vs Internal Documentation Boundary
เอกสารนี้มีโฟกัส “public-safe training + production runbook” แยกชัดเจนจากข้อมูลลับที่ใช้เฉพาะทีมปฏิบัติการ.
/learning/ใช้ฝึก onboarding และสอน runbook ทั่วไปhandbook.html= compatibility entry, ให้แนวทางอ่านเพิ่มเฉพาะ- ต้องคงเป็นแนวทางใช้งานทั่วไปและแนวคิดสอน
- ตัวอย่าง command ใช้ placeholder เสมอ
internal-ops-runbook.htmlเก็บชื่อ container ที่ไม่ซ้ำแหล่งสาธารณะ- ใส่ host/path/domain/credential จริงที่
<...>เท่านั้น - เชื่อมต่อ SSH, backup path, rollback, และ incident template
- ลิงก์จาก public layer ต้องอธิบายว่าเอกสารนี้มีเฉพาะ template
, , , , : , , , , , .
<OLD_DEPLOY_PATH>->หรือ/opt/<stack-name>/services- ชื่อ host จริง ->
- key, SSH, cert path -> placeholders เสมอ
- โทเคนจริง -> ต้องไม่ใส่ลงเอกสารและไม่แชร์ผ่าน public route
4. Portal Standard
Portal เป็นหน้าแรกของ stack และเป็นตัวบอก user ว่ามี app อะไรให้เปิดบ้าง.
- เพิ่ม card ใน
services/portal/index.html. - link ต้องเป็น full subpath เช่น
/projects/demo2/. - ชื่อ card ต้องตรงกับ service ที่ deploy จริง.
- ถ้า portal มี card แต่ nginx/compose ไม่มี service ถือว่า config ไม่สมบูรณ์.
<a href="/projects/demo2/">
Demo 2 - BE + DB + BFF
</a>
5. Nginx Routing Standard
nginx route ต้องรับทั้ง path แบบมี slash และไม่มี slash แล้วส่งเข้า container service ด้วย upstream ภายใน Docker network.
location = /projects/demo2 {
return 308 /projects/demo2/;
}
location /projects/demo2/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Request-Id $request_id;
proxy_pass http://:3000;
}
:3000 .
Nginx Troubleshooting Matrix
ใช้ matrix นี้เป็นจุดเริ่มต้นจับผิด production route.
| อาการ | จุดตรวจ | แนวทางแก้ |
|---|---|---|
| 502 Bad Gateway | proxy ไม่เจอ upstream / service ไม่ขึ้น / port mismatch / app crash | ตรวจว่า service รันอยู่และชื่อ service ใน nginx คือ upstream ที่ตรงกับ compose; ใช้ docker exec , docker compose ps, docker compose logs <service> |
| 504 Gateway Timeout | BE ตอบช้า/ค้าง หรือ timeout proxy ต่ำเกิน | เช็ค app log, เพิ่ม timeout ใน nginx สำหรับงาน async, และตรวจ queue/DB/external latency |
Subroute 404 เช่น /projects/demo1/xxx |
Next.js route/basePath ไม่ครบ, rewrite หาย, slash handling ผิด | ตรวจ NEXT_PUBLIC_BASE_PATH, route config, และ location block สำหรับทั้ง path / กับ /projects/.../ |
Asset 404 เช่น /_next/... |
assetPrefix / build config ผิด / ไม่ rebuild หลังแก้ basePath | ตรวจว่าหน้ามี /projects/demo1/_next/ และไฟล์ build ใหม่ผ่าน docker compose up --build |
| Redirect loop | location + return 308 ผิด, trailing slash ซ้อน, middleware/rewrites ผิด | ทดสอบทีละ endpoint และตรวจ network hop ของ redirect ให้ลุย 1 ทิศทาง |
| WebSocket/SSE fail | header Upgrade/Connection ไม่ส่งผ่าน | เพิ่ม proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade, Connection และ health check ที่ยืนยัน session |
Production nginx template (placeholder-safe)
location /projects/demo1/ {
set $demo1_upstream :3100;
set $project_prefix /projects/demo1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Forwarded-Prefix $project_prefix;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Cache-Control "no-cache";
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_pass http://$demo1_upstream;
}
proxy_pass http://.../; เพราะ prefix จะถูก strip และเกิด asset/redirect ผิดรูปแบบ.
6. Docker Compose Standard
Compose คือ source of truth ของ service, port, env และ network ภายใน stack.
services:
:
build: ./projects/demo2/web
environment:
APP_BASE_PATH: /projects/demo2
PUBLIC_API_BASE_URL: /projects/demo2/api
expose:
- "3000"
build: ./projects/demo2/api
environment:
SERVICE_NAME: demo2-api
DATABASE_URL=postgresql://:@:5432/
LOG_LEVEL: info
expose:
- "8080"
- service name อ่านง่ายและไม่ซ้ำ
- browser ไม่เห็น internal host เช่น
:8080 - DB host ใช้
postgresใน compose network - port ภายในต้องตรงกับ nginx upstream
Compose Healthcheck, Health, Expose vs Ports
แนวทางนี้ลด downtime และช่วยให้ nginx รอ service พร้อมก่อน route.
- Service หลัง nginx ให้ใช้
expose(ไม่จำเป็นต้อง publish). - ใช้
portsเฉพาะ service ที่ต้องเจาะ host โดยเจาะจง. - compose สำหรับ production ควรดูความชัดของ topology ก่อนเปิด
ports.
:
expose:
- "3100"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3100/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 6
start_period: 15s
Compose command example
docker compose -f docker-compose.local.yml config
docker compose -f docker-compose.local.yml up --build -d
docker compose -f docker-compose.yml config
docker compose -f docker-compose.yml up --build -d
# ตรวจ readiness ของ service
docker compose ps
docker compose exec nginx -t
docker compose config ก่อนและหลังเปลี่ยน compose เพื่อจับ syntax/layout drift.
7. Demo 1 Walkthrough
Demo 1 ใช้สอน FE app ที่อยู่ใต้ reverse proxy subpath.
/projects/demo1/:3100 /projects/demo1https:///projects/demo1/ เวลาทดสอบให้เปิดหน้าแรก, reload subroute, คลิก navigation และดู asset path ว่ายังขึ้นต้นด้วย /projects/demo1/.
curl -sL -o /dev/null -w '%{http_code} %{url_effective}\n' \
http://localhost/projects/demo1/
curl -sL http://localhost/projects/demo1/ \
| grep -o '/projects/demo1/_next/[^" ]*' | head
8. Demo 1 Base Path Fix
ปัญหาที่เจอบ่อยคือ link แบบ root-relative ทำให้ user หลุดจาก app prefix.
<a href="/portal/plan">Research Plan</a>
fetch("/api/db/events")
<a href={withBasePath("/portal/plan")}>Research Plan</a>
fetch(withBasePath("/api/db/events"))
Safe FE Base Path Helper & Audit Checklist
ใช้ helper เดียวสำหรับ URL ทั้ง link/redirect/fetch ให้ไม่หลุด /projects/<app>.
export function withBasePath(path: string): string {
if (!path) {
return "";
}
if (path.startsWith("http")) {
return path;
}
const base = process.env.NEXT_PUBLIC_BASE_PATH || "";
return `${base}${path.startsWith("/") ? path : `/${path}`}`;
}
export const API = {
base: process.env.NEXT_PUBLIC_API_BASE_URL || "/projects/demo2/api",
withBasePath,
};
Checklist: ใช้ได้เมื่อ
- มี component ใช้
<a>แบบ raw - มี redirect ผ่าน client หรือ middleware
- มี static file path / asset path ใน FE
- มี fetch จาก browser-side
- มี fallback path เฉพาะ subpath route
Checklist: ต้อง refactor
- ลบ root-relative literal อย่างเดียว
/portal/...,/api/... - ใส่
basePathใน Next.js config - เพิ่ม integration test สำหรับทั้ง local และ production shape
9. FE Architecture
FE ทุก framework ต้องแยกหน้าที่ให้หาไฟล์ง่ายและแก้ต่อได้.
| Folder | ใช้ทำอะไร | ตัวอย่าง |
|---|---|---|
components/ui | primitive component | Button, Input, Dialog |
components/layout | โครงหน้า | Shell, Sidebar, Header |
features | feature-specific UI + logic | tasks, workers, reports |
lib | business/API/auth logic | api-client, auth, base-path |
utils | helper เล็ก ไม่มี business rule | formatDate, cn, currency |
10. FE API Client
FE ต้องเรียก API ผ่าน client กลางเสมอ เพื่อจัด base URL, auth, request id, error และ retry ให้เหมือนกัน.
type ApiResponse<T> = {
success: boolean;
data: T | null;
error: { code: string; message: string } | null;
requestId: string;
};
export async function apiClient<T>(path: string): Promise<ApiResponse<T>> {
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL ?? "/projects/demo2/api";
const res = await fetch(`${baseUrl}${path}`, {
headers: { "x-client": "demo2-web" },
});
return res.json();
}
APP_BASE_PATHใช้กับ route/link/asset ของ app.PUBLIC_API_BASE_URLใช้กับ browser API endpoint.INTERNAL_API_BASE_URLใช้เฉพาะ BFF/BE ไม่เปิดให้ browser เห็น.
11. BE Architecture
BE ใช้ Clean Architecture เป็นแกนกลาง: business logic อยู่ข้างใน, framework และ DB อยู่ข้างนอก.
| Layer | Rule |
|---|---|
| Domain | ห้าม import framework เช่น FastAPI, Fiber, NestJS decorator |
| Use case | รับ interface/port เข้ามา ไม่ new DB client เอง |
| Adapter | แปลง DB/external response เป็น domain model |
| Driver | รับ HTTP, validate input, map error เป็น status code |
12. Go BE Standard
Go service ใช้ layer ชัดและ dependency ผ่าน interface.
cmd/api/main.go
internal/config/
internal/domain/
internal/usecase/
internal/ports/
internal/adapters/postgres/
internal/http/
internal/middleware/
migrations/
tests/
- controller/handler รับ request แล้วเรียก usecase.
- repository query DB และคืน domain object.
- ใช้ context และ timeout ทุก DB/external call.
- log เป็น JSON และใส่
request_id.
13. FastAPI/Python Standard
FastAPI ใช้ dependency injection ได้ดี แต่ต้องจำกัด FastAPI import ไว้ใน driver/rest layer.
src/
domain/
entities/
value_objects/
ports/
repositories/
use_cases/
adapters/
repositories/
clients/
drivers/
rest/
app.py
dependencies.py
routers/
schemas.py
exception_handlers.py
tests/
unit/
integration/
- domain model ใช้ dataclass หรือ class ปกติ และไม่ผูกกับ Pydantic ถ้าไม่จำเป็น.
- Pydantic schema อยู่ที่ driver/rest เพื่อ validate request/response.
- use case throw custom exception แล้ว exception handler map เป็น HTTP response.
- ใช้ in-memory repository สำหรับ unit test และ PostgreSQL adapter สำหรับ integration test.
14. NestJS Standard
NestJS มี module/controller/service อยู่แล้ว แต่ต้องแยก service ที่เป็น use case ออกจาก adapter/repository.
src/
modules/tasks/
tasks.controller.ts
tasks.module.ts
dto/
domain/
use-cases/
repositories/
adapters/
common/
guards/
interceptors/
filters/
migrations/
- controller ห้ามมี business logic หนัก.
- use-case class รับ repository interface ผ่าน DI.
- interceptor ใช้ใส่ request id/logging/response transform.
- exception filter ทำ error response format ให้เหมือน service อื่น.
15. BFF Standard
BFF ใช้เมื่อ browser ต้องเรียกหลาย backend, ต้องซ่อน internal API, หรือต้องจัด session/auth ให้เหมาะกับ FE.
- BFF ทำ response shaping, auth mapping, caching และ error normalization.
- BFF ไม่ควรเก็บ business rule หลักที่ควรอยู่ใน BE use case.
- BFF ต้องส่งต่อ
request_idไปทุก downstream service.
BFF Browser Flow, CORS และ Token Handling
BFF คือชั้นที่เชื่อม Browser กับ BE/AI/ERP โดยยังคง contract ของ browser ไว้ปลอดภัย.
Flow
sequenceDiagram autonumber participant Browser participant BFF participant BE participant AI participant ERP Browser->>BFF: request + cookie/session BFF->>BFF: validate auth, policy, CSRF, rate limit BFF->>BE: internal request (service name / internal net) BE-->>BFF: business result + requestId BFF->>AI: evidence/ai call (if needed) AI-->>BFF: result + warnings + confidence BFF-->>Browser: sanitized response + audit trace ERP-->>BFF: callback/proxy as needed
Token mapping
- Browser เก็บ token แบบเหมาะสมกับ policy: httpOnly cookie เป็นค่า default
- BFF แปลง/ต่ออายุ token เพื่อเรียก internal BE
- CORS เปิดเฉพาะ trusted origin และแนวทาง preflight ที่จำเป็น
- BFF ห้าม expose secrets หรือ internal token ให้ client
- Log ต้องมี
request_id+ actor ทุกจุด
16. PostgreSQL & Migration
PostgreSQL ใช้ผ่าน Docker Compose network และ migration ต้อง track ได้ทั้ง up/down.
DATABASE_URL=postgresql://:@:5432/
migrations/
001_create_tasks.up.sql
001_create_tasks.down.sql
002_create_audit_logs.up.sql
002_create_audit_logs.down.sql
Migration rule
- หนึ่ง migration ทำหนึ่งเรื่อง เช่น create table หรือ add column.
- ทุก migration ต้องมี rollback path หรือเหตุผลว่าทำไม rollback ไม่ได้.
- ก่อน migrate production ต้อง backup DB ก่อน.
- หลัง migrate ต้อง verify schema และ smoke test endpoint สำคัญ.
ความปลอดภัยในการ Migration
| Pattern | ปลอดภัย | ไม่ปลอดภัย |
|---|---|---|
| Change ที่ไม่มี downtime | ADD COLUMN แบบ nullable | DROP/RENAME คอลัมน์ที่ใช้งาน |
| Index | สร้าง index แบบ CONCURRENTLY (DB supports) | lock table ใน peak hour |
| Constraint | เพิ่ม default + validate | เพิ่มแบบ hard fail โดยไม่มี backfill |
| Backfill | deploy + background sync +ตรวจ counts | เปลี่ยน schema แล้วคาดว่าข้อมูล fill ทันที |
Migration safety examples
-- safe
ALTER TABLE assignments ADD COLUMN IF NOT EXISTS source_system VARCHAR(50) NULL;
CREATE INDEX CONCURRENTLY idx_assignments_site_id ON assignments(site_id);
-- unsafe
ALTER TABLE assignments DROP COLUMN task_code;
ALTER TABLE assignments ADD CONSTRAINT ck_due_date CHECK (due_date >= created_at);
Backup + restore drill
BACKUP_PATH="/postgres"
mkdir -p "$BACKUP_PATH"
docker compose exec -T postgres pg_dump -U > "$BACKUP_PATH"/_before_migration.sql
docker compose exec -T postgres psql -U < "$BACKUP_PATH"/_before_migration.sql
17. Logging & Audit
log แต่ละชนิดมีหน้าที่ต่างกัน อย่าเอาทุกอย่างไปรวมใน access log.
| Log | ใช้เมื่อไร | Field หลัก |
|---|---|---|
| Request log | ทุก HTTP request | request_id, method, path, status, duration |
| Business log | เหตุการณ์สำคัญใน use case | action, entity, result, actor |
| Audit log | ใครทำอะไรกับข้อมูลสำคัญ | actor_id, action, before, after, ip |
| Activity log | timeline ให้ user/business ดู | message, entity_id, visible_to |
| Archive log | ข้อมูลที่ถูกย้าย/ปิดรอบ/ลบแบบ soft delete | archive_reason, archived_by, archived_at |
{
"request_id": "req_01H...",
"service": "demo2-api",
"action": "task.create",
"actor_id": "u_123",
"status": "success",
"duration_ms": 42
}
Security & Quality Gates
ก่อน merge หรือ deploy ทุกครั้งต้องผ่าน gate ที่ตรวจซ้ำได้ ไม่ใช้ความรู้สึกว่า “น่าจะโอเค”. Gate เหล่านี้ช่วยปิด CVE, ลด bug จาก architecture drift และทำให้ทีม production รับงานต่อได้มั่นใจ.
1. Dependency CVE gate
Next.js app ทุกตัวต้องใช้ lockfile, ห้ามใช้ latest ใน runtime dependency หลัก และต้องรัน audit.
ใน repo นี้แก้โดย pin next, react, react-dom และ override postcss
เป็น patched version เพื่อปิด advisory GHSA-qx2v-qp2m-jg93.
cd services/projects/demo1
npm audit --audit-level=moderate
cd ../demo1-microservices/web
npm audit --audit-level=moderate
npm audit fix --force บน production โดยไม่เปิด PR/test เพราะคำสั่งนี้อาจกระโดด major version และทำให้ app พัง.
2. SonarQube quality gate
SonarQube คือ static analysis และ quality gate. Junior dev ต้องดู issue จาก SonarQube ก่อนส่งงาน: bug, vulnerability, security hotspot, duplication และ maintainability. ถ้า gate ไม่ผ่าน ให้แก้ root cause ก่อน mark false positive.
cd services
docker compose -f docker-compose.local.yml --profile quality up -d sonarqube sonar-postgres
docker run --rm \
-v "$PWD/..:/usr/src" \
sonarsource/sonar-scanner-cli \
-Dsonar.host.url=http://host.docker.internal:9000 \
-Dsonar.token="${SCAN_TOKEN_ENV}"
export SCAN_TOKEN_ENV.
- ใช้
sonar-project.propertiesเป็น source of truth ของ scan scope. - CI ต้อง fail ถ้า Quality Gate ไม่ผ่าน ไม่ใช่แค่ upload report แล้วปล่อย deploy.
- เริ่มด้วย Clean as You Code: new code ห้ามเพิ่ม blocker/critical issue.
3. Container image CVE gate
ต้อง scan final image ที่ build แล้ว เพราะ CVE อาจมาจาก base image, OS package หรือ app dependency ที่ copy เข้า image. ใช้ Trivy หรือ Docker Scout อย่างใดอย่างหนึ่งใน CI/CD.
trivy image :local
docker scout cves :local
- fail เมื่อเจอ fixable high/critical CVE.
- ถ้า CVE ยังไม่มี fix ต้องสร้าง exception พร้อม owner และ review date.
- อย่า deploy image ที่ scan ไม่ผ่านโดยไม่มี incident/exception note.
4. Local gate script
ใช้สคริปต์เดียวเพื่อให้ทุกคนรันเหมือนกันก่อนส่งงานขึ้น EC2. สคริปต์นี้ทำ npm audit, Next.js build, Docker Compose config และ Trivy filesystem scan เมื่อเครื่องมี Trivy.
cd
./scripts/quality-gate.sh
Reference URLs
18. AI Model to API Standard
AI model engine ไม่ควรผูกกับ HTTP โดยตรง ให้แยก adapter/usecase/controller/storage/queue เพื่อเปลี่ยน model หรือ vendor ได้.
Response contract
{
"requestId": "req_01H...",
"jobId": "job_01H...",
"status": "queued | running | succeeded | failed",
"result": null,
"error": null
}
Sync vs Async
| Mode | ใช้เมื่อไร | Status |
|---|---|---|
| Sync | งานเล็ก ตอบเร็ว เช่น OCR รูปเดียว | 200 OK |
| Async | งานใหญ่ เช่น PDF หลายหน้า/audio ยาว/batch | 202 Accepted + jobId |
19. OCR / Speech / TTS API Examples
Demo 3 ใช้สอน AI API แบบ async job เป็นค่าเริ่มต้น.
| API | Endpoint | Result |
|---|---|---|
| OCR | POST /api/v1/ocr/jobs | text, confidence, page number |
| Voice to Text | POST /api/v1/speech-to-text/jobs | transcript, language, segments, confidence |
| Text to Voice | POST /api/v1/text-to-speech/jobs | audio URL หรือ binary stream |
| Job status | GET /api/v1/jobs/{jobId} | queued/running/succeeded/failed |
POST /api/v1/ocr/jobs
Content-Type: multipart/form-data
file=@invoice.pdf
mode=invoice_extraction
Response: 202 Accepted
{
"requestId": "req_abc",
"jobId": "job_ocr_001",
"status": "queued",
"result": null,
"error": null
}
AI MVP for Foreman
AI ใน Demo 1 MS ใช้เป็นผู้ช่วยแนะนำ ไม่ใช่ระบบตัดสินใจแทนโฟร์แมน ทุกคำแนะนำต้อง explainable, override ได้ และถ้าเลือกใช้จริงต้องสร้าง audit event.
| Use case | Endpoint | Production rule |
|---|---|---|
| Worker Suggestion | POST /api/v1/ai/worker-suggestions | แนะนำ worker พร้อม score/reason/warning แต่ไม่ auto assign |
| Reason Autocomplete | POST /api/v1/ai/assignment-reason/autocomplete | สร้างข้อความสั้นให้ audit/report อ่านรู้เรื่อง |
| Favorite Worker | GET /api/v1/ai/favorite-workers | แยก “ใช้บ่อย” ออกจาก AI scoring เพื่อไม่หลอกผู้ใช้ |
| Face Detection | POST /api/v1/face-detection/jobs | ตรวจว่ามีหน้า/รูปใช้ได้เท่านั้น ไม่ใช่ face recognition |
| Namecard Detection | POST /api/v1/namecard-detection/jobs | ช่วย draft worker/contact fields ให้ HR/โฟร์แมนยืนยัน |
| Barcode Detection | POST /api/v1/barcode-detection/jobs | ใช้เป็นหลักฐาน QR/barcode ก่อน Go BE สร้าง command |
Scoring Rule MVP
+40 skill match
+20 available today
+15 same zone
+15 task history
+10 favorite/recent
-30 schedule conflict
-40 no-show or not site-in
-20 pending sync conflict
{
"workerId": "w_104",
"displayName": "สมชาย",
"score": 85,
"reasons": ["มีทักษะตรงกับงาน", "ว่างวันนี้", "โฟร์แมนใช้บ่อย"],
"warnings": []
}
- AI ต้องบอกเหตุผล ไม่ใช่คืน score เฉย ๆ
- โฟร์แมนต้องยืนยันก่อนเกิด assignment จริง
- override ต้องมี reason และบันทึก audit
- ห้ามใช้ payroll/performance score หรือข้อมูล sensitive ใน MVP
- face/namecard/barcode detection เป็น evidence ไม่ใช่ business decision
AI Evaluation, Fallback, Confidence Policy และ ERP Failure
AI API ต้องมีนโยบายประเมินคุณภาพและ fallback เสมอ ไม่ทิ้งผู้ใช้งานเมื่อโมเดลไม่มั่นใจ.
คำตอบ AI ควรมีครบ
resultหรือ recommendationconfidence(0-1)warnings(เช่น ข้อมูลไม่ครบ, แหล่งที่มาไม่ชัด)fallbackReasonเมื่อ confidence ต่ำrequestIdสำหรับ trace
Fallback policy
| เงื่อนไข | Action |
|---|---|
| confidence < 0.55 | show draft + require human confirmation |
| missing_required_fields | return warning + ask user inputs |
| ai_timeout / model_error | fallback ไป legacy workflow + log |
| ERP_down | disable AI suggestion ที่พึ่ง ERP และแจ้ง retry policy |
ERP failure policy
- ระบบต้องสลับไปโหมดไม่พึ่งข้อมูลไม่เสถียร
- เก็บเหตุผลใน audit และเพิ่ม incident evidence
- ต้องแจ้ง owner และ SLA / recovery plan ชัดเจน
- ไม่มี automation ที่ทำ assignment อัตโนมัติเมื่อ ERP ผิดพลาด
20. ERP API Integration Request
เวลาต้องขอ API จากทีม production/ERP ให้ส่ง requirement ที่ชัดพอสำหรับเปิด API, สร้าง test account และประเมิน risk.
API request template
Subject: ขอเปิด ERP API สำหรับ Demo 2 task integration
Source system: demo2-api
Target system: ERP Production
Business purpose: ดึง employee และ cost center เพื่อสร้าง task assignment
Endpoint needed: GET /employees, GET /cost-centers
Environment: dev, staging, production
Auth: API key หรือ OAuth2 ตาม policy
Expected fields: employeeCode, fullName, department, status
Sample payload: แนบ JSON example
Rate limit/SLA: 100 rpm, timeout 5s
Data sensitivity: PII
Go-live date: YYYY-MM-DD
Rollback plan: ปิด feature flag และกลับไปใช้ cached data
Owner/contact: team, email, chat channel
- ระบุ business purpose
- ระบุ endpoint/method/request/response
- ระบุ auth, rate limit, timeout, SLA
- ระบุ dev/staging/prod และ test account
- ระบุ data sensitivity เช่น PII, payroll, financial data
21. Public/Internal API Spec Standard
API spec ใช้ OpenAPI เป็น source of truth และแยก public API กับ internal API ให้ชัด.
| Type | Rule | Example |
|---|---|---|
| Public API | เปิดให้ ERP/vendor/team อื่นเรียก ต้องมี auth, rate limit, audit | /api/v1/tasks |
| Internal API | ใช้ใน Docker network หรือ private network เท่านั้น | http:// |
| Health | ให้ infra ตรวจ service | /healthz, /readyz |
openapi: 3.0.3
info:
title: Demo 2 Task API
version: 1.0.0
servers:
- url: https:///projects/demo2/api/v1
paths:
/tasks:
post:
summary: Create task
security:
- ApiKeyAuth: []
parameters:
- in: header
name: Idempotency-Key
schema: { type: string }
responses:
"201":
description: Created
"400":
description: Validation error
"500":
description: Internal server error
- ทุก endpoint ต้องมี method, auth, headers, params, body, response และ error.
- ทุก API ที่สร้าง transaction ต้องรองรับ idempotency key.
- ทุก response ต้องมี
requestId. - ต้องมี changelog และ deprecation policy เมื่อเปลี่ยน contract.
API Error Response, Status Mapping, Auth/RBAC, Idempotency
เอกสารนี้บังคับแบบเดียวทั้ง public API และ internal API เพื่อให้ front/back มีการตีความ error ร่วมกัน.
Standard error response
{
"requestId": "req_01H...",
"error": {
"code": "ERR_VALIDATION",
"message": "ข้อมูลที่ส่งเข้ามาไม่ครบ",
"details": [{ "field": "workerIds", "reason": "required" }]
},
"status": 400,
"trace": "trace_01H..."
}
Status mapping
| Status | ใช้เมื่อ | ตัวอย่าง |
|---|---|---|
| 400 | ข้อมูลขอไม่ถูกต้อง | validation |
| 401 | ไม่ได้รับอนุญาต (auth) | token หมดอายุ |
| 403 | มี auth แต่ไม่มีสิทธิ์ | RBAC denied |
| 409 | conflict | resource state conflict |
| 422 | ธุรกิจปฏิเสธ | ไม่ผ่าน policy |
| 429 | rate limit | เรียกเกิน quota |
| 500 | unexpected server error | retry / incident |
Auth / RBAC / Idempotency rules
- Auth สำหรับ public endpoint เป็น required และมี scope/role ตรวจชัดเจน
- RBAC แยกที่ BFF/edge และ BE ตาม policy
- Transaction endpoint ต้องรับและเช็ก
Idempotency-Keyอย่างน้อย 24 ชม. - ทุก request ต้องแนบ
requestIdใน log + trace
OpenAPI + Postman validation snippet
// OpenAPI endpoint + response example
paths:
/tasks:
post:
summary: Create task command
parameters:
- in: header
name: Idempotency-Key
required: true
schema: { type: string }
responses:
"201": { description: Created }
"409": { description: Conflict |
Conflict resource already exists }
// Postman test
pm.test("has requestId", () => {
const body = pm.response.json();
pm.expect(body.requestId).to.exist;
});
pm.test("idempotency", () => {
pm.expect([200, 201, 409]).to.include(pm.response.code);
});
22. Postman & Handoff Package
Postman collection ใช้ส่งต่อให้ทีม production ทดลอง API ได้ทันที ไม่ต้องอ่าน spec แล้วเดา payload เอง.
Handoff package
- OpenAPI file เช่น
openapi.yaml - Postman collection แยก module
- Postman environment: local, staging, production
- sample payload และ sample files สำหรับ OCR/audio/TTS
- auth instruction และ test account
- error cases และ expected status code
- owner/contact และ go-live checklist
// Postman test script example
pm.test("status is success", function () {
pm.expect(pm.response.code).to.be.oneOf([200, 201, 202]);
});
pm.test("has requestId", function () {
const json = pm.response.json();
pm.expect(json.requestId).to.be.a("string");
});
23. Production Runbook
Runbook คือ checklist สั้น ๆ ที่ใช้ก่อน deploy, ระหว่าง deploy และหลัง deploy.
- เปิด /pipeline/ และตรวจว่า stage สำคัญไม่ fail
- run
./scripts/quality-gate.shผ่าน - npm audit ผ่านทุก Next.js app
- SonarQube Quality Gate ผ่าน
- container image scan ไม่มี fixable high/critical CVE
- run test และ build ผ่าน
- backup DB ก่อน migration
- ตรวจ OpenAPI/Postman ล่าสุด
- ตรวจ portal/nginx/compose/env ตรงกัน
- เตรียม rollback command
- เปิด portal และ app route
- ยิง health check
- smoke test API สำคัญ
- ตรวจ request log/audit log
- แจ้งทีม production พร้อม handoff package
Backup / restore / rollback
# backup
docker compose exec postgres pg_dump -U app > backup-before-migrate.sql
# restore
docker compose exec -T postgres psql -U app < backup-before-migrate.sql
# rollback app image
docker compose up -d --no-deps demo2-api
24. Pipeline Monitor
/pipeline/ คือหน้า monitor สำหรับ CI/CD deployment flow ของ portal นี้. ตอนนี้เป็น static/manual dashboard เพื่อสอน flow ให้ชัดก่อน ต่อไปสามารถต่อ GitHub Actions, SonarQube API หรือ deployment log API ได้.
services/portal/pipeline/index.html และถูก serve โดย nginx portal root.
Pipeline status model
{
"environment": "local | production",
"release": { "branch": "main", "commit": "sha", "operator": "manual|ci" },
"stages": [
{ "name": "Dependency CVE", "status": "pass|warn|fail", "evidence": "npm audit output" },
{ "name": "SonarQube", "status": "pass|warn|fail", "evidence": "quality gate url" },
{ "name": "Smoke Routes", "status": "pass|warn|fail", "evidence": "curl status" }
]
}
Next phase
- เพิ่ม GitHub Actions workflow ที่ publish deployment status.
- เพิ่ม API เฉพาะ internal สำหรับอ่าน latest commit, docker compose ps และ smoke result.
- เพิ่ม SonarQube quality gate badge เมื่อมี token/permission พร้อม.
- บันทึก incident note เมื่อ deploy fail หรือ rollback.
Observability & Incident Runbook
ทีมผลิตจริงต้องเห็นปัญหาก่อน user รู้ก่อนด้วย trace + metric + alert.
- latency p50/p95
- error rate 4xx/5xx ตาม service
- queue lag / job duration
- DB query error/timeout rate
- AI job fail-rate และ avg confidence
- ใช้
requestIdต่อข้าม boundary ทั้ง FE/BFF/BE/AI - แนบใน log + response error
- ใช้เพื่อ reconstruct 502/timeout ใน 5 นาทีแรก
Alert rule example
alert(
service="portal",
expr="sum(rate(http_requests_total{status=~\"5..\"}[5m])) > 5",
for="10m",
severity="critical"
)
Incident template
Date/Time:
Detected by:
Impact:
Service:
Root cause hypothesis:
Evidence (logs, requestId, metrics):
Actions taken:
Recovery:
Postmortem owner:
Follow-up:
25. Remote EC2 & Git Basics
บทนี้ใช้สอน Jr Dev ให้ remote เข้าเครื่องจริง, ตรวจ service, แก้ไฟล์อย่างระวัง และเก็บ version ด้วย local git บน EC2.
เครื่อง production demo ปัจจุบันใช้ path หลัก .
git status, หลังแก้ต้อง test, แล้วค่อย commit.
1. เตรียม SSH key ในเครื่องเรา
เก็บ key ไว้ใน ~/.ssh/<KEY_NAME>.pem และตั้ง permission ให้ปลอดภัยก่อนใช้งาน.
chmod 600 ~/.ssh/<KEY_NAME>.pem
2. เพิ่ม SSH config เพื่อเข้าเครื่องง่าย
เปิดไฟล์ ~/.ssh/config แล้วเพิ่ม block นี้. ต่อไปจะพิมพ์แค่ ssh <ENV_ALIAS>.
Host <ENV_ALIAS>
HostName <EC2_OR_BASTION_HOST>
IdentityFile ~/.ssh/<KEY_NAME>.pem
User <SSH_USER>
3. Remote เข้า EC2
# แบบใช้ ssh config
ssh <ENV_ALIAS>
# แบบเต็ม ถ้ายังไม่ได้ตั้ง ssh config
ssh -i ~/.ssh/<KEY_NAME>.pem <SSH_USER>@<EC2_OR_BASTION_HOST>
4. เข้า workspace หลักและตรวจ service
cd
pwd
ls -la
docker ps
docker compose ps
portal/เก็บหน้า portal และ handbook/standard/deploymentprojects/demo1/คือ Demo 1 app เดิมprojects/demo1-microservices/คือ Demo 1 MS: Next.js FE/BFF, Go BE, FastAPI AI APInginx/คือ reverse proxy configdocker-compose.ymlคือ production compose entry point
5. Git พื้นฐานบน EC2
ตอนนี้ เป็น local git repository แล้ว ใช้สำหรับ version control บนเครื่องนี้.
cd
# ดู branch และไฟล์ที่เปลี่ยน
git status --short --branch
# ดู commit ล่าสุด
git log --oneline -5
# ดูว่าไฟล์เปลี่ยนอะไรบ้าง
git diff
# stage ไฟล์ทั้งหมดที่ตั้งใจ commit
git add -A
# commit หลัง build/test แล้ว
git commit -m "feat: describe the change"
6. Flow มาตรฐานเวลาแก้บนเครื่องจริง
- เข้าเครื่องด้วย
ssh <ENV_ALIAS>. - เข้า workspace:
cd. - ตรวจความสะอาดก่อนเริ่ม:
git status --short --branch. - แก้ไฟล์เฉพาะจุดที่เกี่ยวข้อง.
- rebuild/restart service ที่แก้ เช่น
docker compose up -d --build demo1-web. - ตรวจ nginx ถ้าแก้ proxy:
docker exec.nginx -t - ตรวจ URL จริงด้วย
curl -I. - ดู log:
docker compose logs --tail=80 demo1-web demo1-go-api. - ถ้าผ่านแล้วค่อย
git add -Aและgit commit.
7. คำสั่ง deploy ที่ใช้บ่อย
# rebuild เฉพาะ Next.js microservice web
docker compose up -d --build demo1-web
# reload nginx หลังแก้ proxy config หรือหลัง container recreate
docker exec nginx -t
docker exec nginx -s reload
# ตรวจ production route
curl -I https:///
curl -I https:///projects/demo1-ms
curl -I https:///handbook.html
8. ดู log เพื่อ debug
# ดู log service ที่เกี่ยวกับ Demo 1 MS
docker compose logs --tail=120 demo1-web demo1-go-api demo1-ai-api
# follow log ตอนลองกดปุ่มจาก browser
docker compose logs -f demo1-web demo1-go-api
เวลาเช็คปุ่มใน FE ให้ดู nginx log ก่อนว่ามี request เข้าไหม แล้วค่อยดู Go BE/FastAPI log ว่า endpoint ตอบ status อะไร.
9. Undo และ rollback ด้วย git
# ยกเลิกไฟล์ที่ยังไม่ได้ commit เฉพาะไฟล์เดียว
git restore path/to/file
# ดู commit ก่อนหน้า
git log --oneline -10
# revert commit แบบสร้าง commit ใหม่ ไม่ทำลาย history
git revert <commit_sha>
git reset --hard บนเครื่อง production ถ้ายังไม่ได้คุยกับทีม เพราะอาจลบงานที่คนอื่นเพิ่งแก้ไว้.
10. สิ่งที่ห้าม commit
- ห้าม commit
.env, token, password, private key, cert/key จริง - ห้าม commit
node_modules/,.next/, log, db runtime, backup dump - ถ้าต้องเพิ่ม env ใหม่ ให้เพิ่มเฉพาะ
.env.exampleหรือเขียนใน deployment guide - ก่อน commit ทุกครั้งให้ดู
git diff --statและgit diff
11. ตัวอย่าง commit message
feat: add ai auto assign action
fix: correct demo1-ms nginx upstream
docs: add ec2 git workflow to handbook
chore: baseline services stack
26. Maintenance
Maintenance คือการดูแลระบบหลัง deploy ให้ทำงานนิ่ง ตรวจเจอปัญหาเร็ว และย้อนกลับได้เมื่อมี incident. งานนี้ไม่ใช่แค่ restart service แต่รวม health check, logs, disk, backup, security update, dependency review และ git hygiene.
1. Daily checklist
- เปิด portal และ app สำคัญ เช่น
/,/projects/demo1,/projects/demo1-ms - ตรวจ container status ด้วย
docker compose ps - ตรวจ log error ของ nginx, FE, BE, AI API
- ตรวจ disk space เพื่อกัน Docker image/log กินเครื่อง
- ตรวจ git status ว่า production มี uncommitted change หรือไม่
cd
docker compose ps
docker compose logs --tail=80 demo1-web demo1-go-api demo1-ai-api
df -h
du -sh
git status --short --branch
2. Weekly checklist
- ทดสอบ flow สำคัญด้วยมือ เช่น เปิด portal, กด AI Assign, ตรวจ audit log
- รัน
./scripts/quality-gate.shเพื่อจับ CVE/build/config drift - เปิด /pipeline/ และตรวจว่า checklist ยังตรงกับระบบจริง
- ตรวจ Docker image/container เก่าที่ไม่ใช้แล้ว
- ตรวจ backup ล่าสุดว่าสร้างได้และ restore plan ยังใช้ได้
- อ่าน dependency/security warning จาก build logs
- สรุป change log จาก
git log --oneline
# ดู Docker resource ที่กินพื้นที่
docker system df
# ดู commit สัปดาห์ล่าสุดแบบสั้น
git log --oneline --since="7 days ago"
# ตรวจ route สำคัญ
curl -I https:///
curl -I https:///projects/demo1-ms
curl -I https:///handbook.html
3. Monthly checklist
- review nginx route ว่ายังมี app ที่เลิกใช้ค้างอยู่ไหม
- review Docker Compose service, port และ env ที่ไม่ใช้แล้ว
- review dependency upgrade เช่น Next.js, Go base image, Python base image
- review SonarQube Quality Gate trend และแก้ issue ที่ค้างเกินหนึ่งรอบ maintenance
- scan Docker image ด้วย Trivy/Docker Scout และบันทึก exception ถ้า CVE ยังไม่มี fix
- review security patch ของ OS และ Docker
- ซ้อม rollback จาก git commit และจาก backup อย่างน้อยใน staging/local
4. Health check standard
ทุก service ควรมี endpoint สำหรับเช็คว่า process ยังรันและ dependency สำคัญพร้อมใช้งาน.
| Endpoint | ใช้เมื่อไร | ต้องตอบอะไร |
|---|---|---|
/healthz | process ยังอยู่ไหม | 200 OK ถ้า app ยังรัน |
/readyz | พร้อมรับ traffic ไหม | 200 OK เมื่อ DB/queue/internal dependency พร้อม |
/version | ตรวจ release | commit sha, build time, service name |
5. Log maintenance
- log ต้องมี
requestId, service name, action, status, duration - audit log ต้องตอบได้ว่าใครทำอะไร เมื่อไร กับ record ไหน
- ห้าม log secret, token, password, payroll หรือข้อมูล sensitive ที่ไม่จำเป็น
- ถ้า log โตเร็วผิดปกติ ให้หา error loop ก่อน prune
# ดู error จาก reverse proxy
docker compose logs --tail=200
# ดู Go BE audit/business event
docker compose logs --tail=200 demo1-go-api
# follow log ระหว่างทดสอบจาก browser
docker compose logs -f demo1-web demo1-go-api demo1-ai-api
6. Backup and restore maintenance
ถ้า service ใช้ PostgreSQL จริง ต้องมี backup schedule, retention และ restore test. Backup ที่ไม่เคยลอง restore ยังไม่ถือว่าปลอดภัย.
# backup PostgreSQL example
mkdir -p /postgres
docker compose exec -T postgres pg_dump -U app > /postgres/-$(date +%Y%m%d-%H%M%S).sql
# restore example
docker compose exec -T postgres psql -U app < /postgres/-YYYYMMDD-HHMMSS.sql
- เก็บ backup ก่อน migration ทุกครั้ง
- ตั้ง retention เช่น daily 7 วัน, weekly 4 สัปดาห์, monthly 3 เดือน
- backup ต้องอยู่นอก app container และควร copy ออกนอกเครื่อง production
- บันทึก restore command ไว้ใน deployment/runbook
7. Docker cleanup policy
cleanup ช่วยคืน disk แต่ต้องทำด้วยความระวัง เพราะ image เก่าอาจเป็น rollback path.
# ดูพื้นที่ Docker ก่อน cleanup
docker system df
# cleanup เฉพาะ dangling image ที่ไม่ถูกใช้งาน
docker image prune
# หลีกเลี่ยงคำสั่งนี้บน production ถ้ายังไม่ได้ยืนยัน rollback plan
# docker system prune -a
8. Security maintenance
- ใช้ SSH key เท่านั้น ไม่เปิด password login
- จำกัดคนที่มี key เข้า EC2 และ rotate key เมื่อคนออกจากทีม
- ตรวจว่า secret ไม่ถูก commit ด้วย
git diffก่อน commit - update dependency/base image เป็นรอบ ไม่แก้ production แบบสุ่ม และต้องมี audit/build evidence
- ถ้า npm audit หรือ SonarQube fail ให้หยุด deploy แล้วเปิด issue พร้อม owner
- ตรวจ nginx route ว่าไม่มี internal API โผล่ public โดยไม่ตั้งใจ
9. Maintenance incident flow
- ยืนยันอาการด้วย URL/API ที่ user แจ้ง.
- ดู nginx log ว่า request เข้ามาถึง proxy หรือไม่.
- ดู app log ว่า BFF/BE/AI API ตอบ status อะไร.
- ตรวจ container status และ resource เช่น disk/memory.
- ถ้าเป็น regression ให้หา commit ล่าสุดด้วย
git log --oneline -5. - เลือก rollback, hotfix หรือ forward fix แล้วบันทึก post-incident note.
10. Maintenance record template
Date:
Owner:
Scope:
Checks:
- Portal:
- Demo route:
- API:
- Logs:
- Disk:
- Backup:
Changes made:
Git commit:
Risk / follow-up:
Training, Labs & Assessment
แนวทางสอนแบบ hands-on แยกเป็น Lab และกรอบประเมินความพร้อมก่อนรับงานจริง.
- เพิ่ม card ใน portal
- ตั้ง route /projects/demo1/ ให้ทำงาน
- ยืนยัน asset path
- สร้าง endpoint mock ใน BFF
- ส่ง request ผ่าน BFF -> BE flow
- ทดสอบ CORS/token behavior
- เพิ่ม migration ที่มี rollback
- backup/restore dry-run
- ตรวจ smoke / healthz
Day 1-5 แบบเร็ว
| วัน | หัวข้อ | ผลลัพธ์ |
|---|---|---|
| Day 1 | Contract + Route + Base path | อธิบาย browser flow ได้ |
| Day 2 | FE + BFF + API client | เรียก API ผ่าน BFF สำเร็จ |
| Day 3 | DB migration + audit | รัน migration + rollback |
| Day 4 | AI/Ops + error handling | เข้าใจ policy ความไม่แน่นอนของ AI |
| Day 5 | Deploy/runbook + incident | ผ่าน smoke + incident template |
Definition of Done: ครบ path, test, evidence, rollback readiness, handoff package.
Final Handbook Publish Checklist
- ตรวจว่าเอกสารแบ่ง public/internal boundary ชัดเจน
- ตรวจ placeholder ที่ควรอยู่ในเอกสารสาธารณะ
- ตรวจว่ามี OpenAPI + migration policy + incident template
- ตรวจว่า /handbook.html, /learning/handbook.html, /learning/index.html เหมือนกัน
- ตรวจว่ามีคำสั่ง verify ที่ใช้ได้จริง (smoke/compose/nginx)
- อัปเดต section reference map และ links
- รัน `cmp` เพื่อยืนยันไฟล์ mirror
Demo Summary
/projects/demo1/.
services/projects/demo1-microservices เพื่อสอน Next.js FE + BFF, Go BE และ Python FastAPI AI API ใต้ /projects/demo1-ms/.
/api/v1/tasks, PostgreSQL, migration, audit/activity log, OpenAPI และ Postman.
Section Reference Map
ตารางนี้คือแผนสื่อการสอนรายหัวข้อ: แต่ละ section ต้องสอนอะไร, ให้ Jr Dev ฝึกอะไร และใช้ reference URL ไหนเป็นฐาน. เวลา update handbook ให้ update ตารางนี้ด้วย เพื่อให้ทีมรู้ว่าเนื้อหาไม่ได้มาจากความจำลอย ๆ.
| Section | Teaching focus | Reference URLs |
|---|---|---|
| Overview |
|
AWS Microservices on AWSDocker Compose application model |
| Architecture Map |
|
Azure BFF patternDocker Compose networking |
| Mermaid Diagrams |
|
Mermaid sequence diagramsMermaid flowcharts |
| Demo 1 Source Contract |
|
Martin Fowler: MicroservicesDocker Compose overview |
| Local vs Production URL |
|
MDN Same-origin policyNext.js basePathNext.js assetPrefix |
| Portal Standard |
|
MDN anchor elementweb.dev navigationWCAG link purpose |
| Nginx Routing |
|
NGINX config filesNGINX reverse proxyNGINX beginner guide |
| Docker Compose |
|
Docker Compose overviewCompose services referenceCompose profiles |
| Demo 1 Walkthrough |
|
NN/g Task AnalysisGOV.UK journey mapping |
| Demo 1 Base Path Fix |
|
Next.js basePathNext.js linking and navigating |
| FE Architecture |
|
Next.js App RouterNext.js project structureServer and Client ComponentsScalable Next.js Architecture |
| FE API Client / BFF |
|
Next.js BFF guideNext.js environment variablesNext.js route handlersAzure BFF pattern |
| BE Architecture |
|
Fowler layeringThe Twelve-Factor App |
| Go BE Standard |
|
Go module layoutGo REST tutorialGo database accessGo Clean Architecture article |
| FastAPI/Python |
|
FastAPI dependenciesFastAPI errorsFastAPI SQL databasesClean Architecture with Python |
| NestJS |
|
NestJS docsNestJS controllersNestJS providersNestJS exception filters |
| PostgreSQL & Migration |
|
PostgreSQL CREATE TABLEPostgreSQL ALTER TABLEPostgreSQL backuppg_dump |
| Logging & Audit |
|
OWASP Logging Cheat SheetDocker loggingdocker compose logs |
| Security Quality Gates |
|
npm dependency auditSonarQube quality gatesTrivy image scanDocker Scout |
| AI Model to API |
|
OpenAI audio API referenceGoogle Cloud VisionAzure Document Intelligence |
| OCR / Speech / TTS |
|
Google Vision OCR/faceAzure Document IntelligenceOpenAI TTS/STT API |
| AI MVP for Foreman |
|
ISO/IEC 42001 AI management systemNIST AI RMF |
| ERP API Request |
|
Learn OpenAPIOpenAPI Initiative |
| API Spec |
|
OpenAPI specificationsOpenAPI explained |
| Postman Handoff |
|
Postman collections docsPostman collections overview |
| Production Runbook |
|
GitHub Actions deploymentMonitor workflows |
| Pipeline Monitor |
|
GitHub deployment historyGitHub workflow monitoring |
| Remote EC2 & Git |
|
AWS EC2 connectgit statusgit log |
| Public vs Internal Boundary |
|
OWASP Security RequirementsAWS playbooks |
| Nginx Troubleshooting |
|
NGINX troubleshootingproxy module |
| Compose Healthcheck |
|
Docker Compose healthcheckCompose startup order |
| Safe FE Base Path |
|
Next.js basePathNext.js page API |
| BFF Flow & Token |
|
BFF patternCORS docs |
| API Error, Security & Idempotency |
|
RFC 7807OpenAPI 3.1RFC 9110 |
| Observability & Incident |
|
SRE handbookOpenTelemetry observability |
| Training, Labs & Assessment |
|
Training by doing12 factor checklists |
| Final Handbook Publish Checklist |
|
Nielsen Norman checklist useAtlassian checklists |
| Maintenance |
|
AWS EC2 backupAWS playbooksNIST incident handling |
References
ลิงก์เหล่านี้เป็นแหล่งอ่านต่อหลัก แยกตามกลุ่มเพื่อให้ junior dev เรียนต่อได้เอง.