Skip to content

Docker 构建与部署 ​

参照 mono4j 的独立镜像方式:server 使用 Gunicorn,site 使用 Nginx,Celery worker 复用 server 镜像。Compose 配套 Redis,MySQL 使用外部服务。VitePress 继续独立运行,不打入业务镜像。

线上部署流程 ​

推荐使用同一域名提供页面和 API:宿主机 Nginx 负责 HTTPS,转发到 site 容器,再由 site 转发后端 API。以下示例域名为 ai.example.com,部署目录为 /opt/dp,需替换为实际值。

1. 准备服务器和部署文件 ​

服务器需要 Docker Engine、支持 up --wait 的 Docker Compose 插件、宿主机 MySQL,以及宿主机 Nginx 和对应域名的 HTTPS 证书。CI 生成 linux/amd64 镜像,服务器应使用 x86_64 架构。数据库需提前创建,域名解析到服务器地址。

从已经包含最新部署配置的仓库版本准备文件:

bash
git clone https://github.com/imvkmark/daniu-dp.mono4py.git /opt/dp
cd /opt/dp
cp deploy/.env.example deploy/.env
chmod 600 deploy/.env
openssl rand -hex 32

将生成的随机值填入 SECRET_KEY。镜像部署服务器不需要安装 Python、Node 或 pnpm;如仅分发部署文件,保留 compose.yml、deploy.sh、.env 即可,三者放在同一目录。

当前后端接口尚未实现服务端用户鉴权,对外开放前应在入口配置访问控制,或补齐后端鉴权。

2. 编辑唯一的线上配置文件 ​

线上配置默认放在 /opt/dp/deploy/.env,也可使用仓库根目录 /opt/dp/.env.local。部署脚本的选择顺序为:显式指定的 ENV_FILE → deploy/.env → 根目录 .env.local。只使用其中一份配置即可。

使用根目录 .env.local 时可以显式执行:

bash
ENV_FILE=.env.local sh deploy/deploy.sh all 1.0.1

ENV_FILE 支持绝对路径或相对于命令执行目录的路径;版本记录会写回所选文件。.env.local 已被 Git 和 Docker 构建上下文忽略,仅在容器运行时通过 Compose 注入。以下基础配置以 deploy/.env 为例:

dotenv
SECRET_KEY=替换为生成的随机值
DB_HOST=host.docker.internal
DB_NAME=web4py
DB_USER=应用数据库用户
# MySQL 账号无密码时写 DB_PASSWORD=
DB_PASSWORD=应用数据库密码

# 前后端的默认版本;单端部署可分别记录独立版本
IMAGE_TAG=1.0.1
# 宿主机 Nginx 通过此地址访问页面容器
SITE_BIND_HOST=127.0.0.1
SITE_PORT=4904

再按实际功能填写示例中的百炼、TOS、ARK 和语音凭证。当前页面的聊天默认使用语音双流,需要同时填写百炼和语音配置;知识库操作需要百炼知识库和 TOS 配置。完整分组及可选默认值见下方配置与启动。

配置映射关系:

配置位置使用者修改后如何生效
所选环境文件的数据库、百炼、TOS、语音配置server 和 worker,通过 env_file 注入重新执行部署脚本重建有变化的容器
所选环境文件的镜像版本(IMAGE_TAG/独立端版本)、IMAGE_PREFIX、SITE_BIND_HOST、SITE_PORTCompose 选择镜像和端口映射重新执行部署脚本
GitHub Actions 的 ACR_USERNAME、ACR_PASSWORDCI 登录 ACR 推送镜像下一次 CI 运行使用;服务器另行执行 docker login
GitHub Actions 的 VUE_APP_BASE_URL、SITE_BUILD_ENV前端镜像构建重新构建并发布 site 镜像,再部署新版本
packages/server/.env、packages/site/.env本地开发不作为 Docker 线上配置文件

同域名部署时前端保持默认 VUE_APP_BASE_URL=/api/,无需填写服务器 IP 或单独配置 API 域名,也不需要修改业务镜像内的配置文件。

宿主机 MySQL 的连接不是 Compose ports 映射:server、worker 通过 host.docker.internal 访问宿主机实际 MySQL 端口。Compose 已添加 host-gateway 映射。MySQL 需监听容器可访问的网卡地址,并为应用用户配置对应来源的数据库权限;只监听 127.0.0.1 的 Linux MySQL 不能从桥接容器访问。MySQL 非 3306 端口时添加 DB_PORT=实际端口,无需将数据库端口向公网开放。

3. 拉取镜像并启动 ​

确认对应版本的整个 CI 成功后,在仓库根目录执行:

bash
cd /opt/dp
docker login kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com
sh deploy/deploy.sh

脚本会校验配置、拉取 dp-server 和 dp-site、执行数据库迁移、启动 Redis/server/worker/site,并等待健康检查。迁移会修改宿主机数据库,升级已有系统前先完成数据库备份。

4. 配置域名 HTTPS 和端口映射 ​

请求路径:

text
浏览器 https://ai.example.com/szr/
  → 宿主机 Nginx :443
  → 宿主机 127.0.0.1:4904
  → site 容器 :80
      /api/* → server 容器 :4900
  server / worker → host.docker.internal:3306(宿主机 MySQL)
  server / worker → redis:6379(Compose Redis)
组件宿主机映射容器内地址/用途
HTTPS 入口宿主机 Nginx 的 80、44380 跳转 HTTPS,443 转发至 127.0.0.1:4904
site127.0.0.1:4904 → 80页面和 /api/ 的统一入口
server不映射宿主机端口server:4900,由 site 访问
worker不映射端口消费 Celery 任务
Redis不映射宿主机端口redis:6379,仅容器网络使用
MySQL已运行在宿主机上的服务host.docker.internal:3306,端口可通过 DB_PORT 修改

宿主机 Nginx 模板为 deploy/nginx.host.conf.example。替换模板中的域名、证书路径,确保上游端口与 SITE_PORT 一致,再安装配置:

bash
sudo cp deploy/nginx.host.conf.example /etc/nginx/conf.d/dp.conf
# 编辑 /etc/nginx/conf.d/dp.conf,替换 ai.example.com 和证书路径
sudo nginx -t
sudo nginx -s reload

模板会将完整请求路径转发给 site,/api/ 路径无需额外改写;页面可通过 https://ai.example.com/szr/ 访问。外层代理与容器内代理都需要关闭响应缓冲,避免聊天 SSE 一次性返回。模板已设置上传大小和流式读取超时;原理见 Nginx 代理缓冲说明。

此模板适用于 Nginx 运行在宿主机的情况。若入口 Nginx 也在容器内,应将其接入应用网络并转发到 site:80;该容器中的 127.0.0.1 指向自身。Docker 服务名、宿主机端口和容器端口的区别见 Compose 网络说明。

5. 验收服务与持久化 ​

下列手动 Compose 命令以 deploy/.env 为例。若使用根目录 .env.local,需要同时设置 ENV_FILE(容器运行配置)和 --env-file(Compose 插值配置),例如:

bash
ENV_FILE="$PWD/.env.local" docker compose --env-file .env.local -f deploy/compose.yml ps
bash
docker compose --env-file deploy/.env -f deploy/compose.yml ps
curl -f http://127.0.0.1:4904/healthz
curl -I https://ai.example.com/szr/
docker compose --env-file deploy/.env -f deploy/compose.yml exec server python manage.py shell -c 'from ops.health import check_database; check_database(); print("database ok")'
docker compose --env-file deploy/.env -f deploy/compose.yml exec worker python manage.py check_worker_health

ps 应显示四个服务就绪;HTTP /healthz 从 site 访问时只证明 Nginx 正常,数据库检查和 worker 检查需要分别通过。最后用真实页面验证聊天文字/语音、幼教和养老知识库,以及 PDF 后台任务。

数据持久化位置
业务记录、知识库同步状态宿主机 MySQL,由宿主机数据库策略备份
Celery 待处理任务redis-data 命名卷映射到 Redis 的 /data,启用 AOF
应用日志server-logs 命名卷映射到 server、worker 的 /app/storage/logs
上传文件、PDF 图片和语音配置的 TOS 桶
百炼知识库文件及索引配置的百炼业务空间和知识库

容器代码和前端静态文件来自镜像,无需挂载源码目录。Compose 项目名为 daniu-dp,生成 daniu-dp-server-1 等容器及 daniu-dp_default 网络。数据卷显式沿用原名称 mono4py_redis-data、mono4py_server-logs,避免项目改名后切换到空卷;可通过 REDIS_DATA_VOLUME、SERVER_LOGS_VOLUME 指定其他已有卷或新的卷名。

从旧 mono4py 项目首次切换时,先停止旧项目、保留数据卷,再启动新项目,避免端口冲突或两个 Redis 同时写同一个卷:

bash
# 在仓库根目录执行;-p 显式选择原项目名,不添加 -v
docker compose -p mono4py --env-file deploy/.env -f deploy/compose.yml down
sh deploy/deploy.sh all 1.0.1

迁移前确认原卷名称;如之前使用过自定义项目名,应将两个卷变量设置为实际名称。复用旧项目创建的卷时,Compose 可能提示该卷来自其他项目,需核对名称后确认复用。

6. 按端部署、更新与回退 ​

首次部署使用 all(不传参数也默认为 all)。后续直接通过脚本选择更新范围和镜像版本,以下版本号需替换为 CI 已发布的镜像标签:

bash
# 只更新前端,不执行数据库迁移,也不更新后端、worker 或 Redis
sh deploy/deploy.sh site 1.0.2

# 更新后端及 worker,执行迁移,完成后刷新运行中 site 的上游解析
sh deploy/deploy.sh server 1.0.2

# 全量部署,将前后端统一更新到同一版本
sh deploy/deploy.sh all 1.0.2

# 前端回退到一个已发布的旧版本
sh deploy/deploy.sh site 1.0.1

# 查看脚本用法
sh deploy/deploy.sh --help

指定版本部署成功后,脚本会在所选环境文件中记录独立的 SITE_IMAGE_TAG 或 SERVER_IMAGE_TAG。server 包含复用同一镜像的 worker;all 会同时记录两端版本。其他配置和共享的 IMAGE_TAG 保留。拉取、迁移、健康检查或 Nginx reload 失败时不会写入新版本;已经更新的容器不会因此自动回退。

例如先执行 site 1.0.2,再执行 server 1.0.3,后续运行不带版本的全量脚本时,仍使用前端 1.0.2、后端 1.0.3。要将两端再次统一到一个版本,执行 all 版本号。

省略版本时,使用所选环境文件中的独立版本配置;未设置独立版本则回退到 IMAGE_TAG,最后为 latest。兼容原有 IMAGE_TAG=1.0.2 sh deploy/deploy.sh site 写法,命令行第二个版本参数优先于外部 IMAGE_TAG。外部 IMAGE_PREFIX 仍可用于覆盖镜像仓库。

单端更新需要依赖服务已经运行:site 需要 server,server 需要 Redis。缺少依赖时脚本会退出并提示先做全量部署。脚本从任意工作目录调用均可,会定位自身目录的 compose.yml,并按上述优先级选择环境文件。

修改运行凭证或端口后也通过脚本重建目标容器;单纯 restart 不会重新加载环境变量。前端构建变量变化需要先重新构建镜像。后端更新和全量部署会自动 reload 运行中的 site,避免后端容器 IP 变化后 Nginx 继续访问旧地址。

镜像回退仍会执行所选后端版本的迁移命令,不会自动回退数据库结构,需要确认旧镜像与当前数据库兼容。停止服务使用 down 保留命名卷,重装和回退时不要执行 down -v。

本地构建 ​

在仓库根目录执行:

bash
docker build -t dp-server:local packages/server
docker build -f packages/site/Dockerfile -t dp-site:local .

本机默认构建当前 CPU 架构。部署到 x86 服务器时使用 docker build --platform linux/amd64 ...;CI 固定生成 linux/amd64 镜像。

后端通过 uv 锁文件安装生产依赖,运行时使用 Python 3.12、非 root 用户,并包含 MySQL 客户端运行库和 PDF 转图片所需的 Poppler。前端多阶段构建,最终镜像只保留 Nginx 和静态文件。

.env、虚拟环境、依赖目录、日志均被构建上下文排除。后端密钥在容器启动时注入。前端默认 API 地址为 /api/,由 Nginx 转发至内部 server:4900,关闭代理缓冲以支持流式响应。

需要独立 API 域名时可传 --build-arg VUE_APP_BASE_URL=https://example.com/api/。其他前端构建配置可通过 --secret id=site_env,src=/path/to/frontend.env 传入;所有 VUE_APP_* 都可能出现在浏览器产物中,不应包含服务端密钥。

配置与启动 ​

bash
cp deploy/.env.example deploy/.env
# 编辑 deploy/.env

必须配置 SECRET_KEY、外部 MySQL 的 DB_HOST/DB_NAME/DB_USER,并提前创建数据库。DB_PASSWORD 允许为空;数据库账号未设置密码时填写 DB_PASSWORD=,server 和 worker 都会使用空密码。MySQL 端口默认 3306,非默认端口时添加 DB_PORT。MySQL、Redis 的主机名不能使用容器内的 localhost;宿主机 MySQL 保留使用 DB_HOST=host.docker.internal 和实际 DB_PORT;Compose 已为 server、worker 添加 host-gateway 映射,支持 Linux Docker。MySQL 需监听容器可访问的宿主机网卡地址,并允许对应来源连接;仅监听 127.0.0.1 时,Linux 容器仍无法访问。也可继续填写数据库的实际 IP 或域名。DB_CONNECT_TIMEOUT 默认为 3 秒。

deploy/.env.example 按能力分组,只保留连接信息和功能凭证:

  • 基础启动:填写应用密钥和 MySQL 连接信息。
  • 聊天:填写百炼 API Key 和默认应用 ID;养老场景默认复用该应用,需要独立应用时添加 ALIYUN_BAILIAN_YANGLAO_APP_ID。
  • 知识库:填写百炼业务空间、对应场景的知识库 ID,以及 TOS 凭证。养老知识库 ID 必须独立填写,不会回退到默认知识库。
  • PDF:填写 TOS、ARK 配置;生成页面语音还需要语音合成配置。
  • 语音:填写 VOL_APPID、VOL_ACCESS_TOKEN 和有效的 VOL_VOICE_TYPE。当前页面默认走文字+语音双流接口,因此页面聊天需要语音配置;仅调用 chat/text 接口时不需要。

未使用的功能组可以省略。具体资源准备见 阿里云接入文档。

按需覆盖默认值 ​

以下变量不必逐项写入 .env;只有部署与默认值不同时再添加:

变量默认值/用途
IMAGE_PREFIXkjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com/imvkmark/dp,生成 dp-server、dp-site 镜像地址
IMAGE_TAGlatest;前后端的共享默认标签,如 IMAGE_TAG=1.0.1
SERVER_IMAGE_TAG / SITE_IMAGE_TAG默认使用 IMAGE_TAG;脚本指定版本部署成功后分别记录,优先于 .env 中的共享标签
REDIS_DATA_VOLUME / SERVER_LOGS_VOLUMEmono4py_redis-data / mono4py_server-logs;显式保留原数据卷,项目名改为 daniu-dp 后继续复用
SITE_BIND_HOST / SITE_PORT0.0.0.0 / 4904;宿主机 Nginx 转发时设置 SITE_BIND_HOST=127.0.0.1
DB_PORT / DB_CONNECT_TIMEOUT3306 / 3 秒
CELERY_BROKER_URLredis://redis:6379/0,使用 Compose 内置 Redis
CELERY_QUEUE_PREFIX / CELERY_DEFAULT_QUEUEmono4py-prod / default,server 和 worker 必须保持一致
CELERY_CONCURRENCY / CELERY_TIMEZONE2 / Asia/Shanghai
WEB_CONCURRENCY / GUNICORN_THREADS / GUNICORN_TIMEOUT2 / 8 / 300 秒
VOL_TOS_REGIONcn-beijing;TOS 桶在其他地区时必须添加此配置
ARK_ENDPOINT / ARK_MODEL北京 Ark 接入地址 / doubao-seed-2-1-turbo-260628
ALIYUN_BAILIAN_CATEGORY_IDdefault
ALIYUN_RAG_BASE_URL根据百炼业务空间自动生成北京 RAG 地址
ALIYUN_DASHSCOPE_BASE_URLhttps://dashscope.aliyuncs.com/api/v1

AI_PROVIDER 已固定只支持百炼,默认 aliyun,无需填写。USE_CELERY 没有实际切换任务执行方式,部署固定运行 worker;当前未启用 Celery 结果后端,CELERY_RESULT_EXPIRES、CELERY_RESULT_GLOBAL_KEY_PREFIX 也不需要配置,已从部署示例删除。

省略变量和设置为空字符串不同:例如 VOL_VOICE_TYPE= 会覆盖已有默认值,应填写有效音色;没有自定义接入地址时,直接省略对应变量。Compose 为 server、worker 都提供 mono4py-prod 队列前缀,精简示例后仍沿用原来的生产队列。

启动服务 ​

本地构建并运行:

bash
# 将 deploy/.env 的 IMAGE_PREFIX 设为 dp,IMAGE_TAG 设为 local
docker compose --env-file deploy/.env -f deploy/compose.yml -f deploy/compose.local.yml build
docker compose --env-file deploy/.env -f deploy/compose.yml run --rm --no-deps server migrate
docker compose --env-file deploy/.env -f deploy/compose.yml up -d --wait

访问 http://localhost:4904。仅 site 映射宿主机端口,可通过 SITE_PORT 修改。server 的 4900 和 Redis 的 6379 仅供容器网络访问。

迁移命令会修改所配置的数据库;上线前备份数据库。server 启动不自动执行迁移,避免多个副本并发迁移。

PDF 页面唯一约束迁移 ​

0007_unique_pdf_item_page 为 pdf_item 添加 (pdf_id, page) 唯一约束,配合拆页任务复用已有页面,避免重试时产生重复页面。此迁移接在现有百炼迁移之后。旧 web4py 使用 0005_unique_pdf_item_page 创建同名索引;修复后的 0007 会检查现有索引,同名、字段顺序和唯一性一致时复用并正常记录迁移,缺少时创建,定义不一致时明确报错。

更新到此版本时,先停止旧 worker 和 server,在所配置的 MySQL 数据库中检查历史重复记录:

sql
SELECT pdf_id, page, COUNT(*) AS duplicate_count
FROM pdf_item
GROUP BY pdf_id, page
HAVING COUNT(*) > 1;

若存在重复记录,应先确认保留的图片、文案和语音并合并或清理数据;迁移不会自动删除记录。确认没有重复后,使用新 server 镜像运行本页的 migrate 命令,再启动新 server 和 worker。deploy/deploy.sh 会自动执行迁移,使用脚本更新前也需完成上述停服和数据检查。

若使用原始 v1.0.2 镜像遇到 MySQL 1061 Duplicate key name 'unique_pdf_item_page',优先更新到包含迁移修复的后端镜像并重新执行 migrate。若需在当前镜像恢复部署,先在目标数据库检查:

sql
SHOW INDEX FROM pdf_item WHERE Key_name = 'unique_pdf_item_page';
SELECT name FROM django_migrations WHERE app = 'api' ORDER BY name;

只有确认该索引恰好包含两列,Seq_in_index=1 为 pdf_id、Seq_in_index=2 为 page,两行 Non_unique=0、Sub_part IS NULL,且当前项目的 0005_aliyun_knowledge、0006_aliyun_default_provider 已登记、0007_unique_pdf_item_page 未登记时,才可在使用相同数据库配置的 server 容器内执行:

bash
python manage.py migrate api 0007_unique_pdf_item_page --fake
python manage.py migrate

这里的 --fake 仅补记已经存在的 PDF 唯一约束迁移。不要对整个迁移链使用 --fake;定义不一致时应先核对具体差异,保留现有索引和数据。

迁移完成后,可通过 site 转发的 POST /api/pdf/queue/start 补交未处理 PDF。请求体 {} 表示全部未处理记录,{"pdf_id":123} 表示指定记录;返回的 data.queued_count 为已提交任务数,status=1 时可能已有部分任务成功入队。请勿在任务执行期间重复提交;页面记录不会重复创建,OCR/TTS 仍可能重复调用。

ACR 与版本发布 ​

默认沿用参考项目的 ACR 地址及命名空间:

  • kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com/imvkmark/dp-server
  • kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com/imvkmark/dp-site

在 ACR 创建对应仓库,GitHub 仓库配置 Actions Secrets:ACR_USERNAME、ACR_PASSWORD。这些是镜像仓库凭证,与百炼 API Key 无关。更换镜像仓库时同时调整工作流的 REGISTRY/NAMESPACE 和部署环境的 IMAGE_PREFIX。

工作流为 .github/workflows/docker-images.yml,先运行完整后端测试(SQLite,无需 MySQL、Redis 或云端凭证),测试通过后分别构建 server 和 site 的 linux/amd64 镜像;前端构建失败也会阻止该镜像发布。

触发方式行为镜像标签
推送 master测试、构建、推送 ACRmaster、latest、sha-<完整提交SHA>
推送 v1.0.0 等版本标签测试、构建、推送 ACR1.0.0、latest、sha-<完整提交SHA>
推送 v1.0.0-rc.1 等预发布标签测试、构建、推送 ACR1.0.0-rc.1、sha-<完整提交SHA>,不覆盖 latest
向 master 提交 PR测试、构建验证不登录、不推送 ACR
Actions 页面手动运行对所选分支/标签测试、构建、推送分支或版本标签及 sha-<完整提交SHA>;master 和正式版本更新 latest

latest 会随主分支或正式版本构建更新,部署时优先固定版本标签或 sha-<完整提交SHA>。两种镜像独立发布;确认整个工作流成功后再部署同一 SHA,避免使用部分构建成功的版本。BuildKit 使用 GitHub Actions 缓存,前后端分别缓存,不依赖 ACR 的 buildcache 仓库。

仓库配置入口为 Settings → Secrets and variables → Actions:

  • 必填 Secrets:ACR_USERNAME、ACR_PASSWORD,账号需要对两个 ACR 镜像仓库拥有推送权限。缺少时发布任务会明确失败;PR 构建无需这些凭证。
  • 可选 Variables:VUE_APP_BASE_URL,默认 /api/;修改后需重新运行构建。
  • 可选 Secret:SITE_BUILD_ENV,内容为前端构建时的 dotenv 文本,通过 BuildKit 的 site_env 挂载;仅供前端使用,不放数据库密码、百炼 API Key 等服务端凭证。VUE_APP_* 仍可能编译到浏览器产物中,BuildKit Secret 不会使最终 JavaScript 中的内容保密。fork PR 无法读取此配置。

运行完成后可在任务 Summary 中查看镜像标签和 digest。手动触发时进入 Actions → Docker images → Run workflow。工作流只负责测试、打包和发布镜像,不会自动连接部署服务器。

推送工作流到 master 即可触发自动打包;正式版本发布示例:

bash
git tag v1.0.0
git push origin v1.0.0

以上标签仅为命令示例,需要发布时再执行。

服务器准备 deploy/ 目录和 .env,登录仓库后指定已发布的镜像版本部署:

bash
docker login kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com
sh deploy/deploy.sh all 1.0.1

脚本依次校验配置、拉取镜像、执行数据库迁移、启动服务并等待健康检查。Redis 数据和后端日志使用命名卷持久化。生产环境由入口代理配置 HTTPS。

验证与排查 ​

bash
docker compose --env-file deploy/.env -f deploy/compose.yml ps
docker compose --env-file deploy/.env -f deploy/compose.yml logs --tail=100 server worker site
curl -f http://localhost:4904/healthz
docker compose --env-file deploy/.env -f deploy/compose.yml exec server python manage.py check
docker compose --env-file deploy/.env -f deploy/compose.yml exec worker python manage.py check_worker_health

server 的 /healthz 会对所配置的数据库执行只读 SELECT 1:正常返回 HTTP 200,数据库异常返回 HTTP 503,响应不暴露连接凭证。site 的 /healthz 仍仅检查 Nginx;浏览器访问该地址不能用于判断数据库状态。

worker 每 30 秒运行 check_worker_health,先检查自身数据库连接,再经消息队列向当前容器的 celery@<hostname> 节点发送 ping,等待 3 秒;数据库、消息队列或当前 worker 不可用时检查失败。检查总超时为 10 秒,启动宽限期为 60 秒,连续失败 3 次标记 unhealthy。此检查验证 worker 的控制通道,PDF 任务是否能成功调用 OCR/TTS 仍需业务验证。

部署脚本的 up --wait 会等待 server、worker、site 和 Redis 均就绪;运行期间出现 unhealthy 不会仅凭 restart: unless-stopped 自动重启,需结合监控和日志处理。健康检查不会调用外部 AI。

继续分别验证养老、幼教的聊天流、文件上传/列表/删除,以及 PDF 后台任务。修改运行密钥后执行 up -d 重建容器;修改前端编译配置后需要重新构建 site 镜像。

停止服务使用 docker compose --env-file deploy/.env -f deploy/compose.yml down,保留数据卷;不要随意使用 down -v。

验证记录与当前范围 ​

  • 2026-11-07:本地完整后端测试 44 项通过;CI 的 Action 引用修复构建 已完成后端测试和镜像发布。
  • v1.0.1 的 CI 发布 成功,提交 c82b478,镜像名为 dp-server、dp-site。
  • 本次环境变量精简和上线手册整理已完成 Compose 默认/回环地址映射校验、宿主机 Nginx HTTPS 模板语法校验(使用临时证书)以及 VitePress 文档构建;线上需要更新部署文件后才能使用新增的 SITE_BIND_HOST 设置。
  • CI 成功表示镜像已打包和发布,不表示服务器已完成部署。真实百炼聊天、知识库上传、PDF OCR/TTS 和域名 HTTPS 仍需在目标服务器按本页验收。