|
|
||
|---|---|---|
| .. | ||
| README.md | ||
| changelog.md | ||
README.md
部署指南(Docker Compose)
本地开发请用
./scripts/start.sh,不要用本文流程。 本文所有命令都在仓库根目录执行;部署脚本已迁到scripts/,写法固定为./scripts/deploy.sh …。
1. 运行拓扑
docker-compose.yml 定义 4 个服务,容器名前缀 nex-docus-,基础镜像走华为云 SWR 镜像站(国内直连可用):
| 服务 | 容器 | 端口(宿主机→容器) | 说明 |
|---|---|---|---|
mysql |
nex-docus-mysql |
${MYSQL_PORT:-3306} → 3306 |
MySQL 8.0,utf8mb4 / utf8mb4_unicode_ci,数据在 ${STORAGE_PATH}/mysql |
redis |
nex-docus-redis |
${REDIS_PORT:-6379} → 6379 |
Redis 7,requirepass + AOF,数据在 ${STORAGE_PATH}/redis |
backend |
nex-docus-backend |
${BACKEND_PORT:-8000} → 8000 |
由 backend/Dockerfile 构建;启动命令 python scripts/init_db.py && uvicorn main:app …,即建表/迁移/种子全自动 |
frontend |
nex-docus-frontend |
${FRONTEND_PORT:-8080} → 80 |
由 frontend/Dockerfile 构建(node 构建 + nginx 托管),nginx 反代 /api/、/mcp 到后端 |
- 网络:
nex-docus-network;后端在容器内的上游主机名是backend,前端 nginx 依赖该名字。 - 文件存储:宿主机
${STORAGE_PATH}挂到后端/data/nex_docus_store(后端配置里的STORAGE_ROOT)。文档正文、向量索引、搜索索引、PDF 缓存都在这里。 - ⚠️ compose 里的相对路径按执行 compose 的当前目录解析,建议
.env中把STORAGE_PATH写成绝对路径(如/data/nexdocus/storage),避免换目录执行时数据"凭空消失"。
2. 前置要求
- Docker 20.10+,Docker Compose v2(
docker compose;脚本也兼容老docker-compose) - 磁盘 ≥ 15 GB 空闲(后端镜像要装 PyTorch / weasyprint / zvec,镜像本身 + 向量索引 + 文档存储增长都吃磁盘)
- 内存 ≥ 4 GB(若启用本地 Embedding
sentence-transformers,建议 8 GB) - 出站网络可达所选 LLM / Embedding 服务
3. 配置 .env
cp .env.example .env
$EDITOR .env
| 键 | 默认值 | 说明 |
|---|---|---|
MYSQL_ROOT_PASSWORD |
root_password_change_me |
必改 |
DB_NAME / DB_USER / DB_PASSWORD |
nex_docus / nexdocus / password_change_me |
应用库与账号;必改密码 |
MYSQL_PORT |
3306 |
宿主机端口;不需要外部访问时建议改成 127.0.0.1:3306 或干脆不映射 |
REDIS_PASSWORD / REDIS_PORT / REDIS_DB |
redis_password_change_me / 6379 / 8 |
必改密码 |
SECRET_KEY |
占位串 | 必改:openssl rand -hex 32。改了会让已登录用户全部失效 |
DEBUG |
false |
保持 false(true 会打印全量 SQL) |
BACKEND_PORT / FRONTEND_PORT |
8000 / 8080 |
对外端口;用户访问的是 FRONTEND_PORT |
STORAGE_PATH |
./storage |
持久化根目录,建议绝对路径;MySQL/Redis 数据也放这里 |
CHUNK_SIZE / CHUNK_OVERLAP |
800 / 150 |
RAG 分块策略,改动后需重新向量化才生效 |
ADMIN_USERNAME / ADMIN_PASSWORD / ADMIN_EMAIL / ADMIN_NICKNAME |
admin / Admin@123456 / admin@example.com / 系统管理员 |
只在第一次建库时生效,账号已存在则不会改密码 |
DEFAULT_USER_PASSWORD |
User@123456 |
管理员在「系统管理 → 用户管理」新建用户时的初始密码;建议改随机值,否则后端启动会打 [安全自检] 告警 |
DISABLE_SSL_VERIFY |
false |
仅自签名证书的内部模型服务才开 |
ZVEC_DATA_DIR |
空 | 留空即 ${STORAGE_ROOT}/vector_index |
ZVEC_EMBEDDING_DIM |
1536 |
必须与选定的 embedding 模型维度一致,换模型要重建索引 |
前端没有 API 地址配置项:容器内 nginx 固定把
/api/反代到backend:8000。跨域直连后端需自行改frontend/nginx.conf。 这套.env(部署用)与backend/.env(开发用,键名不同)是两套配置,容器里只认前者。
4. 首次部署
./scripts/deploy.sh init
依次执行:.env 检查(没有就从 .env.example 生成并中止,等你填)→ Docker 检查 → pull → build --no-cache → 起 mysql/redis → 等 15s → run --rm backend python scripts/init_db.py → up -d → 打印访问信息。
等价的手工流程:
docker compose pull
docker compose build
docker compose up -d mysql redis
until docker compose exec -T mysql mysqladmin ping -hlocalhost -uroot -p"$MYSQL_ROOT_PASSWORD" --silent; do sleep 2; done
docker compose run --rm backend python scripts/init_db.py
docker compose up -d
docker compose ps
验证:
curl -fsS http://127.0.0.1:8000/health # {"status":"healthy"}
docker compose ps # 4 个服务 healthy/running
open http://<服务器IP>:8080 # 登录页;默认 admin / .env 里的 ADMIN_PASSWORD
5. 日常运维
| 命令 | 作用 |
|---|---|
./scripts/deploy.sh start / stop / restart |
起停服务 |
./scripts/deploy.sh status |
容器状态 |
./scripts/deploy.sh logs |
跟踪全部日志 |
./scripts/deploy.sh logs backend |
跟踪单个服务(mysql / redis / backend / frontend) |
./scripts/deploy.sh upgrade |
升级:交互确认 → git pull → 停前后端 → build --no-cache → 跑 init_db.py(自动补列/种子) → up -d → docker image prune -f |
./scripts/deploy.sh backup |
mysqldump 应用库到 ./backups/nex_docus_<时间戳>.sql |
./scripts/deploy.sh restore <文件> |
覆盖式恢复数据库(需输入 yes) |
./scripts/deploy.sh uninstall |
删除容器/网络/本地构建镜像;不会删除 STORAGE_PATH 数据 |
upgrade会执行git pull:如果服务器上有本地改动或未切换分支,请先自行处理。
6. 备份与恢复
文档正文在文件系统、权限在数据库,两者必须一起备份,单独还原任何一侧都不算恢复。
# 备份
./scripts/deploy.sh backup # 数据库
tar czf nexdocus_storage_$(date +%F).tar.gz -C "$STORAGE_PATH" . # 文件 + 索引 + MySQL/Redis 数据
# 恢复(先起 mysql/redis,再灌数据,最后起应用)
docker compose up -d mysql redis
./scripts/deploy.sh restore backups/nex_docus_20260930_120000.sql
docker compose up -d backend frontend
迁移到新机器:拷贝 storage 目录 + SQL 备份 + .env,新机 STORAGE_PATH 指到新目录,恢复 SQL 后直接 up -d。项目的磁盘目录名是 projects.storage_key(UUID),与项目名解耦,可以整目录搬迁。
定期备份建议交给系统 cron 或备份软件,注意 backups/ 也在 .gitignore 内,别提交到仓库。
7. 反向代理与 HTTPS
前端容器只监听 80。生产建议前置一层网关做 TLS 与域名:
server {
listen 443 ssl http2;
server_name docs.example.com;
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/privkey.pem;
client_max_body_size 100M; # 附件上传
location / {
proxy_pass http://127.0.0.1:8080;
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_http_version 1.1;
proxy_set_header Upgrade $http_kind;
proxy_set_header Connection "upgrade";
}
}
要点:
- 前端容器内的 nginx 已对
/api/v1/chat/send/stream(SSE)与/mcp关闭缓冲并放大超时;外层网关若另有 location 命中这两条路径,也要关闭proxy_buffering,否则 AI 对话会"卡住不出字"。 map $http_upgrade $http_kind { default upgrade; '' close; }放在http {}中(示例已简化)。- 上传大小限制要逐层一致(示例 100M)。
8. 上线前安全清单
MYSQL_ROOT_PASSWORD/DB_PASSWORD/REDIS_PASSWORD/SECRET_KEY全部改掉默认值ADMIN_PASSWORD/DEFAULT_USER_PASSWORD改为随机值;启动后docker compose logs backend | grep 安全自检应无输出(有输出说明仍在用仓库默认值)- 首次登录后修改
admin密码;删除或禁用演示账号 - MySQL / Redis 端口不对公网开放(安全组或改绑
127.0.0.1) DEBUG=false- TLS 前置,HTTP 跳转 HTTPS
STORAGE_PATH与数据库备份纳入例行备份(数据库里含 Git Token、模型 API Key、分享密码明文)- 磁盘监控:Redis 落盘失败会让整站变只读(见下)
9. 常见问题
| 现象 | 原因 / 处理 |
|---|---|
| 前端 502 / 一直转圈 | 后端还没通过 /health(首次 init_db.py 需要时间)。./scripts/deploy.sh logs backend 观察 |
backend 反复重启,日志 MISCONF ... RDB snapshot |
Redis 服务端落盘失败并拒绝写入 → 磁盘满或目录权限问题。清磁盘后 redis-cli CONFIG SET stop-writes-on-bgsave-error no 只是临时解封,重启 Redis 会复原,必须根治磁盘 |
Access denied for user |
.env 与实际库账号不一致;改过 DB_PASSWORD 后已初始化的 MySQL 不会自动同步,需要进容器 ALTER USER 或删库重建 |
| 换机器后项目列表空了 | STORAGE_PATH 用了相对路径,数据实际写在别的目录 |
改了 ADMIN_PASSWORD 但登录仍是旧密码 |
管理员已存在,init_db.py 不会重置密码;在「系统管理 → 用户管理」里改 |
| AI 对话无引用 / 报维度不匹配 | Embedding 模型或 ZVEC_EMBEDDING_DIM 变过 → 重新向量化项目(项目页触发全量) |
| PDF 导出中文乱码 | 后端镜像已内置 fonts-wqy-microhei;若自定义基础镜像请自带中文字体 |
docker compose 提示 version 已废弃 |
已从 docker-compose.yml 移除该字段;若用老 docker-compose v1,建议升级到 Compose v2 |
10. 本版验证边界
- ✅ 已验证:
./scripts/deploy.sh的参数路由与脚本语法、Compose 文件解析、后端镜像构建步骤文本与启动命令。 - ❌ 未在本轮做端到端
docker compose up实测(缺少可用 Docker 环境)。首个正式部署请把它当作演练:init → status → /health → 登录 → 建项目 → 上传 → AI 问答 → 备份,并把结果登记到 sdd/releases/v1.0.0.md 的验证边界。 - ⚠️
frontend/Dockerfile目前rm -rf package-lock.json && npm install(历史原因是 Alpine 下 rollup 可选依赖问题),构建不保证可重现;确认网络环境稳定后建议改回npm ci。