MaxKB 容器跨平台迁移与发布完整技术手册

文档版本 :v4.0(实战修订版) 编写日期 :2026-10-22 适用环境 :Windows 11(Docker Desktop)→ Rocky Linux 9.x(Docker CE) 操作对象 :MaxKB 一体容器(含大模型配置、知识库数据、自定义口令) 编写原则:本文档严格按实际操作顺序编写,包含每一步的命令、参数说明、校验方法与已知故障。


一、环境与资产总览

1.1 端点信息

项目 值 备注
源宿主机 Windows 11 Docker Desktop
源容器名 MaxKB 一体镜像,内置 PostgreSQL
容器内服务端口 8080 容器内部固定,不可改
目标宿主机 Rocky Linux 9.x(VM) IP 192.168.133.135
目标映射端口 28080:8080 宿主机 28080 对外
frp 服务端 159.75.236.150:7000 云主机 Windows Server 2022
frp 远程端口 28082 公网访问端口

1.2 端口三层模型(必须理解)

层级 示例 约束
容器内部 8080 各容器独立,可重复
宿主机映射 -p 28080:8080 同一宿主机不可冲突
frp 远程口 remotePort=28082 服务端全局不可冲突

改宿主机端口不影响容器内部,MaxKB 始终监听 8080。


二、源环境打包(Windows 11)

2.1 确认容器与数据卷

复制代码
docker ps -a --filter name=MaxKB --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
docker inspect MaxKB --format='{{range .Mounts}}{{.Type}} -> {{.Destination}}{{"\n"}}{{end}}'

记录 Destination,MaxKB 一体镜像标准为 /opt/maxkb/data。

2.2 停止容器

复制代码
docker stop MaxKB

PostgreSQL 运行时 commit 可能落半截事务。主动停止是严谨做法。

2.3 提交镜像

复制代码
docker commit MaxKB maxkb:prod20261021
docker images maxkb

不使用 latest 标签,便于版本追踪与回滚。

2.4 导出镜像

复制代码
docker save -o D:\maxkb_prod_image.tar maxkb:prod20261021
Get-Item D:\maxkb_prod_image.tar | Select-Object Name, @{N='Size_GB';E={[math]::Round($_.Length/1GB,2)}}

约 3.65GB,属正常。

2.5 导出数据卷

复制代码
docker run --rm --volumes-from MaxKB -v D:\export:/backup alpine:latest `
  tar czf /backup/maxkb_vol.tar.gz -C /opt/maxkb data

校验:

复制代码
docker run --rm -v D:\export:/backup alpine tar tzf /backup/maxkb_vol.tar.gz | Select-String "pgdata/base|pgdata/global/pg_control"

必须出现 data/postgresql/pgdata/base/ 与 data/postgresql/pgdata/global/pg_control。

2.6 原环境验证(不可省略)

复制代码
docker run -d --name maxkb_verify -p 18080:8080 --volumes-from MaxKB maxkb:prod20261021
Start-Sleep -Seconds 30
docker logs --tail 50 maxkb_verify

浏览器访问 http://localhost:18080,验证:

  • 修改后的口令可登录
  • 大模型配置完整
  • 知识库文档完整
复制代码
docker rm -f maxkb_verify

三、文件传输(SCP)

复制代码
scp D:\maxkb_prod_image.tar root@192.168.133.135:/opt/
scp D:\export\maxkb_vol.tar.gz root@192.168.133.135:/opt/
ssh root@192.168.133.135 "ls -lh /opt/maxkb_prod_image.tar /opt/maxkb_vol.tar.gz"

四、目标端部署(Rocky Linux)

4.1 加载镜像

复制代码
docker load -i /opt/maxkb_prod_image.tar
docker images | grep maxkb

4.2 解压数据

复制代码
mkdir -p /opt/maxkb_prod
tar xzf /opt/maxkb_vol.tar.gz -C /opt/maxkb_prod --strip-components=2
ls /opt/maxkb_prod/data/postgresql/pgdata

必须含 base、global、pg_wal。

4.3 权限与 SELinux(可略)

复制代码
chown -R 999:999 /opt/maxkb_prod
chmod -R 755 /opt/maxkb_prod
chcon -R -t container_file_t /opt/maxkb_prod

4.4 拉起容器(映射新端口 28080)

复制代码
docker run -d \
  --name maxkb \
  -p 28080:8080 \
  -v /opt/maxkb_prod:/opt/maxkb:Z \
  --restart=unless-stopped \
  maxkb:prod20261021

只挂一处 -v 。绝不可再加 /var/lib/postgresql/data,会盖掉 MaxKB 自带 PG。

4.5 验证

复制代码
docker ps --filter name=maxkb
docker logs --tail 60 maxkb
curl -I http://127.0.0.1:28080
firewall-cmd --permanent --add-port=28080/tcp && firewall-cmd --reload

浏览器 http://192.168.133.135:28080 验证通过。


五、frp 公网发布(本次最大故障点)

5.1 架构

复制代码
MaxKB容器(8080) ← -p 28080:8080 ← VM(192.168.133.135:28080)
      ↑ netsh portproxy
Win11(127.0.0.1:28080) ← frpc ←→ 云主机 frps(7000) → 公网:28082

5.2 Win11 本地端口转发

frpc 运行在 Win11,其 localIP 只能填 127.0.0.1。虚拟机流量靠系统转发:

复制代码
netsh interface portproxy add v4tov4 `
  listenaddress=127.0.0.1 listenport=28080 `
  connectaddress=192.168.133.135 connectport=28080
netsh interface portproxy show all

5.3 frpc.toml 完整配置

复制代码
serverAddr = "159.75.***"
serverPort = 7000
​
[[proxies]]
name = "MaxKB"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8081
remotePort = 8082
​
[[proxies]]
name = "MaxKB-VM"
type = "tcp"
localIP = "127.0.0.1"
localPort = 28080
remotePort = 28082
​
[webServer]
addr = "127.0.0.1"
port = 7400
user = "admin"
password = "*****"

若服务端 frps.toml 配了 auth.token,客户端必须同步加:

复制代码
auth.method = "token"
auth.token = "与服务端一致"

⚠️ 5.4 本次真凶:frpc 读取的是旧配置(重点)

故障现象 :配置明明正确,frpc.exe -c frpc.toml 反复报 i/o deadline reached,持续约 2 小时无果。电脑重启多次仍无效。

根因 :frpc 实际加载的配置不是磁盘上的 frpc.toml ,而是上次通过 Web UI(http://127.0.0.1:7400)写入的内部配置 。本地 toml 新增的 28080/28082 段未被加载。

证据 :打开 http://127.0.0.1:7400/static/#/proxies,看到的代理列表只有旧的 8081/8082,缺少新增的 MaxKB-VM。

解决步骤:

  1. 浏览器打开 http://127.0.0.1:7400/static/#/proxies

  2. 进入 Config 页面

  3. 将完整的 frpc.toml 内容整段覆盖粘贴进配置框

  4. 点击 Update & Reload

  5. 回到 Proxies 页面,确认 MaxKB-VM 已出现

  6. 此时公网 http://159.75.236.150:28082 立即可用

原理说明:

  • frpc 启动时会将配置序列化进内存 ,Web UI 的 webServer 模块操作的是内存中的配置副本

  • 磁盘 frpc.toml 只在进程首次启动时读取一次

  • 若通过 Web UI 改过配置,后续 Reload 可能复用内存副本,导致磁盘新增大段不被感知

  • 重启电脑不能解决:frpc 不是系统服务,重启后进程消失,但 Web UI 的 Reload 机制仍指向内存副本

结论 :凡通过 Web UI 管理 frpc 的场景,改完磁盘 toml 后必须到 Web UI 手动覆盖并重载,这是本次故障的唯一正确解法。

5.5 云主机侧检查

复制代码
netstat -ano | findstr :7000

必须 0.0.0.0:7000 LISTENING。

复制代码
netsh advfirewall firewall add rule name=frp7000 dir=in action=allow protocol=TCP localport=7000
netsh advfirewall firewall add rule name=frp28082 dir=in action=allow protocol=TCP localport=28082

云厂商安全组入方向放行 TCP 7000、28082。

5.6 网络拦截兜底(略)

若原网络(公司宽带/校园网)仍报 i/o deadline reached,改用 QUIC 协议(服务端需加 quicBindPort=7000,客户端加 transport.protocol="quic",并放行 UDP 7000)。


六、Nginx 反向代理与 HTTPS 发布

6.1 当前可访问地址(实测)

地址 协议 后端 状态
http://159.75.236.***:28082/chat/xxx HTTP frp→VM:28080 ✅ 可用
http://ai.dql5251.***:28082/chat/xxx HTTP frp→VM:28080 ✅ 可用(nginx 未配置 28080 亦可,因走 frp 直连)
https://ai.dql5251.***:8083/chat/xxx HTTPS nginx→Docker Desktop ✅ 可用(网页嵌入场景)

6.2 关键约束

  • MaxKB 容器内仅提供 HTTP(8080),本身无 HTTPS 能力

  • HTTPS 必须由外层终止:frp 或服务端 nginx 任一端做 TLS 卸载

  • 网页嵌入必须用 HTTPS:浏览器对嵌入 iframe 有混合内容限制,HTTP 页面嵌入 HTTP 资源会被拦截

6.3 推荐架构(HTTPS 统一入口)

复制代码
用户 HTTPS → nginx:443(TLS 终止)→ frp:28082 → VM:28080 → MaxKB:8080

6.4 nginx 配置示例

复制代码
# /etc/nginx/conf.d/maxkb.conf
server {
    listen 443 ssl http2;
    server_name ai.dql5251.***;
​
    ssl_certificate     /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
​
    location / {
        proxy_pass http://159.75.***:28082;
        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 https;
​
        # WebSocket 支持(MaxKB 对话流式输出需要)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
​
        # 流式响应不缓冲
        proxy_buffering off;
        proxy_cache off;
    }
}
​
# HTTP 强制跳转 HTTPS
server {
    listen 80;
    server_name ai.dql5251.***;
    return 301 https://$host$request_uri;
}

6.5 验证

复制代码
nginx -t && systemctl reload nginx
curl -I https://ai.dql5251.top/chat/02f58e0f0331edbf

6.6 协议混用故障说明

现象 原因
https://...:28082 打不开 frp 远程口只做 TCP 透传,不处理 TLS
HTTP 页面嵌入 MaxKB 失败 混合内容被浏览器拦截
嵌入页空白 前端站点 HTTPS,MaxKB 后端 HTTP

统一原则:对外只暴露 443,内部全 HTTP,TLS 在 nginx 一层终止。


七、故障排查矩阵

现象 根因 解法
容器秒退,日志无输出 commit 丢 CMD 用原启动命令或 volumes-from 验证
登录后知识库为空 数据卷未挂载 确认 -v /opt/maxkb_prod:/opt/maxkb
PG 报 ownership error 目录属主非 999 chown -R 999:999
SELinux 拒绝 挂载无标签 :Z 或 chcon
:28080 不通 firewalld firewall-cmd add-port 28080
frpc 报 i/o deadline 网络拦截或配置未重载 见 5.4 与 5.6
Web UI 看不到新代理 frpc 读的是内存旧配置 Web UI 覆盖 + Update & Reload
HTTPS 地址打不开 frp 不做 TLS nginx 443 终止
嵌入页空白 协议混用 全站 HTTPS

八、命令速查表

阶段 命令
停止容器 docker stop MaxKB
提交镜像 docker commit MaxKB maxkb:prod20261021
导出镜像 docker save -o D:\maxkb_prod_image.tar maxkb:prod20261021
导出数据 docker run --rm --volumes-from MaxKB -v D:\export:/backup alpine tar czf /backup/maxkb_vol.tar.gz -C /opt/maxkb data
本地验证 docker run -d -p 18080:8080 --name maxkb_verify --volumes-from MaxKB maxkb:prod20261021
SCP 传输 scp D:\maxkb_prod_image.tar root@192.168.133.135:/opt/
加载镜像 docker load -i /opt/maxkb_prod_image.tar
解压数据 tar xzf /opt/maxkb_vol.tar.gz -C /opt/maxkb_prod --strip-components=2
权限修正 chown -R 999:999 /opt/maxkb_prod && chmod -R 755 /opt/maxkb_prod
拉起容器 docker run -d --name maxkb -p 28080:8080 -v /opt/maxkb_prod:/opt/maxkb:Z --restart=unless-stopped maxkb:prod20261021
frp 重载 Web UI Config 页覆盖 → Update & Reload
nginx 重载 nginx -t && systemctl reload nginx

九、附录:本次实战时间线

  1. Windows 侧完成镜像与数据导出

  2. SCP 推送至 Rocky Linux VM

  3. 目标端 load + 解压 + 拉起容器,映射 28080

  4. 配置 frp,反复报 i/o deadline reached 约 2 小时

  5. 次日重启客户端,发现问题:Web UI 配置与本地 toml 不一致

  6. Web UI 覆盖配置并执行 Update & Reload

  7. 公网 http://159.75.236.***:28082 立即可用

  8. 补充 nginx HTTPS 反向代理,实现网页嵌入


文档结束

相关推荐
m0_682906531 小时前
工作台后端编排链路自检 10-17 11:45:56
ai·大模型·seo·geo·结构化数据·indexnow
长不大的杨瑞杰3 小时前
给 OpenCode v2 接入大模型:Provider、模型选择与 API Key 安全配置实战
人工智能·安全·ai·语言模型
360智汇云4 小时前
模型压缩功能上线:让大模型轻装上阵
ai
Navicat中国4 小时前
Navicat 18 支持 Azure OpenAI 接入,合规 AI 赋能 SQL 开发
数据库·人工智能·microsoft·ai·azure·navicat·数据
七夜zippoe5 小时前
启元 Q1 三份 MJCF 仿真文件对比:显示 / 运动学 / 全范围怎么选
ai·机器人·仿真·robot·mjcf
七夜zippoe6 小时前
启元 Q1 关节指令预检器:URDF 限位拦越界指令
ai·机器人·urdf·启元·关节
七夜zippoe6 小时前
启元 Q1 腿部运动学逆解:Python 算站立下蹲关节角
开发语言·python·ai·机器人·腿部运动学
李航19837 小时前
DeepDraw 网页版
人工智能·python·计算机视觉·ai·ai编程
七夜zippoe7 小时前
启元 Q1 接口地图:从 aimdk_msgs 逆向出 25 个 Service/Topic 的完整清单
ai·机器人·逆向·启元·接口地图