Appearance
🚀 Deploy lên Google Cloud Run
DB dùng Neon (đã có). App deploy lên Cloud Run — build từ source, không cần Docker local.
⚠️ Lưu ý kiến trúc Phase 0 trên serverless
Cloud Run scale-to-zero theo request. Hai hệ quả:
- ExpiryService (cron in-process) chỉ chạy khi có instance sống. Khi scale về 0, cron dừng → đơn quá hạn chỉ bị huỷ khi có request mới đánh thức instance. Chấp nhận được cho test; production cần Cloud Scheduler gọi endpoint
/cron/expirehoặc giữmin-instances=1(tốn quota). - Refresh token / session lưu DB (Neon) nên OK — không phụ thuộc instance.
Bước 1 — Tạo Google Cloud project + bật billing
- Vào https://console.cloud.google.com → tạo project (vd
gghut). - Billing: liên kết thẻ (Cloud Run free tier cần billing account; free 2M request/tháng).
Bước 2 — Đăng nhập gcloud
bash
gcloud auth login # mở browser đăng nhập
gcloud config set project <PROJECT_ID> # vd: gghutBước 3 — Bật APIs
bash
gcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.comBước 4 — Export secrets (KHÔNG commit)
bash
export DATABASE_URL="postgresql://neondb_owner:...@ep-....neon.tech/neondb?sslmode=require&channel_binding=require"
export JWT_SECRET="$(openssl rand -hex 32)" # hoặc dùng secret đã sinh sẵnBước 5 — Deploy
bash
./deploy.shScript sẽ build image bằng Cloud Build rồi deploy. Lấy URL:
bash
gcloud run services describe gghut-core --region asia-southeast1 --format 'value(status.url)'Bước 6 — Test
bash
URL="https://<service-url>.a.run.app"
curl "$URL/livez" # {"data":{"status":"ok"}}
curl "$URL/readyz" # {"data":{"status":"ready"}}
# Register + login
curl -X POST "$URL/api/v1/auth/register" -H 'Content-Type: application/json' \
-d '{"email":"admin@test.com","password":"password123","full_name":"Admin"}'Cấu hình đang dùng
| Biến | Giá trị |
|---|---|
| Region | asia-southeast1 (Singapore, gần Neon) |
| Memory / CPU | 512Mi / 1 vCPU |
| Min / Max instances | 0 / 1 (scale-to-zero, free) |
| Concurrency | 80 |
| Auth | --allow-unauthenticated (API công khai) |
Hardening trước khi chạy thật
- [ ] Chuyển
JWT_SECRET,DATABASE_URLsang Secret Manager (--set-secrets) thay vì--set-env-vars - [ ] Thêm Cloud Scheduler cho expiry cron (gọi
/cron/expirevới header xác thực) - [ ] Siết CORS (hiện
*) về đúng domain frontend - [ ] Bỏ
--allow-unauthenticatednếu muốn xác thực ở layer khác