目的:记录 NapCat、Docker Compose、1Panel 反向代理和 Webhook 之间的端口关系,避免以后再次把“容器端口、宿主机端口、公网路径”混在一起。
一、最终架构
当前链路:
1 | Cloudflare 临时邮箱 Webhook |
二、必须先分清三层端口
1. NapCat 后台端口
在 NapCat 后台:
1 | 网络配置 → HTTP服务器 |
这里填写的端口,例如:
1 | 3000 |
是 NapCat 容器内部监听端口。
例如:
1 | HTTP服务器 A:0.0.0.0:3000 |
这两个端口都属于容器内部。
2. Docker Compose 端口
当前 Compose 配置:
1 | services: |
Docker 端口格式:
1 | 宿主机端口:容器端口 |
所以:
| Compose 配置 | 实际含义 |
|---|---|
3002:3000 |
宿主机 3002 → NapCat 容器 3000 |
3001:3001 |
宿主机 3001 → NapCat 容器 3001 |
6099:6099 |
宿主机 6099 → NapCat 容器 6099 |
最重要的记忆方式:
1 | NapCat 后台填写 Compose 冒号右边的端口。 |
例如:
1 | NapCat 后台监听 3000 |
3. 1Panel 反向代理端口
1Panel 运行在宿主机上,所以它访问的是宿主机端口:
1 | http://127.0.0.1:3002 |
当前环境中,正确关系是:
1 | 1Panel → 宿主机端口 → Docker 映射 → NapCat 容器端口 |
三、端口本身没有固定功能
Compose 中:
1 | - "3001:3001" |
只表示开放并映射端口,不代表 3001 天生就是 HTTP、WebSocket 或其他服务。
真正决定端口功能的是 NapCat 后台的网络配置:
1 | 如果 HTTP服务器监听 3001 |
因此,端口的用途取决于 NapCat 中实际创建并启用的网络服务。
四、为什么两个 HTTP 服务器不能监听同一个端口
曾经出现过这种情况:
1 | HTTP服务器 A |
然后又创建:
1 | HTTP服务器 B |
结果访问:
1 | 宿主机 3002 |
请求始终命中已经占用 3000 的旧 HTTP 服务器,因此:
1 | 旧 Token → 200 |
这不代表新 Token 错了,而是请求根本没有进入新 HTTP 服务器。
正确做法:
1 | HTTP服务器 A:容器端口 3000 |
总结:
1 | 多个客户端可以共用同一个 HTTP 服务器。 |
五、管理后台和 OneBot HTTP API 不是同一个服务
NapCat 有两类不同入口:
NapCat WebUI
用途:
1 | 登录后台 |
NapCat OneBot HTTP API
用途:
1 | POST /send_group_msg |
如果域名反向代理到了 WebUI,却访问:
1 | /send_group_msg |
就会返回:
1 | 404 Not Found |
因为 WebUI 后端没有这个 API 路径。
所以出现 404 时,优先确认:
1 | 当前域名或路径到底代理到了 WebUI,还是代理到了 OneBot HTTP服务器。 |
六、子域名不是必须的
子域名只是用来分类和隔离,不是解决多端口的唯一办法。
例如可以使用独立子域名:
1 | napcat-api.joyb.cc |
也可以在同一个域名下按路径分流:
1 | / → 一个后端端口 |
真正解决多端口问题的是:
1 | 1Panel 的路径匹配与反向代理规则 |
准确理解:
1 | 子域名负责分类和隔离。 |
七、当前 1Panel 路径代理配置

原规则
1 | 名称:root |
对应:
1 | 宿主机 3002 |
邮件 Webhook 专用规则
1 | 名称:mail |
这里的 = 表示精确匹配:
1 | 只有 /mail/send_group_msg 会命中这条规则 |
外部请求:
1 | https://napcat-api.joyb.cc/mail/send_group_msg |
会被 1Panel 改写并转发为:
1 | http://127.0.0.1:3001/send_group_msg |
NapCat 最终收到的仍然是标准接口:
1 | /send_group_msg |
八、为什么必须做路径改写
外部为了区分用途,使用:
1 | /mail/send_group_msg |
但 NapCat 真正认识的是:
1 | /send_group_msg |
所以 1Panel 必须配置成:
1 | 前端路径: |
作用:
1 | 公网看到:/mail/send_group_msg |
如果把 /mail/send_group_msg 原样传给 NapCat,NapCat 可能返回 404。
九、当前 NapCat 网络配置建议
HTTP服务器 A
1 | 类型:HTTP服务器 |
对应:
1 | 宿主机 3002 |
HTTP服务器 B
1 | 类型:HTTP服务器 |
对应:
1 | 宿主机 3001 |
两个 HTTP 服务器必须使用不同容器端口。
十、Cloudflare 临时邮箱 Webhook 正式配置
URL
1 | https://napcat-api.joyb.cc/mail/send_group_msg |
METHOD
1 | POST |
HEADERS
1 | { |
BODY
精简版本:
1 | { |
包含正文版本:
1 | { |
正式使用建议采用 Header 传 Token,不把 Token 放在 URL 查询参数里。
十一、404 与 403 怎么判断
404 Not Found
代表:
1 | 请求到达了某个服务 |
常见原因:
1 | 域名代理到了 WebUI,而不是 OneBot HTTP API |
403 token verify failed
代表:
1 | 请求已经到达 NapCat HTTP服务器 |
常见原因:
1 | Token 用错 |
判断方式:
1 | 同一个 URL: |
通常意味着请求仍然命中了旧 HTTP 服务器。
十二、推荐的排查顺序
第一步:直接测试宿主机端口
测试宿主机 3001:
1 | curl -i -X POST 'http://127.0.0.1:3001/send_group_msg' \ |
第二步:测试公网路径
1 | curl -i -X POST 'https://napcat-api.joyb.cc/mail/send_group_msg' \ |
结果判断
| 本地端口 | 公网路径 | 结论 |
|---|---|---|
| 成功 | 成功 | 全部正常 |
| 成功 | 404 | 1Panel 路径或代理规则错误 |
| 成功 | 403 | 公网请求命中错误后端或 Header 未正确传递 |
| 403 | 403 | NapCat Token 或 HTTP服务器配置错误 |
| 连接失败 | 任意 | NapCat 没监听该端口,或 Docker 没映射 |
十三、curl 多行命令的坑
错误写法:
1 | curl -X POST \ |
反斜杠后插入空行,会导致:
1 | curl: (2) no URL specified |
正确写法:
1 | curl -X POST \ |
最稳妥的是整行执行:
1 | curl -i -X POST 'https://example.com/send_group_msg' -H 'Content-Type: application/json' -H 'Authorization: Bearer Token' -d '{"group_id":"群号","message":"测试"}' |
十四、安全注意事项
不要长期把 Token 放在 URL:
1 | /send_group_msg?access_token=xxxx |
因为 URL 容易出现在:
1 | 浏览器历史 |
正式配置推荐:
1 | Authorization: Bearer Token |
如果 Token 曾经出现在截图、聊天记录或终端输出中,应立即重新生成。
十五、最终记忆口诀
1 | 1. NapCat 后台端口是容器内部端口。 |
十六、当前实际对应关系
1 | NapCat HTTP服务器 A |
1 | NapCat HTTP服务器 B |
1 | NapCat WebUI |
1 | Webhook 公网地址: |
1 | 1Panel 路径代理: |
最终核心:不要把 NapCat 后台端口、Docker 宿主机端口和公网 URL 当成同一层。它们是连续的三层映射关系。
评论