Article · Writing

在本地 Docker 執行 n8n,並用 Cloudflare Tunnel 接收 Webhook

從本地 Docker 執行 n8n 的基本路徑出發,理解為什麼 webhook 需要公開入口,以及 Cloudflare Tunnel 在這裡解決的邊界。

7 分鐘閱讀

Evidence trail

Provenance

這篇內容的 canonical URL 是 /writing/n8n-localhost-deployment-troubleshooting/,發布日期為 2025年7月31日。

相容的歷史路徑:/posts/n8n-localhost-deployment-troubleshooting/

在本地 Docker 執行 n8n,並用 Cloudflare Tunnel 接收 Webhook
文章目錄

本地的 n8n 可以在 localhost:5678 正常執行,但外部服務看不到你的 localhost。這也是很多 webhook 教學最容易跳過的地方:容器啟動成功,只代表本機能開啟介面,不代表 GitHub、付款服務或其他雲端服務能把 HTTP 請求送進來。

這篇文章整理一條 2025 年在 Windows 上實作過的路徑:用 Docker 保存 n8n 資料,再用 Cloudflare Tunnel 把一個公開主機名稱路由到本機服務。命令與介面會隨 n8n、Docker Desktop 和 Cloudflare 的版本改變;文末會標出今天仍可沿用、以及必須重新核對的部分。

先分清楚:本機服務和公開 webhook

n8n 是以工作流程節點串起資料輸入、處理與輸出的自動化平台。當 webhook 節點顯示 http://localhost:5678/... 時,它只是在本機監聽。外部服務無法把請求直接送到你的私有網路,所以需要一個公開入口,再由入口把流量轉回本機。

這不是把 n8n 的管理介面「免費放到網路上」的同義詞。公開入口增加了攻擊面,應該只發布必要的 hostname 與 route,並為 n8n、憑證和 webhook payload 設定適當的安全策略。

Docker 只負責讓 n8n 穩定地跑起來

原始實作使用 n8nio/n8n 映像與 /home/node/.n8n 掛載路徑。持久化 volume 的重點是保留 workflow、credential 加密資料、設定與執行紀錄;若只用 --rm 而沒有掛載資料,容器刪除後就會失去本機狀態。

目前 n8n 官方仍提供單容器命令,但已在該頁標示 Docker Compose 是推薦路徑;官方也提醒 self-hosting 需要自行處理資源、安全與更新。下面的命令只示範本機驗證,並不宣稱是 production 部署:

docker volume create n8n_data
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -e GENERIC_TIMEZONE="Asia/Taipei" \
  -e TZ="Asia/Taipei" \
  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
  -v n8n_data:/home/node/.n8n \
  n8nio/n8n

啟動後,先在本機確認 http://localhost:5678 可以打開並完成初始設定。若目標是長期執行,應改讀官方 Docker Compose 範例、固定映像版本、保存 encryption key、設定備份與更新流程;latest 是可變的標籤,不應當成可重現版本。

Docker 在 Windows 終端機顯示版本
原始文章中的 Docker 本機驗證畫面;它只證明 Docker CLI 當時可用,不代表現在的 n8n 版本相同。

Cloudflare Tunnel 如何補上公開入口?

Cloudflare Tunnel 的角色是讓本機的 cloudflared 主動建立到 Cloudflare 的連線,再把公開 hostname 映射到本機服務。外部請求先到 Cloudflare,再經 tunnel 送到 http://localhost:5678;這與直接在路由器開 inbound port 不同。

Cloudflare 目前推薦多數情境使用 remotely-managed tunnel;locally-managed tunnel 仍適合特定的本地開發、測試或 legacy 設定。若沿用本文的 CLI 路徑,最小流程是:

cloudflared tunnel login
cloudflared tunnel create n8n-tunnel
cloudflared tunnel route dns n8n-tunnel webhook.example.com
cloudflared tunnel run n8n-tunnel

config.yml 需要把 tunnel ID、credentials file 和 ingress 指向本機 n8n:

tunnel: <TUNNEL-UUID>
credentials-file: C:\Users\<YOUR-USERNAME>\.cloudflared\<TUNNEL-UUID>.json

ingress:
  - hostname: webhook.example.com
    service: http://localhost:5678
  - service: http_status:404

原文曾直接連到一個帶有日期的 cloudflared Windows 執行檔。那個下載網址不應永久複製;請改從 Cloudflare Tunnel 官方下載與建立指南 取得適合平台的版本,並先執行 cloudflared --version。需要開機常駐時,再參考官方的 Windows service 指南

原始文章說明本機服務與外部網路的關係
原始文章中的概念示意;公開 hostname、Tunnel 與本機服務之間的實際路由,仍以 Cloudflare 當前設定為準。

Webhook 測試網址和正式網址不是同一個

n8n 的 webhook 通常會區分測試與 production URL。測試 URL 只有在編輯器等待測試時才可用;工作流程啟用後,外部服務應使用 production URL。透過 reverse proxy 或 tunnel 時,還要讓 n8n 知道外部使用的 scheme、host 與 path,否則畫面產生的連結可能仍指向 localhost

因此驗證順序應該是:

  1. 先在 localhost:5678 讓 workflow 能接收本機請求。
  2. 再從另一個網路位置呼叫公開 hostname,確認 tunnel 有轉發到相同 workflow。
  3. 最後檢查 n8n 顯示的 webhook URL、TLS、認證、CORS 與 payload,不要只看瀏覽器能否打開首頁。

如果 webhook 會接收電子報訂閱資料,還需要額外的 rate limit、輸入驗證、重放防護、秘密管理與錯誤紀錄。Tunnel 只解決連線路徑,不會自動替 workflow 完成這些應用層工作。

這次實作的結果與限制

原始文章驗證了「Docker 本機服務 → Cloudflare Tunnel → 公開 webhook」這條路徑,也記錄了當時從 Hugging Face Spaces 搬回本機的背景。但其中關於 SMTP、OAuth2 期限與特定託管平台限制的描述,屬於當時環境中的觀察,不能直接推廣到所有帳號、節點或今天的服務行為。

同樣地,本文沒有提供長期 uptime、郵件投遞率或 production security review。它是一篇目前仍可理解的部署文章,但不是不需更新的 runbook。執行前應核對 n8n 官方 self-hosting 文件Docker Compose 安裝文件Cloudflare Tunnel routing 文件

參考資料