Compose 生产部署
四服务的 Compose 部署——Postgres、对象存储、一次性迁移任务和应用——外加 TLS、外部数据库,以及那个会让附件上传全挂的凭据陷阱。
一体机镜像把所有东西塞进同一个容器的生命周期。试用时这个取舍是对的,生产时是错的:你没法只重启应用而不重启数据库,也没法分别扩容、备份、升级各个部件。
Compose 部署把它拆成四个:
| 服务 | 是什么 | 说明 |
|---|---|---|
postgres | Postgres 16 | 独立命名卷 |
seaweedfs | 存附件的对象存储 | Apache-2.0 协议,S3 兼容 |
migrate | 一次性迁移任务 | 跑完即退出 |
app | Busabase 本体 | 等上面三个都就绪 |
为什么迁移要单独做成一个服务
migrate 跑一次就退出,app 对它声明了 condition: service_completed_successfully。一旦你跑多个 app 副本,这件事就至关重要:如果每个副本启动时各跑各的迁移,它们会互相竞争,而失败的那个报出来的样子像「schema 损坏」,不像「锁冲突」。
部署步骤
git clone https://github.com/busabase/busabase-premium.git
cd busabase-premium/compose
./init.sh
BUSABASE_IMAGE=busabase/busabase-premium:latest docker compose up -d请跑 init.sh,不要手工改 .env。S3 凭据出现在两个地方——应用侧的 .env 和存储侧的 seaweed-s3.json——而且必须一致。手工填两遍漏改一处,是这里最常见的自伤,而且症状极具误导性:应用启动完全正常、登录完全正常,然后每一次附件上传都失败。
init.sh 拒绝覆盖已存在的 .env。这是故意的——对着一个已经有数据的数据库重新生成凭据,等于把自己锁在外面。
TLS 与反向代理
Compose 文件里没有任何东西负责终结 TLS。请在应用端口前面放你自己的代理,并把 APP_URL 设成用户实际输入的地址:
server {
listen 443 ssl;
server_name busabase.company.internal;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Busabase 会流式输出 agent 内容,并用 websocket 做实时更新。
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
client_max_body_size 100m;
}proxy_buffering off 和那两行 Upgrade 头不是可选项。开着缓冲的话,agent 的回复会在整轮结束后一次性吐出来,而不是流式出现,用户看到的就是「agent 卡住了」。client_max_body_size 必须不小于你最大的附件,否则上传会在代理层就被拒,Busabase 根本收不到。
APP_URL 必须和公网地址逐字一致,协议和端口都算。登录会话的 cookie 是按它签发的,所以对不上的表现是:登录看起来成功了,然后立刻弹回登录页。
用你自己的 Postgres 或 S3
Compose 里这两个服务是为了省事,不是必需的。要接你已经在运维的基础设施,把应用指过去并移除对应的本地服务:
PG_DATABASE_URL=postgresql://user:password@your-host:5432/busabase
STORAGE_URL=minio://ACCESS_KEY:SECRET_KEY@your-s3-host:9000/bucket?auto_create=true&ssl=false存储用一条 URL 配置,不是一组分散的变量。minio:// 是我们内部的协议标记,含义是「S3、path-style 寻址、不走 TLS」——它描述的是协议而不是厂商,对 SeaweedFS、MinIO 以及任何 S3 兼容存储都适用。TLS 端点请用 ssl=true 并去掉端口。
这么改的话,记得把 depends_on 里的 postgres / seaweedfs 也去掉,否则 Compose 会一直等一个它已经不再启动的服务。migrate 要保留——不管你选了哪个数据库,迁移都还是要跑。
如果你的 S3 挡在一个会改写或剥离请求头的代理后面,见故障排查里关于 checksum 的那条。