Skip to content

🚀 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ả:

  1. 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/expire hoặc giữ min-instances=1 (tốn quota).
  2. 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

  1. Vào https://console.cloud.google.com → tạo project (vd gghut).
  2. 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: gghut

Bước 3 — Bật APIs

bash
gcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com

Bướ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ẵn

Bước 5 — Deploy

bash
./deploy.sh

Script 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ếnGiá trị
Regionasia-southeast1 (Singapore, gần Neon)
Memory / CPU512Mi / 1 vCPU
Min / Max instances0 / 1 (scale-to-zero, free)
Concurrency80
Auth--allow-unauthenticated (API công khai)

Hardening trước khi chạy thật

  • [ ] Chuyển JWT_SECRET, DATABASE_URL sang Secret Manager (--set-secrets) thay vì --set-env-vars
  • [ ] Thêm Cloud Scheduler cho expiry cron (gọi /cron/expire với header xác thực)
  • [ ] Siết CORS (hiện *) về đúng domain frontend
  • [ ] Bỏ --allow-unauthenticated nếu muốn xác thực ở layer khác