跳转到内容
supastack
浏览文档

For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /zh/docs/web/deploy-google-cloud.md (or send Accept: text/markdown).

部署到 Google Cloud

在 Cloud Build 上构建套件的 Docker 镜像,用托管密钥在 Cloud Run 上运行,并绑定你的域名。

询问本指南
打开方式

初学者演练

前提条件:应用在本地可用、一个可以从互联网访问的真实数据库(设置数据库),以及你要上线的功能对应的服务商账户。你需要一个 Google 账户;配置结算时会要求绑定银行卡,尽管轻度使用仍在免费额度内。

快速术语:容器镜像是应用打包后的副本,任何主机都能运行。Artifact Registry 是 Google 存放镜像的仓库。Cloud Build 在 Google 的机器上构建镜像——本地不需要 Docker。Cloud Run 把镜像作为 HTTPS 服务运行并自动扩缩。Secret Manager 保存密码和密钥。修订版本(revision)是服务的一次部署版本。

你将构建的内容:一个 Google Cloud 项目、一个存放镜像的 Artifact Registry 仓库、一个通过 HTTPS 提供应用的 Cloud Run 服务、存放在 Secret Manager 中的密钥,以及一个托管 Postgres。套件根目录的 Dockerfile 已经能产出一个监听 8080 端口的独立 Next.js 服务器——正是 Cloud Run 所期望的。

诚实的成本说明:Cloud Run 的免费额度可以覆盖轻度流量,但 Cloud SQL——Google 的托管 Postgres——没有免费层。Supabase 或 Neon 的免费数据库是最便宜的起步方式;本指南走这条路。建议在 Billing → Budgets & alerts 下添加预算提醒,然后再开始折腾。

创建账户并安装 CLI

1. 打开 console.cloud.google.com,用你的 Google 账户登录并接受条款。

2. 按提示关联结算:Billing → Link a billing account → Create billing account。激活账户需要银行卡;试用额度可以覆盖早期实验。

3. 点击项目下拉菜单 → New Project,命名并 Create——或复用你为 Google 登录创建的项目;一个项目就够了。

4. 从 cloud.google.com/sdk 安装 Google Cloud CLI:下载适合你操作系统的安装程序并完成安装,然后打开一个新终端,让 gcloud 命令可用。

5. 运行下面两条命令。第一条会打开浏览器为 CLI 授权;第二条选择你的项目——使用控制台仪表板上显示的项目 ID,它不一定和名称相同。

预期结果:gcloud config list 显示你的账户和项目。如果 gcloud 无法识别,重新打开终端或先完成安装程序。

gcloud auth login
gcloud config set project YOUR_PROJECT_ID

创建生产数据库

新手路径——Google 之外的托管 Postgres。在 supabase.com:New project → 选择名称、数据库密码和区域 → 等待初始化 → Project Settings → Database。Supabase 提供两种连接串:5432 端口的会话池/直连,和 6543 端口的事务池——5432 串用于迁移和长连接客户端,6543 串用于无服务器应用。在 neon.tech:New project → 复制它显示的连接串。两者都可以;保持密码部分完整。

把直连/会话串放进根目录 .env 的 DATABASE_URL——迁移工具读取根目录文件且需要会话连接——以及 apps/web/.env.local 供本地开发服务器使用。然后从仓库根目录运行一次迁移命令,在新数据库中创建套件的表。已部署应用使用的 DATABASE_URL 密钥也可以换成 6543 的池化串。

Google 原生替代方案是 Cloud SQL——同一项目内的托管 Postgres。它没有免费层,且私有 IP 连接需要 VPC 连接器——把它当作以后的升级,而不是起点。

# DATABASE_URL=<the direct/session Postgres string, port 5432> in .env + apps/web/.env.local, then:
corepack pnpm --filter @supastack/db db:migrate

启用服务并推送镜像

从仓库根目录运行下面的命令。它们会启用本次部署用到的四个 Google 服务、在 Artifact Registry 中创建 Docker 仓库,并把仓库提交给 Cloud Build——它在远端构建根目录的 Dockerfile,因此不需要 Docker Desktop。

替换 YOUR_PROJECT_ID,并选择一个区域——下面是 us-central1——仓库和服务都复用它。预期结果:构建日志滚动数分钟,以 DONE / STATUS: SUCCESS 结束。随后镜像会出现在控制台的 Artifact Registry → supastack → web 下。

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

gcloud artifacts repositories create supastack --repository-format=docker --location=us-central1

gcloud builds submit --tag us-central1-docker.pkg.dev/YOUR_PROJECT_ID/supastack/web:latest

把密钥存入 Secret Manager

密钥绝不能进入 --set-env-vars 或镜像——两者都以明文存储,任何能读取服务配置的人都看得见。Secret Manager 让它们保持加密并在运行时注入。

1. 在控制台打开 Security → Secret Manager → Create Secret。

2. 创建 DATABASE_URL,值为完整的 Postgres 连接串——池化的无服务器串对应用来说就可以;AUTH_SECRET,至少 32 个随机字符(openssl rand -hex 32 可以生成一个);以及 CREDENTIAL_ENCRYPTION_KEY,值为 Base64 编码的 32 字节密钥(openssl rand -base64 32);它用于加密工作区在应用中保存的服务商密钥。

3. 为每个已启用的服务商各建一个密钥——例如 STRIPE_SECRET_KEY 加 STRIPE_WEBHOOK_SECRET、RESEND_API_KEY、GOOGLE_CLIENT_SECRET、GITHUB_CLIENT_SECRET。像 EMAIL_PROVIDER=resend 这样的非机密设置保持为普通环境变量,不要做成密钥。

服务第一次引用某个密钥时,它的运行时服务账户需要读取权限——通过控制台的服务编辑器挂载密钥时,Google 会自动提供该授权;在 CLI 上,部署错误会报出需要授予的 Secret Manager 角色名。

# Secrets to create in Secret Manager:
DATABASE_URL     # Postgres connection string — the pooled serverless string is fine
AUTH_SECRET      # openssl rand -hex 32
CREDENTIAL_ENCRYPTION_KEY   # openssl rand -base64 32

# plus one per enabled provider, e.g.:
STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET
RESEND_API_KEY
GOOGLE_CLIENT_SECRET
GITHUB_CLIENT_SECRET

部署 Cloud Run 服务

控制台路径:Cloud Run → Create service → Deploy one revision from an existing container image → 选择刚推送的 …/supastack/web:latest 镜像 → 选择相同区域 → 在 Authentication 下选择 Allow unauthenticated invocations(这是一个公开应用)→ Create。

下面的 CLI 等价命令在同一步骤中加上环境变量接线。明文配置放进 --set-env-vars;密钥在 --set-secrets 中按 Secret Manager 名称引用。把你的服务商开关(EMAIL_PROVIDER、BILLING_PROVIDER、AI_PROVIDER、JOB_PROVIDER)作为普通环境变量与 APP_URL 并列添加。

APP_ENV=production 是必需的——没有它,应用会以 local 模式启动:生产配置校验被跳过,安全 cookie 前缀保持关闭,仅限开发的 /mail-preview 页面仍然公开可访问(当 EMAIL_PROVIDER=local 时会泄露本地邮件发件箱)。生产环境在启动时还需要另外四个值:EXPO_PUBLIC_API_URL 是移动应用访问 API 所用的公开 https URL——设为服务 URL(纯 Web 部署时与 APP_URL 相同);EXPO_PUBLIC_APP_SCHEME 是移动端深链 scheme——不上线移动应用时,任何合法值如 supastack 都可以;MOBILE_ALLOWED_ORIGINS 是服务器信任的精确 https origin 的逗号分隔列表——你的应用 URL 就是正确的起点,通配符会被拒绝;CREDENTIAL_ENCRYPTION_KEY 加密已保存的服务商凭据,留在 Secret Manager 中。

首次部署时 Cloud Run 会分配一个 https://….run.app URL,而应用的 APP_URL 必须等于它的真实公开 URL,认证回调和链接才能工作。所以先用占位符部署一次,从服务页面复制 *.run.app URL,然后更新服务(控制台:Edit & deploy new revision,或重新运行该命令),把 APP_URL——以及对应的 EXPO_PUBLIC_API_URL / MOBILE_ALLOWED_ORIGINS 值——设置为它。容器端口保持 8080——Cloud Run 的默认值已经与 Dockerfile 的 PORT 一致。

gcloud run deploy supastack --image us-central1-docker.pkg.dev/YOUR_PROJECT_ID/supastack/web:latest --region us-central1 --allow-unauthenticated --set-env-vars "APP_ENV=production,APP_URL=https://YOUR_SERVICE_URL,EXPO_PUBLIC_API_URL=https://YOUR_SERVICE_URL,EXPO_PUBLIC_APP_SCHEME=supastack,MOBILE_ALLOWED_ORIGINS=https://YOUR_SERVICE_URL" --set-secrets "DATABASE_URL=DATABASE_URL:latest,AUTH_SECRET=AUTH_SECRET:latest,CREDENTIAL_ENCRYPTION_KEY=CREDENTIAL_ENCRYPTION_KEY:latest"

绑定你自己的域名(可选)

测试期间可以跳过——*.run.app URL 已经提供 HTTPS。准备好后:Cloud Run → 你的服务 → Custom Domains / Domain Mappings → Add mapping → 选择服务并输入你的域名。

如有提示请验证域名所有权(Google 会引导你完成),然后在你的域名注册商处创建映射屏幕列出的 DNS 记录。记录生效后,托管的 HTTPS 证书会自动签发——通常几分钟,最长一天。

域名开始承载流量后,把 APP_URL 更新为 https://yourdomain.com,并注册对应的 OAuth redirect URI(https://yourdomain.com/api/auth/callback/…)——登录指南会说明在哪里配置。

验证部署

打开 https://YOUR_SERVICE_URL/api/health——应返回 ok。然后端到端走一遍应用:打开 URL、注册、请求邮件验证码、确认它能到达收件箱(这需要 EMAIL_PROVIDER=resend、RESEND_API_KEY 和已验证的发件人——本地适配器永远到不了真实收件箱)、登录并使用一个你启用的功能。

Cloud Run → 你的服务 → Logs 显示请求和错误输出。如果部署出问题,Revisions 选项卡提供一键回滚到上一个修订版本。

移动端和桌面客户端必须指向这个 HTTPS 后端:Expo 用 apps/mobile/.env.local 中的 EXPO_PUBLIC_API_URL,桌面外壳用 SUPASTACK_APP_URL。

常见问题

14 个问题

supastack 是什么?

supastack 是用于构建 AI 驱动 SaaS 产品的模块化基础。它把通用基础设施整合在一起,让你专注于产品专属的功能。

它支持 Web 和移动端吗?

支持。supastack 包含 Next.js 与 Expo 应用,作为 Web 与移动端体验的起点。

包含哪些认证方式?

Better Auth 覆盖邮箱/密码、OTP 与社交登录。个人工作区随账户一起开通,产品记录从第一天起就有边界。

AI 是如何支持的?

supastack 包含可配置的多供应商 AI、用量追踪、预算,以及加密的自带密钥(BYOK)支持。

订阅如何处理?

对于基于该套件构建的产品,Stripe 计费、订阅与权限构成付费访问的基础。供应商密钥仅存于服务端。

我的产品专属代码放在哪里?

产品专属功能保留在独立的代码库中,产品通过配置接入 supastack 的基础模块。

supastack 如何定价?

套件为一次性购买、终身更新:单框架 249 美元(限时优惠价,较常规价 349 美元优惠 100 美元),或全框架(Next.js、iOS、Android)499 美元(限时优惠价,较常规价 599 美元优惠 100 美元),每个额外开发者席位 75 美元。套件本身没有订阅。本站结账后通过邮件发送许可证密钥,仓库访问通过 GitHub 邀请授予。

工作区如何界定我的数据?

用户记录按 workspaceId 划定边界。身份、权限、AI 用量、计费事件与审计条目都留在个人工作区边界内。

后台任务如何工作?

Trigger.dev 是明确的任务运行时。JobRunner 契约只承诺 enqueue、status 与 cancel——工作流语义保持 Trigger.dev 专有且显式。

邮件与营销触达有何不同?

事务性邮件覆盖产品工作流,如任务完成通知。冷触达与营销活动属于产品自身的范畴,不在本套件的邮件模块内。

移动端购买如何运作?

移动端已支持 RevenueCat 原生购买和恢复购买,访问权限由服务端验证。发布前需配置商店账户并完成设备测试。Web 计费保持独立。

AI 供应商密钥存放在哪里?

自带密钥凭证经过加密且仅存于服务端。密钥在日志中被脱敏;用量与预算在工作区级别保持可见。

结账支持哪些付款方式?

Stripe 托管结账接受银行卡,在 Stripe 账户启用后还可提供支付宝与微信支付——方便中国买家。钱包授权为异步确认,付款完成后许可证页面会立即更新。

我能申请退款吗?

获得代码仓库访问权限后,supastack 将永久归你所有,因此无法退款。但请放心,你将获得包含终身更新的完整源代码,可为你自己或客户构建并发布无限数量的产品。你只需注意不能转卖代码,也不能将仓库作为启动模板二次分发。

CN
主题