Dokploy 部署
用持久化 City 数据库把 Downcity Node 街区部署到 Dokploy。
Node 街区是 Downcity City Infra 的标准 Docker / Dokploy 部署形态。
它运行 cities/node,暴露 City HTTP API,并把 SQLite 数据保存在持久化 /data volume 里。适合给产品、应用、Agent 或内部工具提供一套长期运行的城市服务层。
Dokploy 配置
在 Dokploy 里创建应用,选择当前 Git 仓库:
| 配置项 | 值 |
|---|---|
| 部署模式 | Compose |
| Compose 文件 | ./docker-compose.yml |
| Container port | 43127 |
| Volume | Compose 自动创建 downcity_infra_data |
Dokploy 里必须配置这两个稳定的 bootstrap secret:
DOWNCITY_CITY_ADMIN_SECRET_KEY=admin_xxx
DOWNCITY_CITY_TOKEN_SIGNING_KEY=sign_xxxHOST、PORT 和 DOWNCITY_CITY_DATABASE_URL 已经写在 docker-compose.yml 中:
HOST=0.0.0.0
PORT=43127
DOWNCITY_CITY_DATABASE_URL=file:/data/downcity.sqlite/data 必须是持久化 volume。town、model、用户、session、usage、payment 和 City env 都会保存在这个 SQLite 数据库里。
域名路径
Node 街区默认监听 43127,City API 直接挂在服务根路径下:
GET /health
POST /v1/env/upsert
GET /v1/services
POST /v1/ai/text如果你的域名是 https://base.example.com,产品侧 SDK 和可信后端应该使用:
base_url=https://base.example.com如果 Stripe redirect URL 没有直接配置,可以把 DOWNCITY_CITY_BASE_URL 写入 City env,让支付页自动推导默认 success / cancel URL:
curl -X POST https://base.example.com/v1/env/upsert \
-H 'content-type: application/json' \
-H 'authorization: Bearer admin_xxx' \
-d '{"key":"DOWNCITY_CITY_BASE_URL","value":"https://base.example.com"}'Provider Key
Provider API key 不建议写在 Dokploy env 里。部署完成后,通过 Admin API 写入 City 数据库:
curl -X POST https://base.example.com/v1/env/upsert \
-H 'content-type: application/json' \
-H 'authorization: Bearer admin_xxx' \
-d '{"key":"MOONSHOT_API_KEY","value":"your_api_key"}'
curl -X POST https://base.example.com/v1/env/upsert \
-H 'content-type: application/json' \
-H 'authorization: Bearer admin_xxx' \
-d '{"key":"DEEPSEEK_API_KEY","value":"your_api_key"}'运行时 ctx.env.MOONSHOT_API_KEY 和 ctx.env.DEEPSEEK_API_KEY 会优先从 City 数据库读取。
验证
Dokploy 部署完成后,先验证公开服务:
curl https://base.example.com/health只用 IP 和端口时:
curl http://1.2.3.4:43127/health预期返回大致如下:
{
"ok": true,
"services": ["env", "towns", "accounts", "balance", "payment", "usage", "payment.stripe", "ai"]
}如果这里超时,说明 Dokploy 服务没有对外暴露、VPS 防火墙没放行 43127,或还没有绑定可访问的域名。
产品侧调用
产品前端和应用应该通过 @downcity/city 调用 Node 街区:
import { City } from "@downcity/city";
const client = new City({
role: "user",
city_url: "https://base.example.com",
town_id: "my-town",
user_token: "user_token",
});可信后端应该用 Admin City 携带 DOWNCITY_CITY_ADMIN_SECRET_KEY:
import { City } from "@downcity/city";
const admin = new City({
role: "admin",
city_url: "https://base.example.com",
admin_secret_key: process.env.DOWNCITY_CITY_ADMIN_SECRET_KEY,
});完整 SDK 能力继续看 User City 和 Admin City。