Files
goodgo-platform/docs/deployment.md
Ho Ngoc Hai d8b409a9ab
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 18s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m15s
Deploy / Build API Image (push) Failing after 28s
Deploy / Build Web Image (push) Failing after 16s
Deploy / Build AI Services Image (push) Failing after 17s
E2E Tests / Playwright E2E (push) Failing after 31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 3s
Security Scanning / Trivy Scan — API Image (push) Failing after 1m46s
Security Scanning / Trivy Scan — Web Image (push) Failing after 1m7s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 53s
Security Scanning / Trivy Filesystem Scan (push) Failing after 35s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 0s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
docs: dịch 22 file Markdown còn lại sang tiếng Việt có dấu (TEC-2881)
Hoàn tất đợt cuối của nhiệm vụ chuyển toàn bộ tài liệu sang tiếng Việt.
Đã dịch 22 file `.md` còn sót (~9.7k dòng) — gồm RUNBOOK, audits,
docs/architecture, docs/load-testing, libs READMEs và các quick references.
Giữ nguyên code blocks, đường dẫn, identifier kỹ thuật, URL và biến môi trường.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-19 03:26:14 +07:00

14 KiB

Hướng Dẫn Deployment

Tổng Quan

GoodGo Platform AI gồm bốn dịch vụ có thể deploy:

Dịch vụ Công nghệ Port mặc định
API NestJS (Node.js) 3001
Web Next.js 3000
AI Services FastAPI (Python) 8000
Infrastructure Docker Compose Khác nhau

Yêu Cầu Trước

  • Docker Engine 24+ & Docker Compose v2
  • Node.js 22 LTS
  • pnpm 10.27+
  • Python 3.12 (cho AI services, nếu chạy ngoài Docker)

Cấu Hình Môi Trường

Sao chép .env.example thành .env và cấu hình tất cả giá trị bắt buộc:

cp .env.example .env

Biến Bắt Buộc

Biến Mô tả Ví dụ
DATABASE_URL Chuỗi kết nối PostgreSQL postgresql://user:pass@host:5432/goodgo
JWT_SECRET Khóa ký JWT (tối thiểu 32 ký tự) Tạo bằng openssl rand -hex 32
JWT_REFRESH_SECRET Khóa ký refresh token Tạo bằng openssl rand -hex 32
REDIS_URL Chuỗi kết nối Redis redis://localhost:6379
TYPESENSE_API_KEY API key admin Typesense Tạo một khóa ngẫu nhiên an toàn

Biến Tùy Chọn

Biến Mô tả Mặc định
API_PORT Port API server 3000
WEB_PORT Port web app 3001
NODE_ENV Chế độ môi trường development
CORS_ORIGINS Các origin CORS được phép
CLAUDE_API_KEY Claude API key (cho content moderation)
NEXT_PUBLIC_MAPBOX_TOKEN Token Mapbox (cho bản đồ)
VNPAY_*, MOMO_*, ZALOPAY_* Thông tin payment gateway

Cài Đặt Hạ Tầng (Docker Compose)

Khởi động tất cả dịch vụ hạ tầng:

docker compose up -d

Lệnh này khởi động:

  • PostgreSQL 16 + PostGIS 3.4 (port 5432)
  • Redis 7 (port 6379)
  • Typesense 27 (port 8108)
  • MinIO (API: 9000, Console: 9001)
  • AI Services (port 8000)
  • pg-backup — backup PostgreSQL hằng ngày tự động lúc 02:00 UTC, có verify lúc 04:00 UTC
  • Loki (port 3100) — tổng hợp log
  • Promtail — agent thu thập log (chuyển log container đến Loki)
  • Prometheus (port 9090)
  • Grafana (port 3002) — dashboard cho metric và log

Kiểm tra tất cả dịch vụ đang khỏe mạnh:

docker compose ps

Tất cả dịch vụ đều có health check. Đợi đến khi tất cả hiển thị trạng thái healthy.

Cài Đặt Database

# Sinh Prisma client
pnpm db:generate

# Áp dụng migration
pnpm db:migrate:deploy

# Seed dữ liệu khởi tạo (tùy chọn)
pnpm db:seed

Build cho Production

API (NestJS)

cd apps/api
pnpm build

Output: apps/api/dist/

Chạy trong production:

NODE_ENV=production PORT=3001 node apps/api/dist/main.js

Web (Next.js)

cd apps/web
pnpm build

Output: apps/web/.next/

Chạy trong production:

NODE_ENV=production pnpm --filter web start

AI Services (FastAPI)

AI service chạy trong Docker qua docker compose. Để build riêng:

cd libs/ai-services
docker build -t goodgo-ai-services .
docker run -p 8000:8000 --env-file ../../.env goodgo-ai-services

Checklist Production

Bảo Mật

  • Đặt JWT_SECRETJWT_REFRESH_SECRET mạnh, độc nhất (tối thiểu 32 ký tự)
  • Đặt NODE_ENV=production
  • Cấu hình CORS_ORIGINS chỉ cho phép domain của bạn
  • Đổi mật khẩu database mặc định
  • Đổi credential MinIO mặc định (MINIO_USER, MINIO_PASSWORD)
  • Đổi credential Grafana mặc định (GRAFANA_ADMIN_USER, GRAFANA_ADMIN_PASSWORD)
  • Dùng TYPESENSE_API_KEY mạnh, độc nhất
  • Bật SSL/TLS termination (reverse proxy)
  • Đặt MINIO_USE_SSL=true nếu MinIO được public

Database

  • Chạy pnpm db:migrate:deploy (không dùng db:migrate:dev)
  • Bật connection pooling cho PostgreSQL (khuyến nghị PgBouncer)
  • Cấu hình backup tự động
  • Đặt max_connections phù hợp trong cấu hình PostgreSQL

Monitoring

  • Xác nhận Prometheus đang scrape endpoint /metrics
  • Import dashboard Grafana từ monitoring/grafana/dashboards/
  • Cài đặt rule alerting cho error rate và latency

Performance

  • Cấu hình Redis maxmemory và chính sách eviction
  • Đặt --memory-limit phù hợp cho Typesense
  • Bật nén gzip/brotli ở reverse proxy
  • Cấu hình CDN cho static asset (Next.js /_next/static/)

Health Check

Dịch vụ Endpoint Phản hồi mong đợi
API GET /health {"status": "ok"}
API (Swagger) GET /api/v1/docs Trang Swagger UI
API (Metrics) GET /api/v1/metrics Metric Prometheus
AI Services GET /health {"status": "ok"}
Typesense GET /health {"ok": true}
Loki GET /ready 200 OK
Redis redis-cli ping PONG
PostgreSQL pg_isready -h host -p 5432 Exit code 0

Cân Nhắc Về Scaling

Horizontal Scaling

  • API: Stateless — scale với nhiều instance phía sau load balancer
  • Web: Stateless — scale với nhiều instance hoặc deploy lên Vercel/Cloudflare
  • AI Services: CPU-bound — scale theo lượng yêu cầu định giá
  • Redis: Dùng Redis Cluster cho tính sẵn sàng cao
  • PostgreSQL: Read replica cho workload nhiều truy vấn

Kiến Trúc Khuyến Nghị (Production)

                    ┌─────────────┐
                    │ Load Balancer│
                    │ (nginx/ALB)  │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────▼──┐  ┌─────▼──┐  ┌─────▼──┐
        │ API #1 │  │ API #2 │  │ API #N │
        └────────┘  └────────┘  └────────┘
              │            │            │
              └────────────┼────────────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────▼──┐  ┌─────▼──┐  ┌─────▼─────┐
        │  PG    │  │ Redis  │  │ Typesense  │
        │Primary │  │Cluster │  │  Cluster   │
        │+ Replica│  │        │  │            │
        └────────┘  └────────┘  └────────────┘

CI/CD Pipeline

Chiến Lược Branch

Branch Đích deploy Trigger Ghi chú
develop Staging Tự động (push) Mọi merge vào develop đều tự deploy lên staging
master Staging Tự động (push) Push master cũng deploy lên staging để verify
Manual Staging/Production workflow_dispatch Trigger thủ công qua GitHub Actions UI

Quy Trình Auto-Deploy Staging

Push to develop → Build images → Tag rollback → Deploy to staging → Smoke tests → Cleanup / Rollback
  1. Build: Docker image cho API, Web, và AI Services được build và push lên GHCR với tag staging-latest
  2. Tag rollback: Image hiện đang chạy được tag là :rollback trước khi pull image mới
  3. Deploy: Image mới được pull và dịch vụ được cập nhật qua rolling restart (zero-downtime)
  4. Verify: Health check poll $STAGING_URL/health trong tối đa 100 giây
  5. Smoke test: scripts/smoke-test.sh chạy với staging URL, kiểm tra health probe, các endpoint API cốt lõi, search và auth
  6. Cleanup: Khi thành công, các tag :rollback được xóa và docker image prune dọn dẹp các layer cũ
  7. Notify: Thông báo Slack khi thành công hoặc thất bại
  8. Rollback: Nếu smoke test thất bại, rollback tự động khôi phục image có tag :rollback

Thông Báo

Trạng thái deploy được gửi đến Slack qua secret SLACK_WEBHOOK_URL:

Sự kiện Kênh Nội dung
Smoke test staging pass Slack Commit SHA, branch, link đến run
Smoke test staging fail Slack 🚨 Commit SHA, branch, link đến run
Trigger rollback staging Slack ⚠️ Commit SHA, lý do, link đến run
Deploy production thành công Slack Commit SHA, branch
Trigger rollback production Slack ⚠️ Commit SHA, lý do, link đến run

Secret Bắt Buộc

Secret Môi trường Mô tả
STAGING_HOST staging Hostname/IP server staging
STAGING_USER staging User SSH cho deploy staging
STAGING_SSH_KEY staging Khóa SSH private cho staging
STAGING_URL staging URL gốc staging (vd: https://staging.goodgo.vn)
PRODUCTION_HOST production Hostname/IP server production
PRODUCTION_USER production User SSH cho deploy production
PRODUCTION_SSH_KEY production Khóa SSH private cho production
PRODUCTION_URL production URL gốc production
SLACK_WEBHOOK_URL cả hai URL incoming webhook Slack

Rollback

Cơ Chế An Toàn Khi Rollback

Pipeline deploy sử dụng tag image :rollback rõ ràng để bảo đảm rollback an toàn. Cách hoạt động như sau:

  1. Trước khi pull image mới: Image hiện đang chạy được tag là goodgo-api:rollback, goodgo-web:rollback, và goodgo-ai-services:rollback
  2. Sau khi pull image mới: Dịch vụ được cập nhật với image mới qua rolling restart
  3. Sau khi smoke test pass: Tag :rollback được xóa và docker image prune dọn dẹp layer cũ
  4. Nếu smoke test fail: Image có tag :rollback được dùng để khôi phục phiên bản trước

Điều này bảo đảm docker image prune không bao giờ xóa image cần cho rollback, vì:

  • Image pruning chỉ xảy ra sau khi smoke test pass
  • Tag :rollback giữ image trước được pin lại ngay cả khi pruning vô tình chạy

Rollback Tự Động (Staging)

Pipeline staging có rollback tự động khi smoke test thất bại:

  1. Trước deploy: Image container hiện tại được tag với hậu tố :rollback trước khi pull image mới
  2. Smoke test thất bại: Nếu scripts/smoke-test.sh thoát non-zero, job rollback-staging được trigger
  3. Thực hiện rollback: Container được dừng và khởi động lại bằng image có tag :rollback
  4. Verify: Health check xác nhận rollback đã thành công
  5. Notification: Slack báo cáo rollback kèm link đến run thất bại

Rollback Tự Động (Production)

Cơ chế giống staging — smoke test thất bại sẽ trigger rollback-production dùng image có tag :rollback.

Rollback Thủ Công

Để rollback thủ công một deployment staging hoặc production:

Lựa chọn 1: Re-deploy một commit đã biết là tốt

# Trigger deploy của một commit cụ thể qua GitHub Actions
gh workflow run deploy.yml \
  --ref <known-good-commit-or-branch> \
  -f environment=staging

Lựa chọn 2: SSH rollback dùng tag :rollback (nhanh nhất)

# SSH vào server staging/production
ssh deploy@<host>
cd ~/goodgo

# Dừng dịch vụ hiện tại
docker compose -f docker-compose.prod.yml stop api web ai-services

# Xác nhận image :rollback tồn tại
docker image inspect goodgo-api:rollback > /dev/null 2>&1 && echo "API rollback available"
docker image inspect goodgo-web:rollback > /dev/null 2>&1 && echo "Web rollback available"
docker image inspect goodgo-ai-services:rollback > /dev/null 2>&1 && echo "AI rollback available"

# Khởi động lại dịch vụ (compose lấy image cache/rollback)
docker compose -f docker-compose.prod.yml up -d --wait api web ai-services

# Verify health
curl -sf http://localhost:3001/health && echo "Rollback successful"

Lưu ý: Tag :rollback chỉ có sẵn cho đến khi lần deploy thành công kế tiếp dọn chúng đi. Nếu cần rollback về phiên bản cũ hơn, dùng Lựa chọn 3 dưới đây.

Lựa chọn 3: Pin về một image tag cụ thể

ssh deploy@<host>
cd ~/goodgo

# Đặt IMAGE_TAG về một SHA đã biết là tốt
export IMAGE_TAG=<known-good-commit-sha>
export REGISTRY_URL=ghcr.io/<owner>

# Pull và khởi động lại với tag đã pin
docker compose -f docker-compose.prod.yml pull api web ai-services
docker compose -f docker-compose.prod.yml up -d --no-deps --wait api web ai-services

Lựa chọn 4: Dùng deploy-production.sh (rollback tích hợp sẵn)

Script deploy thủ công (scripts/deploy-production.sh) có hỗ trợ rollback tích hợp:

  • Tự động tag image :rollback trước khi pull
  • Chạy health check và smoke test
  • Tự rollback dùng tag :rollback nếu một trong hai thất bại
  • Chỉ prune image sau khi smoke test pass
ssh ubuntu@185.225.232.65
cd ~/goodgo
./scripts/deploy-production.sh [image-tag]

Rollback Database

Prisma không hỗ trợ down migration tự động. Nếu một migration cần được hoàn tác:

  1. Xác định migration trong prisma/migrations/
  2. Viết script rollback SQL thủ công
  3. Áp dụng qua psql hoặc công cụ migration
  4. Cập nhật bảng _prisma_migrations

Luôn test migration với database staging trước khi deploy production.

Checklist Sau Rollback

  • Xác nhận health endpoint phản hồi: GET /health, GET /ready
  • Chạy smoke test thủ công: ./scripts/smoke-test.sh <url>
  • Kiểm tra log ứng dụng: docker compose -f docker-compose.prod.yml logs --tail=100 api web
  • Xác nhận dashboard Grafana hiển thị metric bình thường
  • Thông báo cho team qua Slack về rollback và nguyên nhân gốc