容器方式部署(Docker Compose)
推荐部署方式。一份 Compose 配置同时拉起 PostgreSQL 与雷驼企业私有服务(API + /admin + 语音识别引擎)。
前置:先完成部署总览第 2–3 节的前置条件与部署前规划。
1. 准备部署目录
docker --version # 需要 Docker Engine 24+docker compose version # 需要 Compose v2
mkdir -p /opt/dathor && cd /opt/dathor获取交付的服务镜像(二选一):
# 方式一:从镜像仓库在线拉取(需要主机可访问该仓库;私有仓库先 docker login)docker login <镜像仓库地址> # 公开仓库可跳过docker pull <镜像仓库地址>/dathor-server:<版本>
# 方式二:离线导入交付的镜像包(内网无法访问镜像仓库时)docker load -i dathor-server-<版本>.tardocker image ls | grep dathor-server # 记录完整镜像标签,填入 .env 的 DATHOR_SERVER_IMAGE建议使用明确的版本号标签,不要用
latest:版本可追溯,且重建容器时不会意外拉到新版本。 客户如有内部镜像仓库,可将镜像转推一份到内部仓库,后续部署与升级都从内部仓库拉取。
2. 创建 docker-compose.yml
在 /opt/dathor 下创建下面的文件,无需修改(全部可变项通过 .env 注入):
services: postgres: image: postgres:16-alpine restart: unless-stopped security_opt: [no-new-privileges:true] environment: POSTGRES_USER: dathor POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env} POSTGRES_DB: dathor POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256 volumes: - dathor-pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U dathor -d dathor"] interval: 10s timeout: 5s retries: 5 networks: [backend]
server: image: ${DATHOR_SERVER_IMAGE:?set the delivered image tag in .env} restart: unless-stopped init: true read_only: true cap_drop: [ALL] security_opt: [no-new-privileges:true] tmpfs: - /tmp:rw,noexec,nosuid,nodev,size=128m depends_on: postgres: condition: service_healthy ports: - "127.0.0.1:${DATHOR_HTTP_PORT:-3000}:3000" environment: NODE_ENV: production HOST: 0.0.0.0 PORT: "3000" BASE_URL: ${BASE_URL:?set the public HTTPS origin in .env} ADMIN_ALLOWED_ORIGINS: ${ADMIN_ALLOWED_ORIGINS:-} DATABASE_URL: postgres://dathor:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}@postgres:5432/dathor JWT_SECRET: ${JWT_SECRET:?generate with openssl rand -hex 32} VAULT_MASTER_KEY: ${VAULT_MASTER_KEY:?generate with openssl rand -hex 32} AI_PROVIDER_SECRET_KEY: ${AI_PROVIDER_SECRET_KEY:?generate with openssl rand -hex 32} STT_SECRET_KEY: ${STT_SECRET_KEY:?generate with openssl rand -hex 32} ARTIFACT_SIGNING_KEY: ${ARTIFACT_SIGNING_KEY:?generate with openssl rand -hex 32} ADMIN_INITIAL_USERNAME: ${ADMIN_INITIAL_USERNAME:-admin} ADMIN_INITIAL_PASSWORD: ${ADMIN_INITIAL_PASSWORD:?set a 12-128 character first-boot password in .env} volumes: - dathor-data:/app/data networks: [edge, backend]
volumes: dathor-pgdata: dathor-data:
networks: edge: backend: internal: true这份配置已按最小权限设计:
- 服务容器以非 root 运行,根文件系统只读,仅
/tmp(tmpfs)与数据卷可写; - 丢弃全部 Linux capabilities,禁止提权;
- 服务端口只绑定宿主机
127.0.0.1,必须经反向代理对外; - PostgreSQL 位于
internal网络,不暴露任何宿主机端口; - 任一必填变量缺失时,Compose 以明确错误退出,不会带着不安全默认值启动。
3. 创建 .env
与 docker-compose.yml 同目录创建 .env:
cat > /opt/dathor/.env <<'EOF'# 交付镜像标签:在线拉取时写 <镜像仓库地址>/dathor-server:<版本>,离线导入时写本地镜像标签DATHOR_SERVER_IMAGE=dathor-server:<版本>
# 对外 HTTPS origin,必须与桌面端填写的地址完全一致BASE_URL=https://dathor.example.com
# 反向代理访问的宿主机回环端口DATHOR_HTTP_PORT=3000
# 额外允许访问维护后台的精确 HTTPS origin,逗号分隔;通常留空ADMIN_ALLOWED_ORIGINS=
# 数据库密码POSTGRES_PASSWORD=
# 5 个互不相同的随机密钥,用 openssl rand -hex 32 分别生成JWT_SECRET=VAULT_MASTER_KEY=AI_PROVIDER_SECRET_KEY=STT_SECRET_KEY=ARTIFACT_SIGNING_KEY=
# 初始管理员,仅用户表为空时生效ADMIN_INITIAL_USERNAME=adminADMIN_INITIAL_PASSWORD=EOF
chmod 600 /opt/dathor/.env.env 含全部生产密钥,请限制文件权限并纳入客户的密钥管理流程。密钥含义与生成方式见部署总览第 3.2 节,完整变量清单见部署总览附录 A。
4. 启动
cd /opt/dathordocker compose up -ddocker compose psdocker compose logs -f server首次启动会自动执行数据库迁移并创建初始管理员账号,日志出现监听端口信息即表示启动完成。
验证:
curl -fsS http://127.0.0.1:3000/health/livecurl -fsS http://127.0.0.1:3000/health/ready # 200 表示数据库已连通、可对外提供服务5. TLS 反向代理
服务进程不做 TLS。以 Nginx 为例:
server { listen 443 ssl http2; server_name dathor.example.com; # 必须与 BASE_URL 域名一致
ssl_certificate /etc/ssl/certs/dathor.crt; ssl_certificate_key /etc/ssl/private/dathor.key;
client_max_body_size 64m; # 附件上限 50 MiB,留出余量
location / { proxy_pass http://127.0.0.1:3000; # 与 DATHOR_HTTP_PORT 一致 proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 300s; # AI 流式响应与长语音转写耗时较长 }}
server { listen 80; server_name dathor.example.com; return 301 https://$host$request_uri;}proxy_read_timeout 不宜过小,否则 AI 流式回答与长语音转写会被中断。
6. 使用客户已有的 PostgreSQL
若客户要求使用现有数据库集群,在同目录追加 docker-compose.override.yml:
services: postgres: profiles: ["disabled"] # 不启动随附数据库 server: depends_on: [] environment: DATABASE_URL: postgres://dathor:<密码>@db.example.com:5432/dathor networks: - edge要求:PostgreSQL 16 及以上;数据库与账号预先创建,账号具备建表与结构迁移权限。
CREATE USER dathor WITH PASSWORD '<强密码>';CREATE DATABASE dathor OWNER dathor;7. 语音模型文件(可选)
启用服务端语音识别时,把模型文件放入数据卷:
docker compose cp ./sense-voice-small-v1 server:/app/data/stt-models/sense-voice-small-v1docker compose exec server ls /app/data/stt-modelsdocker compose restart server目录内需包含 sense-voice.onnx 与 tokens.txt,目录名与 STT_MODEL_VERSION(默认 sense-voice-small-v1)一致。缺少模型文件时其他功能不受影响。
8. 升级
cd /opt/dathor
# 1. 先备份(第 9 节)
# 2. 获取新版本镜像(二选一),并把 .env 中的 DATHOR_SERVER_IMAGE 改为新标签docker pull <镜像仓库地址>/dathor-server:<新版本># 或:docker load -i dathor-server-<新版本>.tar
# 3. 重建服务容器docker compose up -d
# 4. 验证docker compose logs -f servercurl -fsS http://127.0.0.1:3000/health/ready数据库迁移在启动时自动执行且不可回退,务必先备份。数据保存在 dathor-pgdata 与 dathor-data 卷中,重建容器不会丢失。保留上一版本镜像可在必要时快速回退程序(数据结构不回退)。
9. 备份与恢复
# 数据库docker compose exec -T postgres pg_dump -U dathor dathor > dathor-$(date +%F).sql
# 数据目录(头像、附件、语音模型)docker run --rm -v dathor-data:/data -v "$PWD":/backup alpine \ tar czf /backup/dathor-data-$(date +%F).tar.gz -C /data .恢复:
docker compose up -d postgresdocker compose exec -T postgres psql -U dathor -d dathor < dathor-<日期>.sqldocker run --rm -v dathor-data:/data -v "$PWD":/backup alpine \ tar xzf /backup/dathor-data-<日期>.tar.gz -C /datadocker compose up -d务必确认 .env 中的 5 个密钥与备份数据来自同一套部署,否则 Vault、AI 供应商与语音识别凭据密文无法解密。
10. 日常运维
docker compose ps # 查看状态docker compose logs -f --tail=200 server # 跟踪服务日志docker compose restart server # 重启服务docker compose down # 停止,保留数据卷docker compose down -v # 停止并删除数据卷(清空全部数据,慎用)完成部署后回到部署总览第 5 节执行首次配置与授权证书上传。