名称: bknd-deploy-hosting 描述: 用于将Bknd应用程序部署到生产托管平台。涵盖Cloudflare Workers/Pages、Node.js/Bun服务器、Docker、Vercel、AWS Lambda及其他平台。
部署到托管平台
将您的Bknd应用程序部署到各种托管平台。
前提条件
- 本地运行的Bknd应用程序
- 定义并测试的架构
- 已配置的数据库(参见
bknd-database-provision) - 准备好的环境变量(参见
bknd-env-config)
何时使用UI模式
- Cloudflare/Vercel仪表板用于环境变量
- 平台特定的部署设置
- 查看部署日志
何时使用代码模式
- 所有部署配置和命令
- 目标平台的适配器设置
- CI/CD流水线配置
平台选择指南
| 平台 | 最适合 | 数据库选项 | 冷启动时间 |
|---|---|---|---|
| Cloudflare Workers | 边缘计算,全球低延迟 | D1, Turso | ~0毫秒 |
| Cloudflare Pages | 静态 + API | D1, Turso | ~0毫秒 |
| Vercel | Next.js应用 | Turso, Neon | ~200毫秒 |
| Node.js/Bun VPS | 完全控制,专用 | 任意 | N/A |
| Docker | 容器化,可移植 | 任意 | N/A |
| AWS Lambda | 无服务器,按使用付费 | Turso, RDS | ~500毫秒 |
代码方法
Cloudflare Workers
步骤 1: 安装Wrangler
npm install -D wrangler
步骤 2: 创建 wrangler.toml
name = "my-bknd-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-d1-database-id"
# 可选:R2用于媒体存储
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "my-bucket"
[vars]
ENVIRONMENT = "production"
步骤 3: 配置适配器
// src/index.ts
import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
export default hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: {
secret: env.JWT_SECRET,
},
},
config: {
media: {
enabled: true,
adapter: {
type: "r2",
config: { bucket: env.R2_BUCKET },
},
},
},
}),
});
步骤 4: 创建D1数据库
# 创建数据库
wrangler d1 create my-database
# 将 database_id 复制到 wrangler.toml
步骤 5: 设置密钥
wrangler secret put JWT_SECRET
# 输入您的密钥(至少32个字符)
步骤 6: 部署
wrangler deploy
Cloudflare Pages(带有函数)
步骤 1: 创建 functions/api/[[bknd]].ts
import { hybrid, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
import { d1Sqlite } from "bknd/adapter/cloudflare";
import schema from "../../bknd.config";
export const onRequest = hybrid<CloudflareBkndConfig>({
app: (env) => ({
connection: d1Sqlite({ binding: env.DB }),
schema,
isProduction: true,
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
});
步骤 2: 配置Pages
在Cloudflare仪表板中:
- 连接您的git仓库
- 设置构建命令(如果有)
- 在设置 > 函数 > D1数据库绑定中添加D1绑定
- 在设置 > 环境变量中添加环境变量
Node.js / Bun(VPS)
步骤 1: 创建生产入口
// index.ts
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
// 或对于Node.js:
// import { serve } from "bknd/adapter/node";
const config: BunBkndConfig = {
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: {
secret: process.env.JWT_SECRET!,
expires: "7d",
},
},
config: {
media: {
enabled: true,
adapter: {
type: "s3",
config: {
bucket: process.env.S3_BUCKET!,
region: process.env.S3_REGION!,
accessKeyId: process.env.S3_ACCESS_KEY!,
secretAccessKey: process.env.S3_SECRET_KEY!,
},
},
},
guard: {
enabled: true,
},
},
};
serve(config);
步骤 2: 设置环境变量
export DB_URL="libsql://your-db.turso.io"
export DB_TOKEN="your-turso-token"
export JWT_SECRET="your-32-char-minimum-secret"
export PORT=3000
步骤 3: 使用进程管理器运行
# 使用 PM2
npm install -g pm2
pm2 start "bun run index.ts" --name bknd-app
# 或 systemd(创建 /etc/systemd/system/bknd.service)
Docker
步骤 1: 创建 Dockerfile
FROM oven/bun:1.0-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .
# 为基于文件的SQLite创建数据目录
RUN mkdir -p /app/data
ENV PORT=3000
EXPOSE 3000
CMD ["bun", "run", "index.ts"]
步骤 2: 创建 docker-compose.yml
version: "3.8"
services:
bknd:
build: .
ports:
- "3000:3000"
volumes:
- bknd-data:/app/data
environment:
- DB_URL=file:/app/data/bknd.db
- JWT_SECRET=${JWT_SECRET}
- NODE_ENV=production
restart: unless-stopped
volumes:
bknd-data:
步骤 3: 部署
# 构建并运行
docker compose up -d
# 查看日志
docker compose logs -f bknd
Vercel(Next.js)
步骤 1: 创建API路由
// app/api/bknd/[[...bknd]]/route.ts
export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";
步骤 2: 创建 bknd.config.ts
import type { NextjsBkndConfig } from "bknd/adapter/nextjs";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", {
title: text().required(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
export default {
app: (env) => ({
connection: {
url: env.DB_URL,
authToken: env.DB_TOKEN,
},
schema,
isProduction: env.NODE_ENV === "production",
auth: {
jwt: { secret: env.JWT_SECRET },
},
}),
} satisfies NextjsBkndConfig;
步骤 3: 设置Vercel环境变量
在Vercel仪表板或CLI中:
vercel env add DB_URL
vercel env add DB_TOKEN
vercel env add JWT_SECRET
步骤 4: 部署
vercel deploy --prod
AWS Lambda
步骤 1: 安装依赖
npm install -D serverless serverless-esbuild
步骤 2: 创建 handler.ts
import { createHandler } from "bknd/adapter/aws";
export const handler = createHandler({
connection: {
url: process.env.DB_URL!,
authToken: process.env.DB_TOKEN,
},
isProduction: true,
auth: {
jwt: { secret: process.env.JWT_SECRET! },
},
});
步骤 3: 创建 serverless.yml
service: bknd-api
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
environment:
DB_URL: ${env:DB_URL}
DB_TOKEN: ${env:DB_TOKEN}
JWT_SECRET: ${env:JWT_SECRET}
plugins:
- serverless-esbuild
functions:
api:
handler: handler.handler
events:
- http:
path: /{proxy+}
method: ANY
- http:
path: /
method: ANY
步骤 4: 部署
serverless deploy --stage prod
预部署检查清单
# 1. 生成类型
npx bknd types
# 2. 使用类似生产配置本地测试
DB_URL="your-prod-db" JWT_SECRET="your-secret" npx bknd run
# 3. 验证架构同步
# 架构在生产中的首次请求时自动同步
环境变量(所有平台)
| 变量 | 是否必需 | 描述 |
|---|---|---|
DB_URL |
是 | 数据库连接URL |
DB_TOKEN |
取决于 | 身份验证令牌(Turso/LibSQL) |
JWT_SECRET |
是 | 至少32个字符以确保安全 |
PORT |
否 | 服务器端口(默认:3000) |
常见问题
“Module not found” 用于本地SQLite
问题: better-sqlite3 在无服务器中不可用
解决方法: 使用LibSQL/Turso代替基于文件的SQLite:
connection: {
url: "libsql://your-db.turso.io",
authToken: process.env.DB_TOKEN,
}
“JWT_SECRET required” 错误
问题: 生产中身份验证失败
解决方法: 设置JWT_SECRET环境变量:
# Cloudflare
wrangler secret put JWT_SECRET
# Vercel
vercel env add JWT_SECRET
# Docker
docker run -e JWT_SECRET="your-secret" ...
冷启动超时(Lambda)
问题: 首次请求超时
解决方法:
- 使用轻量数据库(Turso优于RDS)
- 减少捆绑包大小
- 为关键函数启用预置并发
D1绑定未找到
问题: env.DB 未定义
解决方法: 检查wrangler.toml中的D1绑定:
[[d1_databases]]
binding = "DB" # 必须与代码中的 env.DB 匹配
database_name = "my-database"
database_id = "actual-id-from-wrangler-d1-create"
媒体上传在无服务器中失败
问题: 本地存储无法在无服务器中工作
解决方法: 使用云存储适配器:
config: {
media: {
adapter: {
type: "s3", // 或 "r2", "cloudinary"
config: { /* 凭据 */ },
},
},
}
CORS错误
问题: 前端无法访问API
解决方法: 在适配器中配置CORS:
// 大多数适配器自动处理此问题
// 对于自定义需求,请查看平台文档
部署命令参考
# Cloudflare Workers
wrangler deploy
wrangler tail # 查看日志
# Vercel
vercel deploy --prod
vercel logs
# Docker
docker compose up -d
docker compose logs -f
# AWS Lambda
serverless deploy --stage prod
serverless logs -f api
注意事项
建议:
- 在生产配置中设置
isProduction: true - 使用云存储(S3/R2/Cloudinary)处理媒体
- 设置强JWT_SECRET(至少32个字符)
- 启用Guard进行授权
- 部署前用生产数据库测试
- 对所有密钥使用环境变量
不建议:
- 在无服务器中使用基于文件的SQLite
- 在代码中硬编码密钥
- 未测试架构同步就部署
- 在生产中使用本地存储适配器
- 跳过JWT_SECRET配置
- 提交包含真实密钥的
.env文件
相关技能
- bknd-database-provision - 设置生产数据库
- bknd-production-config - 生产安全设置
- bknd-storage-config - 配置媒体存储
- bknd-env-config - 环境变量设置
- bknd-local-setup - 本地开发(部署前测试)