数据层:Supabase
在 web-nextjs 中使用 Supabase,包括自部署(Docker Compose)完整配置指南。
数据层:Supabase
Supabase Cloud vs 自部署
| 特性 | Supabase Cloud | 自部署(Docker Compose) |
|---|---|---|
| 上手速度 | ⚡ 快速,几分钟即可创建项目 | 需要 Docker 知识和服务器配置 |
| 免费额度 | 有(2 个项目,500MB 数据库) | 无限制(取决于你的硬件) |
| 数据掌控 | 数据存储在 Supabase 云端 | 数据完全在你自己的服务器上 |
| 存储限制 | 有(免费版 1GB) | 无限制(取决于硬盘容量) |
| 扩展性 | 自动扩展,按需升级 | 需要手动扩展 |
| 维护成本 | 零(Supabase 团队维护) | 需要自行维护、升级、备份 |
| 国内访问 | 较慢(服务器在海外) | 快(部署在国内服务器) |
建议:开发阶段使用 Supabase Cloud 快速开始;生产环境推荐自部署,以获得更好的数据掌控和国内访问速度。
快速开始:Docker Compose 自部署
前置条件
- Docker ≥ 20.10
- Docker Compose ≥ 2.0
- 服务器开放端口:
8000(Supabase Studio)、54321(API Gateway)、5432(PostgreSQL)
步骤 1:克隆官方 docker-compose 配置
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env步骤 2:关键环境变量说明
编辑 .env 文件,以下变量必须修改:
# 数据库密码(必改,默认值不安全)
POSTGRES_PASSWORD=your-super-strong-password
# JWT 密钥(至少 32 位随机字符串)
# 生成方式:
openssl rand -base64 32
JWT_SECRET=your-generated-jwt-secret
# API 密钥(ANON_KEY 公开使用,SERVICE_ROLE_KEY 仅服务端使用)
# 使用官方生成器:https://supabase.com/docs/guides/self-hosting/docker#generate-api-keys
ANON_KEY=eyJh...
SERVICE_ROLE_KEY=eyJh...
# Studio 登录凭据
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=your-strong-dashboard-password步骤 3:启动所有服务
docker compose up -d服务包括:PostgreSQL、Kong API Gateway、Supabase Studio、Auth、Realtime、Storage、Edge Functions 等。
步骤 4:验证
访问 http://localhost:8000(Supabase Studio),使用 .env 中的 DASHBOARD_USERNAME / DASHBOARD_PASSWORD 登录。
身份认证配置
邮件发送配置(SMTP)
开发环境默认使用 Inbucket(邮件都路由到 http://localhost:54324,方便调试)。生产环境需配置真实 SMTP。
.env 中 SMTP 配置:
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-smtp-user
SMTP_PASS=your-smtp-password
SMTP_SENDER_NAME=My App推荐的国内邮件服务:
- 阿里云邮件推送(DirectMail)
- 腾讯云 SES
- Resend(国际服务,对国内支持一般)
第三方登录(OAuth)
GitHub OAuth
- 登录 GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
- 回调 URL 填:
http://你的域名:8000/auth/v1/callback - 获取 Client ID 和 Client Secret
- 在 Supabase Studio → Authentication → Providers → GitHub 中填入
Google OAuth
- 前往 Google Cloud Console → API 和服务 → 凭据 → 创建 OAuth 2.0 客户端 ID
- 回调 URL 同 GitHub
- 在 Supabase Studio 中填入 Client ID 和 Secret
微信登录
微信开放平台(open.weixin.qq.com)申请网站应用 → 获取 AppID/AppSecret。
Supabase 目前不内置微信 OAuth,推荐通过以下方式集成:
- Edge Function 中间层:编写自定义 OAuth provider
- 第三方 Auth 服务:如 Authing、Casdoor 作为中间层,桥接微信登录和 Supabase Auth
国内短信验证码
Supabase Auth 支持自定义 SMS 提供商,通过 Edge Function 作为中间层调用国内短信 API。
阿里云短信(Aliyun SMS)
- 登录阿里云控制台 → 短信服务
- 申请签名(需营业执照) → 申请模板
- 编写 Edge Function 调用阿里云 SMS API
- 在 Supabase Studio → Authentication → SMS Providers → 选择「Custom」→ 填入 Edge Function URL
腾讯云短信(Tencent SMS)
- 登录腾讯云控制台 → 短信 → 创建应用
- 申请签名和模板
- 集成方式同阿里云(Edge Function 中间层)
数据表与 RLS 安全
执行迁移
将 supabase/migrations/ 目录下的 SQL 文件在 Supabase Studio 的 SQL Editor 中逐一执行:
- Dashboard → SQL Editor
- 粘贴 SQL 文件内容
- 点击 Run
自定义 schema 说明
web-nextjs 模板的 SQL 文件使用 __SCHEMA__ 占位符。通过 CLI --schema 参数创建项目时会自动替换。
手动替换方式:在 SQL 文件中全局搜索替换 __SCHEMA__ 为你的 schema 名称(如 myapp),再执行 SQL。
RLS 最佳实践
SERVICE_ROLE_KEY可绕过 RLS(仅在服务端 Route Handler 中使用)anon/authenticatedkey 必须遵守 RLS 策略- 每张表建表后立即启用 RLS:
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
文件存储(Storage)
配置
自部署 Storage 支持以下后端:
- 本地文件系统:
.env中STORAGE_BACKEND=file - S3 兼容存储(如 MinIO):
STORAGE_BACKEND=s3
在 web-nextjs 中使用
// Server Action 中使用 Supabase Storage SDK
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(supabaseUrl, serviceRoleKey)
const { data, error } = await supabase.storage.from('avatars').upload(`${userId}/profile.jpg`, file)数据备份
pg_dump 方式(推荐,最通用)
# 备份(在宿主机执行)
docker exec -t supabase-db pg_dump -U postgres -d postgres > backup_$(date +%Y%m%d_%H%M%S).sql
# 恢复
docker exec -i supabase-db psql -U postgres -d postgres < backup_20250101_000000.sqlDocker volume 备份
直接备份 Docker volume 目录(/var/lib/docker/volumes/supabase_db_data)。
自动化定时备份
# 每天凌晨 3 点自动备份(添加到 crontab)
0 3 * * * docker exec -t supabase-db pg_dump -U postgres -d postgres > /backup/db_$(date +\%Y\%m\%d).sqlRealtime
自部署 Realtime 已包含在 Docker Compose 中(realtime 服务)。
启用表的 Realtime
Dashboard → Database → Replication → 勾选对应表。
在 Next.js 客户端组件中订阅
const channel = supabase
.channel('payments-changes')
.on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'payments' }, (payload) => {
console.log('Change received!', payload)
})
.subscribe()Edge Functions
自部署使用 Deno 运行时(edge-runtime 服务,已在 Docker Compose 中)。
本地开发
supabase functions serve <function-name>部署到自部署实例
将函数文件放入 supabase/docker/volumes/functions/ 目录后重启 edge-runtime 容器:
docker compose restart edge-runtimeAI 功能(pgvector)
启用 pgvector 扩展
在 SQL Editor 中执行:
CREATE EXTENSION IF NOT EXISTS vector;创建向量列
ALTER TABLE documents ADD COLUMN embedding vector(1536);
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);在 Server Action 中结合 OpenAI 进行语义检索
'use server'
import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
export async function searchDocuments(query: string) {
const embedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: query,
})
const { data } = await supabase.rpc('match_documents', {
query_embedding: embedding.data[0].embedding,
match_count: 10,
})
return data
}MCP Server
Supabase MCP Server 让 AI 编程助手(GitHub Copilot、Cursor 等)可以直接操作 Supabase —— 读写数据库、管理表结构。
安装
npx @supabase/mcp-server-supabase@latest在 VS Code + GitHub Copilot 中配置
创建 .vscode/mcp.json:
{
"servers": {
"supabase": {
"command": "npx",
"args": [
"-y",
"@supabase/mcp-server-supabase@latest",
"--supabase-url",
"http://localhost:8000",
"--supabase-key",
"<your-service-role-key>"
]
}
}
}在 Cursor 中配置
编辑 ~/.cursor/mcp.json,内容同上。
参考:Supabase MCP
安全注意事项
- ⚠️ 生产环境必须修改的默认值:
POSTGRES_PASSWORDJWT_SECRETANON_KEYSERVICE_ROLE_KEYDASHBOARD_USERNAMEDASHBOARD_PASSWORD
- ⚠️
SERVICE_ROLE_KEY绝不能出现在客户端代码中(不能以NEXT_PUBLIC_开头) - ⚠️ 建议在 Supabase 前使用反向代理(Nginx/Traefik)做 SSL 终止,不要直接暴露 8000 端口
- ⚠️ 定期检查 Docker 镜像更新:
docker compose pull && docker compose up -d
常见问题(FAQ)
Q: 自部署后收不到邮件?
→ 检查 SMTP 配置,使用 Inbucket (localhost:54324) 调试。
Q: Studio 无法访问?
→ 检查 http://localhost:8000 是否通,检查 Docker 端口映射(docker ps)。
Q: RLS 导致查询返回空?
→ 在 Studio 中检查 policy 定义,或临时用 SERVICE_ROLE_KEY 测试。
Q: auth.users 和自定义表如何关联?
→ 使用 REFERENCES auth.users(id) ON DELETE CASCADE。
Q: 自部署和 Cloud 的 SDK 用法有区别吗? → 无区别,只需将 URL 和 key 换为自部署地址即可。