杂乱的知识

NapCat Docker 端口与 1Panel 路径代理排坑笔记

2026-07-23 #记录

目的:记录 NapCat、Docker Compose、1Panel 反向代理和 Webhook 之间的端口关系,避免以后再次把“容器端口、宿主机端口、公网路径”混在一起。


一、最终架构

当前链路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Cloudflare 临时邮箱 Webhook
↓
https://napcat-api.joyb.cc/mail/send_group_msg
↓
1Panel 精确匹配路径
↓
http://127.0.0.1:3001/send_group_msg
↓
Docker 宿主机端口 3001
↓
NapCat 容器端口 3001
↓
NapCat 第二个 HTTP 服务器
↓
校验该 HTTP 服务器对应的 Token
↓
发送到 QQ 群

二、必须先分清三层端口

1. NapCat 后台端口

在 NapCat 后台:

1
网络配置 → HTTP服务器

这里填写的端口,例如:

1
2
3000
3001

是 NapCat 容器内部监听端口。

例如:

1
2
HTTP服务器 A:0.0.0.0:3000
HTTP服务器 B:0.0.0.0:3001

这两个端口都属于容器内部。

2. Docker Compose 端口

当前 Compose 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
napcat:
environment:
- NAPCAT_UID=${NAPCAT_UID}
- NAPCAT_GID=${NAPCAT_GID}

ports:
- "3002:3000"
- "3001:3001"
- "6099:6099"

volumes:
- ./data/qq:/app/.config/QQ
- ./data/config:/app/napcat/config
- ./data/plugins:/app/napcat/plugins

container_name: napcat
network_mode: bridge
restart: always
image: mlikiowa/napcat-docker:latest

Docker 端口格式:

1
宿主机端口:容器端口

所以:

Compose 配置 实际含义
3002:3000 宿主机 3002 → NapCat 容器 3000
3001:3001 宿主机 3001 → NapCat 容器 3001
6099:6099 宿主机 6099 → NapCat 容器 6099

最重要的记忆方式:

1
2
NapCat 后台填写 Compose 冒号右边的端口。
1Panel 反向代理访问 Compose 冒号左边的端口。

例如:

1
2
3
NapCat 后台监听 3000
Docker 映射 3002:3000
宿主机访问 127.0.0.1:3002

3. 1Panel 反向代理端口

1Panel 运行在宿主机上,所以它访问的是宿主机端口:

1
2
http://127.0.0.1:3002
http://127.0.0.1:3001

当前环境中,正确关系是:

1
1Panel → 宿主机端口 → Docker 映射 → NapCat 容器端口

三、端口本身没有固定功能

Compose 中:

1
- "3001:3001"

只表示开放并映射端口,不代表 3001 天生就是 HTTP、WebSocket 或其他服务。

真正决定端口功能的是 NapCat 后台的网络配置:

1
2
3
4
5
6
7
8
如果 HTTP服务器监听 3001
→ 3001 就是 HTTP API

如果 WebSocket服务器监听 3001
→ 3001 就是 WebSocket

如果没有任何服务监听 3001
→ 即使 Docker 映射了,该端口也没有实际服务

因此,端口的用途取决于 NapCat 中实际创建并启用的网络服务。


四、为什么两个 HTTP 服务器不能监听同一个端口

曾经出现过这种情况:

1
2
3
HTTP服务器 A
端口:3000
Token:旧 Token

然后又创建:

1
2
3
HTTP服务器 B
端口:3000
Token:新 Token

结果访问:

1
2
宿主机 3002
→ 容器 3000

请求始终命中已经占用 3000 的旧 HTTP 服务器,因此:

1
2
旧 Token → 200
新 Token → 403 token verify failed

这不代表新 Token 错了,而是请求根本没有进入新 HTTP 服务器。

正确做法:

1
2
HTTP服务器 A:容器端口 3000
HTTP服务器 B:容器端口 3001

总结:

1
2
多个客户端可以共用同一个 HTTP 服务器。
但两个独立 HTTP 服务器要使用不同配置或不同 Token,就必须监听不同端口。

五、管理后台和 OneBot HTTP API 不是同一个服务

NapCat 有两类不同入口:

NapCat WebUI

用途:

1
2
3
4
登录后台
修改网络配置
查看日志
管理插件

NapCat OneBot HTTP API

用途:

1
2
3
POST /send_group_msg
POST /send_private_msg
以及其他 OneBot API

如果域名反向代理到了 WebUI,却访问:

1
/send_group_msg

就会返回:

1
404 Not Found

因为 WebUI 后端没有这个 API 路径。

所以出现 404 时,优先确认:

1
当前域名或路径到底代理到了 WebUI,还是代理到了 OneBot HTTP服务器。

六、子域名不是必须的

子域名只是用来分类和隔离,不是解决多端口的唯一办法。

例如可以使用独立子域名:

1
napcat-api.joyb.cc

也可以在同一个域名下按路径分流:

1
2
/                         → 一个后端端口
/mail/send_group_msg → 另一个后端端口

真正解决多端口问题的是:

1
1Panel 的路径匹配与反向代理规则

准确理解:

1
2
子域名负责分类和隔离。
路径规则负责把不同请求转发到不同端口。

七、当前 1Panel 路径代理配置

image.png

原规则

1
2
3
名称:root
前端请求路径:/
后端代理地址:http://127.0.0.1:3002

对应:

1
2
3
宿主机 3002
→ Docker 映射
→ NapCat 容器 3000

邮件 Webhook 专用规则

1
2
3
4
5
名称:mail
匹配规则:=
前端请求路径:/mail/send_group_msg
后端代理地址:http://127.0.0.1:3001/send_group_msg
后端域名:$host

这里的 = 表示精确匹配:

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
2
3
4
5
前端路径:
/mail/send_group_msg

后端地址:
http://127.0.0.1:3001/send_group_msg

作用:

1
2
公网看到:/mail/send_group_msg
NapCat 收到:/send_group_msg

如果把 /mail/send_group_msg 原样传给 NapCat,NapCat 可能返回 404。


九、当前 NapCat 网络配置建议

HTTP服务器 A

1
2
3
4
5
类型:HTTP服务器
主机:0.0.0.0
端口:3000
Token:第一套独立 Token
状态:启用

对应:

1
2
宿主机 3002
→ 容器 3000

HTTP服务器 B

1
2
3
4
5
类型:HTTP服务器
主机:0.0.0.0
端口:3001
Token:邮件 Webhook 专用 Token
状态:启用

对应:

1
2
宿主机 3001
→ 容器 3001

两个 HTTP 服务器必须使用不同容器端口。


十、Cloudflare 临时邮箱 Webhook 正式配置

URL

1
https://napcat-api.joyb.cc/mail/send_group_msg

METHOD

1
POST

HEADERS

1
2
3
4
{
"Content-Type": "application/json",
"Authorization": "Bearer 你的邮件HTTP服务器Token"
}

BODY

精简版本:

1
2
3
4
{
"group_id": "你的QQ群号",
"message": "📬 新邮件通知\n发件人:${from}\n收件人:${to}\n主题:${subject}\n查看邮件:${url}"
}

包含正文版本:

1
2
3
4
{
"group_id": "你的QQ群号",
"message": "📬 新邮件通知\n\n发件人:${from}\n收件人:${to}\n主题:${subject}\n\n邮件正文:\n${parsedText}\n\n查看邮件:${url}"
}

正式使用建议采用 Header 传 Token,不把 Token 放在 URL 查询参数里。


十一、404 与 403 怎么判断

404 Not Found

代表:

1
2
请求到达了某个服务
但该服务没有对应路径

常见原因:

1
2
3
4
域名代理到了 WebUI,而不是 OneBot HTTP API
路径写错
路径没有正确改写
1Panel 路径规则没有命中

403 token verify failed

代表:

1
2
请求已经到达 NapCat HTTP服务器
但当前 HTTP服务器不接受这个 Token

常见原因:

1
2
3
4
5
Token 用错
使用了旧 Token
修改的不是当前命中的 HTTP服务器
反向代理仍然指向另一个端口
两个 HTTP服务器错误地监听同一个容器端口

判断方式:

1
2
3
同一个 URL:
旧 Token 成功
新 Token 失败

通常意味着请求仍然命中了旧 HTTP 服务器。


十二、推荐的排查顺序

第一步:直接测试宿主机端口

测试宿主机 3001:

1
2
3
4
curl -i -X POST 'http://127.0.0.1:3001/send_group_msg' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer 你的Token' \
-d '{"group_id":"你的QQ群号","message":"本地端口测试"}'

第二步:测试公网路径

1
2
3
4
curl -i -X POST 'https://napcat-api.joyb.cc/mail/send_group_msg' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer 你的Token' \
-d '{"group_id":"你的QQ群号","message":"公网路径测试"}'

结果判断

本地端口 公网路径 结论
成功 成功 全部正常
成功 404 1Panel 路径或代理规则错误
成功 403 公网请求命中错误后端或 Header 未正确传递
403 403 NapCat Token 或 HTTP服务器配置错误
连接失败 任意 NapCat 没监听该端口,或 Docker 没映射

十三、curl 多行命令的坑

错误写法:

1
2
3
curl -X POST \

'https://example.com'

反斜杠后插入空行,会导致:

1
2
3
curl: (2) no URL specified
-bash: -H: command not found
-bash: -d: command not found

正确写法:

1
2
3
4
curl -X POST \
'https://example.com' \
-H 'Content-Type: application/json' \
-d '{"message":"test"}'

最稳妥的是整行执行:

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
2
3
4
5
6
浏览器历史
终端命令历史
1Panel/OpenResty 访问日志
Cloudflare 日志
截图
监控系统

正式配置推荐:

1
Authorization: Bearer Token

如果 Token 曾经出现在截图、聊天记录或终端输出中,应立即重新生成。


十五、最终记忆口诀

1
2
3
4
5
6
7
1. NapCat 后台端口是容器内部端口。
2. Docker ports 左边是宿主机,右边是容器。
3. 1Panel 访问 Docker 映射左边的宿主机端口。
4. 两个 NapCat HTTP服务器不能监听同一个容器端口。
5. 同一个域名可以通过不同路径代理到不同宿主机端口。
6. 子域名负责分类,路径规则负责分流。
7. 404 查路径和后端服务,403 查命中的服务器和 Token。

十六、当前实际对应关系

1
2
3
NapCat HTTP服务器 A
容器端口:3000
宿主机端口:3002
1
2
3
NapCat HTTP服务器 B
容器端口:3001
宿主机端口:3001
1
2
3
NapCat WebUI
容器端口:6099
宿主机端口:6099
1
2
Webhook 公网地址:
https://napcat-api.joyb.cc/mail/send_group_msg
1
2
3
1Panel 路径代理:
/mail/send_group_msg
→ http://127.0.0.1:3001/send_group_msg

最终核心:不要把 NapCat 后台端口、Docker 宿主机端口和公网 URL 当成同一层。它们是连续的三层映射关系。

评论
分享

评论