122 lines
3.0 KiB
Markdown
122 lines
3.0 KiB
Markdown
|
||
#n8n #docker #http-proxy #https-proxy #telegram #xray #v2ray
|
||
## 问题描述
|
||
|
||
n8n 运行在 Docker 容器内,宿主机已有代理(xray/v2ray 监听 `10808` 端口),但 n8n 的 Telegram 节点无法连接 `api.telegram.org`。
|
||
|
||
---
|
||
|
||
## 排查过程
|
||
|
||
### 1. 宿主机可以访问,容器不行
|
||
|
||
宿主机用 proxychains 可以正常访问 Telegram API:
|
||
|
||
```bash
|
||
proxychains4 curl https://api.telegram.org/bot<TOKEN>/getMe
|
||
# ✅ 返回 bot 信息
|
||
```
|
||
|
||
容器内用 Node.js fetch 测试:
|
||
|
||
```bash
|
||
node -e "fetch('https://api.telegram.org/...').then(r=>r.text()).then(console.log).catch(console.error)"
|
||
# ❌ ETIMEDOUT
|
||
```
|
||
|
||
### 2. 发现 docker-compose.yml 中代理地址错误
|
||
|
||
```yaml
|
||
# ❌ 错误:容器内的 127.0.0.1 是容器自身,不是宿主机
|
||
HTTP_PROXY: http://127.0.0.1:10808
|
||
HTTPS_PROXY: http://127.0.0.1:10808
|
||
```
|
||
|
||
### 3. 修正为 host.docker.internal
|
||
|
||
```yaml
|
||
# ✅ 正确:通过 host.docker.internal 访问宿主机
|
||
HTTP_PROXY: http://host.docker.internal:10808
|
||
HTTPS_PROXY: http://host.docker.internal:10808
|
||
```
|
||
`host.docker.internal` 能工作的前提是 `docker-compose.yml` 中已有:
|
||
```yaml
|
||
extra_hosts:
|
||
- "host.docker.internal:host-gateway"
|
||
```
|
||
|
||
### 4. 确认代理端口可达
|
||
|
||
在容器内验证连通性:
|
||
|
||
```bash
|
||
node -e "
|
||
const net = require('net');
|
||
const s = net.createConnection(10808, 'host.docker.internal', () => {
|
||
console.log('✅ 代理端口可达');
|
||
s.destroy();
|
||
});
|
||
s.on('error', e => console.log('❌ 失败:', e.message));
|
||
"
|
||
# ✅ 代理端口可达
|
||
```
|
||
|
||
宿主机确认代理监听地址:
|
||
|
||
```bash
|
||
ss -tlnp | grep 10808
|
||
# LISTEN *:10808 ← 监听 0.0.0.0,容器可以访问 ✅
|
||
```
|
||
|
||
### 5. Node.js 原生 fetch 不读代理环境变量
|
||
|
||
`node fetch` 不会自动使用 `HTTP_PROXY`/`HTTPS_PROXY`,所以容器内的测试命令显示 ETIMEDOUT 是**测试方法有误**,并非代理没生效。
|
||
|
||
**n8n 使用 axios**,axios 会自动读取代理环境变量,所以 n8n 节点内是正常工作的。
|
||
|
||
验证方法:直接在 n8n 里用 **HTTP Request 节点** 访问:
|
||
|
||
```
|
||
https://api.telegram.org/bot<TOKEN>/getMe
|
||
```
|
||
|
||
能返回 bot 信息即代理生效 ✅
|
||
|
||
---
|
||
|
||
## 最终解决方案
|
||
|
||
### docker-compose.yml 关键配置
|
||
|
||
```yaml
|
||
services:
|
||
n8n:
|
||
environment:
|
||
HTTP_PROXY: http://host.docker.internal:10808 # 指向宿主机代理
|
||
HTTPS_PROXY: http://host.docker.internal:10808
|
||
NO_PROXY: localhost,127.0.0.1 # 内网地址不走代理
|
||
extra_hosts:
|
||
- "host.docker.internal:host-gateway" # 必须!映射宿主机 IP
|
||
```
|
||
|
||
### 前提条件
|
||
|
||
|条件|检查命令|
|
||
|---|---|
|
||
|宿主机代理监听 `0.0.0.0`(非 `127.0.0.1`)|`ss -tlnp \| grep 10808`|
|
||
|docker-compose 有 `extra_hosts` 配置|查看 yml 文件|
|
||
|
||
### 重启生效
|
||
|
||
```bash
|
||
docker compose down && docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
|问题|原因|解决|
|
||
|---|---|---|
|
||
|代理不生效|`127.0.0.1` 在容器内指向容器本身|改为 `host.docker.internal`|
|
||
|测试误报 ETIMEDOUT|Node.js 原生 `fetch` 不读代理环境变量|用 n8n HTTP Request 节点直接测试| |