描述問題/錯誤/疑問
環境:
問題: 我透過 Docker Compose 執行 Evolution API。儘管在 docker-compose.yml 中定義了 Redis 服務,API 日誌卻充滿了:[Redis] redis disconnected
此外,當我嘗試使用 docker compose up -d 重新啟動堆疊時,偶爾會遇到此網路錯誤:Failed to Setup IP tables: Unable to enable ACCEPT OUTGOING rule: (iptables: No chain/target/match by that name)
我目前的 docker-compose.yml 片段:
evolution_api:
image: atendai/evolution-api:latest
environment:
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_HOST=redis
- CACHE_REDIS_PORT=6379
depends_on:
- redis
redis:
image: redis:7-alpine
我已嘗試的方法:
-
將 CACHE_REDIS_HOST 變更為 redis://redis:6379。
-
執行 yunohost firewall reload。
-
嘗試透過將 n8n 設定為「訪客」存取權限來繞過 YunoHost SSO。
疑問:
-
YunoHost 的原生 Redis 服務或其 iptables 管理(AFW)是否已知會與 Docker 內部網路衝突?
-
我該如何確保 Docker 容器繞過 YunoHost 的防火牆規則,以維持與其自身 Redis 容器的穩定連線?
-
我是否應該手動注入特定的 DOCKER-USER 鏈規則以阻止 ACCEPT OUTGOING 失敗?
錯誤訊息是什麼(如有的話)?
關於 n8n 設定的資訊
- n8n 版本:2.15.1
- 資料庫(預設值:SQLite):預設值
- n8n EXECUTIONS_PROCESS 設定(預設值:own、main):預設值
- 執行 n8n 的方式(Docker、npm、n8n cloud、桌面應用程式):systemd 服務(YunoHost)
- 作業系統:Debian 12
看看下面的内容是否有帮助。
这很可能是 Docker 的网络引擎和 YunoHost 的防火墙 (AFW) 在 Debian 12 上的经典冲突。
根本原因是 YunoHost 使用 nftables(以前使用 iptables)管理防火墙,当它重新加载或应用规则时,经常会刷新 iptables 链。Docker 创建自己的自定义链(如 DOCKER 链)来处理容器路由。当 YunoHost 刷新这些链时,Docker 尝试向一个不再存在的链添加规则,导致错误:iptables: No chain/target/match by that name。
因为网络规则被破坏了,你的 evolution_api 容器看不到 redis 容器,即使它们在同一个 compose 文件中。这导致了 redis disconnected 的大量输出。
这是修复这两个问题的分步解决方案。
1. 修复配置 (Evolution API)
Evolution API 需要一个连接 URI,而不是单独的 Host 和 Port 变量。你使用的是 CACHE_REDIS_HOST,API 很可能会忽略它而使用 CACHE_REDIS_URI。
**更新你的 docker-compose.yml 环境部分:**删除 CACHE_REDIS_HOST 和 CACHE_REDIS_PORT,用 CACHE_REDIS_URI 替换。
# 改这个:
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_HOST=redis
- CACHE_REDIS_PORT=6379
# 改成这个:
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_URI=redis://redis:6379
(注意:如果你为 Redis 使用了密码,格式是 redis://:password@redis:6379)。
2. 解决 iptables / YunoHost 冲突
要修复 Unable to enable ACCEPT OUTGOING rule 错误并恢复容器之间的连接,你必须确保 Docker 在 YunoHost 初始化防火墙之后重新创建其网络链。
快速修复(手动)
依次运行这些命令来清除冲突并强制 Docker 重建其规则:
# 1. 先重新加载 YunoHost 防火墙
yunohost firewall reload
# 2. 重启 Docker 守护程序以强制它重新注入其链到 iptables
sudo systemctl restart docker
# 3. 启动你的堆栈
docker compose up -d
永久修复(自动化)
由于 YunoHost 可能在更新或通过 WebUI 时重新加载防火墙,Docker 的规则会再次被破坏。为了防止这种情况,你可以创建一个简单的 systemd 覆盖来确保在防火墙更改时 Docker 重启,或更简单地添加一个 cron 作业/钩子。
然而,在 YunoHost 上最稳定的方法是确保 Docker 是最后启动的。如果你发现这在重启后经常发生,运行:
sudo systemctl enable docker
如果你手动重新加载防火墙,始终在其后运行 sudo systemctl restart docker。
回答你的具体问题:
1. YunoHost 的本地 Redis 或 iptables 管理是否已知会冲突?
是的。 YunoHost 的防火墙管理很激进。它不
您好,
感謝您的回答。
我試過您的 docker compose 設定,但無法成功。「Redis disconnected」錯誤仍在繼續。以下是我最新的 docker-compose.yml 文件:
version: '3.8'
services:
evolution_api:
image: atendai/evolution-api:latest
container_name: evolution_api
restart: always
network_mode: "host"
ports:
- "8080:8080"
environment:
- SERVER_TYPE=http
- SERVER_PORT=8080
- SERVER_URL=http://my-server-ip:8080
- CORS_ORIGIN=*
- CORS_METHODS=GET,POST,PUT,DELETE,PATCH
- AUTHENTICATION_TYPE=apikey
- WA_PHONE_VERSION=2.3000.10125062854
- CONFIG_SESSION_PHONE_CLIENT=Chrome
- AUTHENTICATION_API_KEY=my-auth-api-key
# Connecting to YunoHost database
- DATABASE_ENABLED=true
- DATABASE_PROVIDER=postgresql
- DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public
# Connecting to YunoHost's Redis
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_URI=redis://redis:6379
另外,我還有一個問題,您認為為什麼 QR 碼沒有出現?當我查看瀏覽器上的請求時,似乎沒有任何問題。一切看起來都是 200 OK。謝謝您。
您仍然看到"Redis disconnected"的原因是您新的docker-compose.yml中存在網路不匹配。
問題:network_mode: "host" vs. redis://redis
您已切換到network_mode: "host"。在此模式下,容器沒有自己的內部Docker網路;它直接共享您VPS的網路。
由於您正在嘗試連接到YunoHost的原生Redis(直接在主機OS上運行),您必須將其稱為localhost。
問題:network_mode: "host" vs. redis://redis
您已切換到network_mode: "host"。在此模式下,容器沒有自己的內部Docker網路;它直接共享您VPS的網路。
由於您正在嘗試連接到YunoHost的原生Redis(直接在主機OS上運行),您必須將其稱為localhost。
解決方案:更新docker-compose.yml
將您的CACHE_REDIS_URI改為使用localhost。
services:
evolution_api:
image: atendai/evolution-api:latest
container_name: evolution_api
restart: always
network_mode: "host"
# 注意:使用network_mode: host時會忽略'ports',
# 該應用將自動綁定到您VPS IP的8080端口。
environment:
- SERVER_TYPE=http
- SERVER_PORT=8080
- SERVER_URL=http://my-server-ip:8080
- CORS_ORIGIN=*
- CORS_METHODS=GET,POST,PUT,DELETE,PATCH
- AUTHENTICATION_TYPE=apikey
- WA_PHONE_VERSION=2.3000.10125062854
- CONFIG_SESSION_PHONE_CLIENT=Chrome
- AUTHENTICATION_API_KEY=my-auth-api-key
# 連接到YunoHost數據庫(正確)
- DATABASE_ENABLED=true
- DATABASE_PROVIDER=postgresql
- DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public
# 連接到YunoHost的Redis(已修復)
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_URI=redis://localhost:6379
重要步驟: 保存文件後,運行:
docker compose up -d
為什麼QR碼沒有出現
您提到瀏覽器請求返回200 OK,但沒有QR碼顯示。這直接由Redis斷開連接引起。
以下是技術原因:
-
請求(200 OK): 當您請求QR碼時,API服務器正在運行,所以它接受請求並返回有效的HTTP響應。“200 OK"只是表示"服務器正常運行並收到您的請求。”
-
處理(失敗): 要生成QR碼,Evolution API必須使用Baileys庫初始化WhatsApp會話。該庫需要存儲會話狀態和臨時連接數據。
-
崩潰: Evolution API使用Redis來管理此狀態。由於Redis斷開連接,API無法在後台創建會話。它向瀏覽器返回成功響應,但負載(實際QR碼數據)為空或無效,因為後端進程在嘗試寫入Redis時崩潰。
一旦您將CACHE_REDIS_URI修復為localhost並且"Redis disconnected"日誌停止,QR碼將立即出現。
YunoHost用戶的最終提示
如果即使更改為localhost後仍然看到"Redis disconnected",則意味著YunoHost的Redis配置為僅允許來自特定用戶的連接或設有密碼。
通過在VPS終端上運行以下命令,檢查YunoHost Redis是否有密碼:
redis-cli ping
感謝你的回答。
我其實已經解決了 Redis 和 QR 顯示的兩個問題。
關於 Redis 的第一個問題,你的解決方案對我有效。按照你在 compose 文件中指示的更改就足夠了,我還重啟了 YunoHost (AFW) 防火牆和 Docker。
對於第二個問題,我發現 Evolution API 映像因為舊的 WhatsApp 協議而不再受支援。我更換了映像,它立即就能運作,甚至不需要更改我的 compose 文件。我已經在下面分享了我的設定:
version: '3.8'
services:
evolution_api:
image: evoapicloud/evolution-api:latest # 這是穩定版本
container_name: evolution_api
restart: always
network_mode: "host"
environment:
- SERVER_TYPE=http
- SERVER_PORT=8080
- SERVER_URL=http://your-server-ip:8080
- CORS_ORIGIN=*
- CORS_METHODS=GET,POST,PUT,DELETE,PATCH
- AUTHENTICATION_TYPE=apikey
- AUTHENTICATION_API_KEY=your-api-key
# 分別提及 WhatsApp 電話版本和瀏覽器。
- WA_PHONE_VERSION=2.3000.1030415680
- CONFIG_SESSION_PHONE_CLIENT=Chrome
# 我們要使用 YunoHost 的資料庫。
- DATABASE_ENABLED=true
- DATABASE_PROVIDER=postgresql
- DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_URI=redis://localhost:6379
# 選項:額外穩定性的設定。
- DELAY_MESSAGE=1000
- QR_CODE_EXPIRATION=600
volumes:
- ./evolution_instances:/evolution/instances
即使解決了這些問題,仍然還有一個問題:我已經設定了 Evolution API 觸發節點,但當 n8n 收到回應時,它卡在「載入資料。」但在執行普通節點時沒有問題。只有在執行觸發節點時才會出現。我已經在 GitHub 上開啟了一個問題,但還沒有找到任何修復資源。你對此有任何資訊嗎?感謝。
很高興聽到 Redis 和 QR 碼問題已經解決!改用 evoapicloud 映像檔是正確的選擇——atendai 映像檔確實已經過時,經常無法與目前的 WhatsApp Web 協議相容。
關於 n8n 觸發節點卡在**「載入資料」**,這是在同一台 YunoHost 伺服器上執行 n8n 和 Evolution API 時的一個常見問題。
由於你的一般節點可以正常運作,所以「管道」(API → n8n)對於請求來說是有效的。但是,觸發節點的運作方式相反:API 會向 n8n 發送 Webhook。當 n8n 處於「監聽」模式並顯示「載入資料」時,它正在等待有效的 HTTP 請求擊中其 Webhook 端點。
以下是在你的特定 YunoHost 設置中最可能發生這種情況的三個原因:
1. 「髮夾」網路問題(最可能)
你可能在 Evolution API webhook 設定中使用了 n8n 實例的公開 URL(例如 https://n8n.yourdomain.com/webhook/...)。
問題: 當 Evolution API(在同一伺服器上)嘗試將資料發送到你的公開 URL 時,請求會發送到你的 VPS IP,然後嘗試返回。許多防火牆(包括 YunoHost 的 AFW/iptables)和一些 VPS 提供商出於安全考慮會阻止這種「迴路」(髮夾 NAT)。請求永遠無法到達 n8n,因此節點會永遠停留在「載入資料」。
修復方法: 在 Evolution API webhook 設定中,嘗試使用 n8n 的內部位址而非公開位址。
2. n8n WEBHOOK_URL 環境變數
如果 n8n 不知道自己的公開 URL,它有時會產生使用 localhost 或內部 IP 的「測試」Webhook URL,這取決於 Docker 網路如何與 YunoHost systemd 服務互動,Evolution API 可能無法正確路由。
修復方法: 確保你的 n8n 服務(通過 YunoHost 或環境變數)已明確設定 WEBHOOK_URL:
WEBHOOK_URL=https://n8n.yourdomain.com/
如果未設定此變數,n8n 可能會給 API 一個在 UI 中看起來正確但對於傳入請求來說實際上已損毀的 URL。
3. 資料承載不匹配(「UI 掛起」)
由於你改用了 evoapicloud 映像檔,發送到 n8n 的事件 JSON 結構可能與 n8n Evolution API 節點期望的結構略有不同。
當 n8n 的觸發節點收到無法解析為預期架構的請求時,UI 有時會停留在「載入資料」而不是顯示錯誤,因為它陷入了迴圈,嘗試將傳入的 JSON 映射到節點的內部欄位。
如何測試:
-
在 n8n 中建立標準的 Webhook 節點(不是 Evolution API 觸發節點)。
-
複製該 Webhook URL 並將其放入 Evolution API webhook 設定中。
-
觸發事件(向機器人發送訊息)。
-
如果標準 Webhook 節點接收了資料,那麼問題是 Evolution API 觸發節點中的架構不匹配。在這種情況下,你可以實際上使用標準 Webhook 節點和「設定」或「代碼」節點來建立整個工作流以清理資料——這通常比使用專用觸發節點更穩定。
你的檢查清單摘要:
-
使用標準 Webhook 節點進行測試。 如果這有效,問題是觸發節點的代碼(架構不匹配)。
-
將 Evolution API 中的 Webhook URL 變更為 http://localhost:5678/... 以繞過 YunoHost 防火牆/迴路問題。
-
檢查 n8n 日誌(sudo journalctl -u n8n 或類似命令),在節點「載入資料」時查看是否出現任何 403 Forbidden 或 Connection Refused 錯誤。
神奇的是,我通過將 n8n 從版本 1.15.1 更新到 1.19.2 解決了這個問題,不過我真的不明白它是如何解決的。