FreshRSS和RSSHub的一些问题
技术笔记:解决 Docker 容器间“回环访问”导致的 cURL 28 超时
1. 问题背景
在群晖(Synology)NAS 上,通过 Docker 同时部署了 FreshRSS(RSS 阅读器)和 RSSHub(订阅源生成)。
现象:FreshRSS 更新订阅时报错 cURL error 28: Operation timed out。
矛盾点:在群晖 SSH 宿主机环境下 curl 订阅地址秒回结果,但在 FreshRSS 容器内部访问却超时。
网络拓扑:
外部访问域名:https://rsshub.xxx.xxx:8083(通过 NPM 反向代理)。
内部局域网 IP:192.168.0.101:9200(超时)。
Docker 默认网桥:172.17.0.1(有效)。
2. 核心原因分析
为什么会超时?
回环 NAT 限制:许多路由器和 Docker 默认网络环境不支持“回环访问”(NAT Loopback)。当容器尝试通过公网域名或宿主机局域网 IP 访问同一台机器上的另一个容器时,数据包发往网关后往往无法正确折返。
代理干扰:FreshRSS 容器若配置了环境变量 HTTP_PROXY,请求可能会被发往代理服务器,而代理服务器可能无法解析你的内网域名或内网 IP。
容器环境缺乏工具:Alpine 或精简版的 PHP 镜像通常不带 curl,导致通过 docker exec 调试困难。
3. 解决方案:本地 DNS 劫持(Extra Hosts)
为了不修改成百上千个订阅链接,最优雅的方法是让 FreshRSS 容器在发起对 rsshub.todtom.tech 的请求时,直接在容器内部将其指向 Docker 宿主机的网桥 IP。
为什么指向 172.17.0.1 而不用管端口?
这是最容易产生误解的地方。Hosts 文件只负责解析域名到 IP,不负责转发端口。
你在浏览器或 FreshRSS 里填写的地址是 https://rsshub.xxx.xxx:8083。
当你在 Hosts 里设置 172.17.0.1 rsshub.xxx.xxx 后,FreshRSS 实际上是在访问 https://172.17.0.1:8083。
关键点:只要你的 NPM(Nginx Proxy Manager)也将 8083 端口映射到了宿主机上,这个请求就会精准地命中 NPM,再由 NPM 转发给 RSSHub。
4. 实施步骤(Docker Compose)
修改 docker-compose.yml
为了保证容器更新或重启后配置不丢失,不要手动修改 /etc/hosts,而应在配置文件中加入 extra_hosts。
YAML
version: '3'
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss-new
# ... 其他配置 ...
extra_hosts:
- "rsshub.todtom.tech:172.17.0.1"
environment:
- TZ=Asia/Shanghai
# 如果代理导致了干扰,确保这些变量是空的或者正确配置了 NO_PROXY
- HTTP_PROXY=http://your-proxy:port
- HTTPS_PROXY=http://your-proxy:port
- NO_PROXY=localhost,127.0.0.1,172.17.0.1,rsshub.xxx.xxx更新容器命令
在 docker-compose.yml 文件所在目录下执行:
Bash
# 1. 拉取最新镜像(可选)
docker-compose pull
# 2. 重新启动并应用配置(后台运行)
docker-compose up -d注:该命令会自动检测配置更改,仅重建受影响的容器。
5. 进阶疑问解答
关于 FreshRSS 代理失效的问题
你发现 env 中看到了代理,但 FreshRSS 界面上似乎没生效。
FreshRSS 机制:FreshRSS 作为一个 PHP 应用,有时会优先使用其 Web 管理界面 -> 设置 -> 管理 -> 代理 中的配置,而不是系统环境变量。
TRUSTED\_PROXY:这个环境变量是用来告诉 FreshRSS 哪些 IP 是反向代理(如 NPM),以便正确获取客户端的真实 IP,它不负责 FreshRSS 访问外部时的请求代理。
为什么第一次更新还是超时,第二次才成功?
这种情况通常由以下原因引起:
DNS 缓存:PHP-FPM 或 cURL 进程可能缓存了旧的解析结果,第一次尝试失败后触发了缓存刷新。
RSSHub 唤醒/冷启动:如果 RSSHub 开启了某些缓存机制,或者目标网站(如抖音)响应较慢,第一次请求可能在建立连接或抓取数据时刚好超过了 FreshRSS 默认的 20 秒限制,而第二次请求因为有了缓存,速度变快从而通过。
6. 总结建议
容器间通信:优先使用 extra_hosts 劫持域名到网桥 IP,保持订阅链接的一致性。
配置持久化:始终通过 docker-compose.yml 修改配置,避免 docker exec 临时修改在更新后丢失。
代理避让:在 NO_PROXY 中加入内网域名,防止内网流量“绕远路”导致超时。
评论 加载中...