bknd-deploy-hosting
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDeploy to Hosting
部署至托管平台
Deploy your Bknd application to various hosting platforms.
将你的Bknd应用部署至各类托管平台。
Prerequisites
前置条件
- Working Bknd application locally
- Schema defined and tested
- Database provisioned (see )
bknd-database-provision - Environment variables prepared (see )
bknd-env-config
- 本地可正常运行的Bknd应用
- 已定义并测试完成的Schema
- 已配置数据库(参考)
bknd-database-provision - 已准备好环境变量(参考)
bknd-env-config
When to Use UI Mode
何时使用UI模式
- Cloudflare/Vercel dashboards for environment variables
- Platform-specific deployment settings
- Viewing deployment logs
- 通过Cloudflare/Vercel控制台配置环境变量
- 设置平台专属的部署参数
- 查看部署日志
When to Use Code Mode
何时使用代码模式
- All deployment configuration and commands
- Adapter setup for target platform
- CI/CD pipeline configuration
- 所有部署配置与命令
- 目标平台的适配器设置
- CI/CD流水线配置
Platform Selection Guide
平台选择指南
| Platform | Best For | Database Options | Cold Start |
|---|---|---|---|
| Cloudflare Workers | Edge, global low-latency | D1, Turso | ~0ms |
| Cloudflare Pages | Static + API | D1, Turso | ~0ms |
| Vercel | Next.js apps | Turso, Neon | ~200ms |
| Node.js/Bun VPS | Full control, dedicated | Any | N/A |
| Docker | Containerized, portable | Any | N/A |
| AWS Lambda | Serverless, pay-per-use | Turso, RDS | ~500ms |
| 平台 | 适用场景 | 数据库选项 | 冷启动 |
|---|---|---|---|
| Cloudflare Workers | 边缘计算、全球低延迟 | D1, Turso | ~0ms |
| Cloudflare Pages | 静态站点+API | D1, Turso | ~0ms |
| Vercel | Next.js应用 | Turso, Neon | ~200ms |
| Node.js/Bun VPS | 完全控制、专属服务器 | 任意 | N/A |
| Docker | 容器化、可移植 | 任意 | N/A |
| AWS Lambda | 无服务器、按使用付费 | Turso, RDS | ~500ms |
Code Approach
代码部署方式
Cloudflare Workers
Cloudflare Workers
Step 1: Install Wrangler
bash
npm install -D wranglerStep 2: Create
wrangler.tomltoml
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"步骤1:安装Wrangler
bash
npm install -D wrangler步骤2:创建
wrangler.tomltoml
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"Optional: R2 for media storage
Optional: R2 for media storage
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "my-bucket"
[vars]
ENVIRONMENT = "production"
**Step 3: Configure Adapter**
```typescript
// 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 },
},
},
},
}),
});Step 4: Create D1 Database
bash
undefined[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "my-bucket"
[vars]
ENVIRONMENT = "production"
**步骤3:配置适配器**
```typescript
// 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数据库
bash
undefinedCreate database
Create database
wrangler d1 create my-database
wrangler d1 create my-database
Copy the database_id to wrangler.toml
Copy the database_id to wrangler.toml
**Step 5: Set Secrets**
```bash
wrangler secret put JWT_SECRET
**步骤5:设置密钥**
```bash
wrangler secret put JWT_SECRETEnter your secret (min 32 chars)
Enter your secret (min 32 chars)
**Step 6: Deploy**
```bash
wrangler deploy
**步骤6:部署**
```bash
wrangler deployCloudflare Pages (with Functions)
Cloudflare Pages(搭配Functions)
Step 1: Create
functions/api/[[bknd]].tstypescript
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 },
},
}),
});Step 2: Configure Pages
In Cloudflare dashboard:
- Connect your git repository
- Set build command (if any)
- Add D1 binding under Settings > Functions > D1 Database Bindings
- Add environment variables under Settings > Environment Variables
步骤1:创建
functions/api/[[bknd]].tstypescript
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)
Node.js / Bun(VPS)
Step 1: Create Production Entry
typescript
// index.ts
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
// or for 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);Step 2: Set Environment Variables
bash
export DB_URL="libsql://your-db.turso.io"
export DB_TOKEN="your-turso-token"
export JWT_SECRET="your-32-char-minimum-secret"
export PORT=3000Step 3: Run with Process Manager
bash
undefined步骤1:创建生产环境入口文件
typescript
// 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:设置环境变量
bash
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:使用进程管理器运行
bash
undefinedUsing PM2
使用PM2
npm install -g pm2
pm2 start "bun run index.ts" --name bknd-app
npm install -g pm2
pm2 start "bun run index.ts" --name bknd-app
Or systemd (create /etc/systemd/system/bknd.service)
或使用systemd(创建/etc/systemd/system/bknd.service)
---
---Docker
Docker
Step 1: Create
Dockerfiledockerfile
FROM oven/bun:1.0-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .步骤1:创建
Dockerfiledockerfile
FROM oven/bun:1.0-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .Create data directory for SQLite (if using file-based)
为SQLite创建数据目录(若使用文件型数据库)
RUN mkdir -p /app/data
ENV PORT=3000
EXPOSE 3000
CMD ["bun", "run", "index.ts"]
**Step 2: Create `docker-compose.yml`**
```yaml
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:Step 3: Deploy
bash
undefinedRUN mkdir -p /app/data
ENV PORT=3000
EXPOSE 3000
CMD ["bun", "run", "index.ts"]
**步骤2:创建`docker-compose.yml`**
```yaml
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:部署
bash
undefinedBuild and run
构建并运行
docker compose up -d
docker compose up -d
View logs
查看日志
docker compose logs -f bknd
---docker compose logs -f bknd
---Vercel (Next.js)
Vercel(Next.js)
Step 1: Create API Route
typescript
// app/api/bknd/[[...bknd]]/route.ts
export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";Step 2: Create
bknd.config.tstypescript
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;Step 3: Set Vercel Environment Variables
In Vercel dashboard or CLI:
bash
vercel env add DB_URL
vercel env add DB_TOKEN
vercel env add JWT_SECRETStep 4: Deploy
bash
vercel deploy --prod步骤1:创建API路由
typescript
// app/api/bknd/[[...bknd]]/route.ts
export { GET, POST, PUT, DELETE, PATCH } from "bknd/adapter/nextjs";步骤2:创建
bknd.config.tstypescript
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中执行:
bash
vercel env add DB_URL
vercel env add DB_TOKEN
vercel env add JWT_SECRET步骤4:部署
bash
vercel deploy --prodAWS Lambda
AWS Lambda
Step 1: Install Dependencies
bash
npm install -D serverless serverless-esbuildStep 2: Create
handler.tstypescript
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! },
},
});Step 3: Create
serverless.ymlyaml
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: ANYStep 4: Deploy
bash
serverless deploy --stage prod步骤1:安装依赖
bash
npm install -D serverless serverless-esbuild步骤2:创建
handler.tstypescript
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.ymlyaml
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:部署
bash
serverless deploy --stage prodPre-Deployment Checklist
部署前检查清单
bash
undefinedbash
undefined1. Generate types
1. 生成类型定义
npx bknd types
npx bknd types
2. Test locally with production-like config
2. 使用类生产配置在本地测试
DB_URL="your-prod-db" JWT_SECRET="your-secret" npx bknd run
DB_URL="your-prod-db" JWT_SECRET="your-secret" npx bknd run
3. Verify schema sync
3. 验证Schema同步
Schema auto-syncs on first request in production
生产环境中首次请求时会自动同步Schema
undefinedundefinedEnvironment Variables (All Platforms)
全平台通用环境变量
| Variable | Required | Description |
|---|---|---|
| Yes | Database connection URL |
| Depends | Auth token (Turso/LibSQL) |
| Yes | Min 32 chars for security |
| No | Server port (default: 3000) |
| 变量名 | 是否必填 | 说明 |
|---|---|---|
| 是 | 数据库连接URL |
| 可选 | 认证令牌(Turso/LibSQL需提供) |
| 是 | 长度至少32字符,用于安全验证 |
| 否 | 服务器端口(默认:3000) |
Common Pitfalls
常见问题排查
"Module not found" for Native SQLite
「找不到Native SQLite模块」
Problem: not available in serverless
better-sqlite3Fix: Use LibSQL/Turso instead of file-based SQLite:
typescript
connection: {
url: "libsql://your-db.turso.io",
authToken: process.env.DB_TOKEN,
}问题: 在无服务器环境中不可用
better-sqlite3解决方案: 使用LibSQL/Turso替代文件型SQLite:
typescript
connection: {
url: "libsql://your-db.turso.io",
authToken: process.env.DB_TOKEN,
}"JWT_SECRET required" Error
「JWT_SECRET必填」错误
Problem: Auth fails in production
Fix: Set JWT_SECRET environment variable:
bash
undefined问题: 生产环境中认证失败
解决方案: 设置JWT_SECRET环境变量:
bash
undefinedCloudflare
Cloudflare
wrangler secret put JWT_SECRET
wrangler secret put JWT_SECRET
Vercel
Vercel
vercel env add JWT_SECRET
vercel env add JWT_SECRET
Docker
Docker
docker run -e JWT_SECRET="your-secret" ...
undefineddocker run -e JWT_SECRET="your-secret" ...
undefinedCold Start Timeouts (Lambda)
Lambda冷启动超时
Problem: First request times out
Fix:
- Use lighter database (Turso over RDS)
- Reduce bundle size
- Enable provisioned concurrency for critical functions
问题: 首次请求超时
解决方案:
- 使用轻量数据库(如Turso替代RDS)
- 减小包体积
- 为核心函数启用预置并发
D1 Binding Not Found
D1绑定未找到
Problem:
env.DB is undefinedFix: Check wrangler.toml D1 binding:
toml
[[d1_databases]]
binding = "DB" # Must match env.DB in code
database_name = "my-database"
database_id = "actual-id-from-wrangler-d1-create"问题:
env.DB is undefined解决方案: 检查wrangler.toml中的D1绑定配置:
toml
[[d1_databases]]
binding = "DB" # 必须与代码中的env.DB一致
database_name = "my-database"
database_id = "actual-id-from-wrangler-d1-create"Media Uploads Fail in Serverless
无服务器环境中媒体上传失败
Problem: Local storage doesn't work in serverless
Fix: Use cloud storage adapter:
typescript
config: {
media: {
adapter: {
type: "s3", // or "r2", "cloudinary"
config: { /* credentials */ },
},
},
}问题: 本地存储在无服务器环境中无法工作
解决方案: 使用云存储适配器:
typescript
config: {
media: {
adapter: {
type: "s3", // 或 "r2", "cloudinary"
config: { /* 凭据信息 */ },
},
},
}CORS Errors
CORS错误
Problem: Frontend can't access API
Fix: Configure CORS in your adapter:
typescript
// Most adapters handle this automatically
// For custom needs, check platform docs问题: 前端无法访问API
解决方案: 在适配器中配置CORS:
typescript
// 大多数适配器会自动处理此问题
// 如需自定义,请参考对应平台文档Deployment Commands Reference
部署命令参考
bash
undefinedbash
undefinedCloudflare Workers
Cloudflare Workers
wrangler deploy
wrangler tail # View logs
wrangler deploy
wrangler tail # 查看日志
Vercel
Vercel
vercel deploy --prod
vercel logs
vercel deploy --prod
vercel logs
Docker
Docker
docker compose up -d
docker compose logs -f
docker compose up -d
docker compose logs -f
AWS Lambda
AWS Lambda
serverless deploy --stage prod
serverless logs -f api
undefinedserverless deploy --stage prod
serverless logs -f api
undefinedDOs and DON'Ts
注意事项
DO:
- Set in production config
isProduction: true - Use cloud storage (S3/R2/Cloudinary) for media
- Set strong JWT_SECRET (min 32 chars)
- Enable Guard for authorization
- Test with production database before deploying
- Use environment variables for all secrets
DON'T:
- Use file-based SQLite in serverless
- Hardcode secrets in code
- Deploy without testing schema sync
- Use local storage adapter in production
- Skip JWT_SECRET configuration
- Commit files with real secrets
.env
建议:
- 在生产配置中设置
isProduction: true - 使用云存储(S3/R2/Cloudinary)存储媒体文件
- 设置强JWT_SECRET(至少32字符)
- 启用Guard进行授权管理
- 部署前使用生产数据库测试
- 所有密钥均通过环境变量配置
禁止:
- 在无服务器环境中使用文件型SQLite
- 在代码中硬编码密钥
- 未测试Schema同步就部署
- 在生产环境中使用本地存储适配器
- 跳过JWT_SECRET配置
- 提交包含真实密钥的文件
.env
Related Skills
相关技能
- bknd-database-provision - Set up production database
- bknd-production-config - Production security settings
- bknd-storage-config - Configure media storage
- bknd-env-config - Environment variable setup
- bknd-local-setup - Local development (pre-deploy testing)
- bknd-database-provision - 配置生产环境数据库
- bknd-production-config - 生产环境安全设置
- bknd-storage-config - 媒体存储配置
- bknd-env-config - 环境变量配置
- bknd-local-setup - 本地开发环境搭建(部署前测试用)