網頁

n8n Task Runner 深度解析:從概念到實戰部署(重新讓 Code node 能跑 Python 程式)

1. 前言:為什麼 Task Runner 是 n8n 2.x 的一大步?

n8n 2.x 版本引入的 Task Runner 機制,是其發展藍圖中的一個關鍵里程碑。此功能從根本上解放了 Code 節點的潛力,特別是對於 Python 程式碼的執行。它允許使用者在一個隔離且可客製化的環境中,安裝如 pandasnumpy 等強大的資料科學與數據處理函式庫。這意味著,以往需要在外部系統完成的重型運算、複雜的資料轉換與分析任務,現在都能無縫整合到 n8n 的自動化工作流程中。

本文件的核心目標,是引導您從理解 Task Runner 的底層運作原理出發,逐步完成一套穩定、可擴充的「External Mode」部署方案,並最終掌握常見的錯誤排除技巧與最佳實踐。這方面也是很多人的痛點,常常無法部署成功

接下來,我們將首先深入剖析 Task Runner 的核心架構,為後續的實戰部署打下堅實的理論基礎。


2. 核心概念:剖析 Task Runner 的運作模式

在著手部署之前,深入理解 Task Runner 的架構與其兩種運作模式至關重要。這不僅能幫助您做出最符合需求的技術選型,也能讓您在後續的維護與排錯過程中更加得心應手。

n8n 提供了兩種截然不同的 Task Runner 運作模式:Internal ModeExternal Mode。它們在設定、功能與適用場景上有著顯著差異。

比較維度

Internal Mode

External Mode

設定複雜度

低。n8n 主程序會自動啟動與管理。

高。需要額外設定一個獨立的 sidecar 容器來運行。

自訂套件能力

不支援。無法安裝額外的 Python 或 JS 套件。

完全支援可透過自訂 Dockerfile 安裝任何所需套件。

安全性

較低。Task Runner 作為 n8n 的子進程運行,共享相同的用戶與群組權限 (UID/GID),缺乏必要的權限隔離。

較高。在獨立的容器中運行,與 n8n 主程式隔離。

生產環境適用性

不建議。功能受限且安全性較低。

強烈建議。提供生產環境所需的靈活性、擴充性與安全性。

綜合比較,External Mode 雖然初始設定較為複雜,但其強大的自訂能力與更高的安全性使其成為所有正式應用、複雜運算或生產環境部署的唯一推薦方案。

讓我們來看看n8n 的 Task Runner(External Mode)架構圖

這是一個進階的部署架構,主要目的是將「工作流程的指揮(Orchestration)」與「實際的任務執行(Execution)」分離,以提升系統的穩定性、安全性和擴展性。

讓我為您詳細拆解這個架構的運作原理與各個組件的意義:

A. 架構總覽:兩個容器的協作

圖片將系統分為了左右兩個主要的容器(Container):

  • 右側:n8n container(主控端): 這是 n8n 的大腦,負責管理工作流程、處理 API 請求、資料庫交互以及 Webhook 接收。

  • 左側:task runner container(執行端): 這是 n8n 的肌肉,專門負責執行具體的節點邏輯(尤其是耗費資源的 JavaScript 代碼或 Python 腳本)。


B. 詳細組件解析

a. 右側:n8n container (主程序)

這是主要的 n8n instance (實例)。

  • n8n process: 主進程。

  • Task Broker(任務代理): 這是調度中心。它維護著一個與外部 Worker 的連線清單,負責將待執行的任務分發出去。它透過 WebSocket (ws) 等待並接收來自 Launcher 的連線。

  • Task Requester(任務請求者): 當您的 Workflow 執行到某個節點(例如 : Code note)時,Requester 會發出「執行這個任務」的請求給 Broker。

b. 左側:task runner container (執行單元)

這是一個獨立運行的環境,通常是一個獨立的 Docker 容器或 Pod。

  • Launcher process(啟動器進程):

    • 它是 Task Runner 容器的管理員。

    • ws (WebSocket): 它主動透過 WebSocket 連線到右側的 Task Broker 註冊自己,表示「我準備好接單了」。

    • spawn (生成): 當收到任務時,它會生成(Spawn)一個子進程來執行任務。

    • monitor (監控): 它負責監控子進程的狀態。如果子進程崩潰,Launcher 會知道並回報。

  • Task Runner process(任務執行進程):

    • 這是實際「幹活」的地方。您的 JavaScript/Python Code 節點、HTTP Request 處理等都在這裡發生。

    • 隔離性: 注意它是由 Launcher 生成的獨立進程。這意味著如果這個進程因為記憶體不足(OOM)或程式碼錯誤而崩潰,不會影響到主 Launcher,更不會導致右側的 n8n 主程序當機

c. 通訊與監控

  • ws (WebSockets): 圖中顯示雙向箭頭,代表兩邊透過 WebSocket 保持即時的雙向通訊,延遲極低。

  • Connection Direction: 注意箭頭方向,是由左側 (Launcher) 主動連線至右側 (Broker)。這意味著 Task Runner 不需要公開的 Ingress URL,只要能連上主 n8n 即可。

  • /healthz endpoint: 這是標準的健康檢查接口(Health Check),通常用於 Kubernetes 或 Docker Swarm,用來確認容器是否存活。


C. 為什麼要使用這種架構?

對於中階以上的 n8n 使用者,理解這個架構非常重要,因為它解決了單一實例(Monolith)模式下的幾個痛點:

  • 防止崩潰(Crash Prevention): 在傳統模式下,如果一個 Code Node 跑了一個巨大的迴圈吃光了記憶體,整個 n8n server 會當機重啟。在這個架構下,只會是左下角的 Task Runner process 死掉,Launcher 會回報錯誤,而主 n8n 依然活著繼續處理其他請求。

  • 安全性(Security / Sandboxing): 執行環境被隔離在獨立的容器中。這對於處理不受信任的輸入或在多租戶環境中非常關鍵。

  • 效能擴展(Scalability): 雖然這張圖只畫了一個 Task Runner,但您可以部署多個 Task Runner 容器連線到同一個 n8n 主程序,從而平行處理大量的計算任務。

現在我們已經理解了其核心概念,接下來將進入 External Mode 的實戰部署環節。請注意這裡需要分別設定這兩個主要的容器(Container),少了一個,執行 Code node 中的 Python 就會出現 “ Python runner unavailable: Virtual environment is missing from this system “


3. 實戰部署:透過 Docker Compose 設定 External Mode

本章節將提供一套在您已配置的 Docker Compose 環境中,基於您的配置檔案,用增加參數的方式來修改。包含 n8n、PostgreSQL 資料庫以及一個已安裝 pandasnumpy 的 Python Task Runner。採用此方案能大幅簡化部署流程,並有效避開許多新手在手動設定時可能遇到的陷阱。

先看看 docker-compose.yaml 所在處的檔案結構

新增 task-runner 資料夾的檔案結構


請依照以下步驟進行部署:

  1. 步驟一:增加環境變數@ .env

    1. 編輯原本的 .env 檔案。新增以下參數

      TASK_RUNNER_AUTH_TOKEN=your_task_runner_token_here

  1. 此檔案掌管著所有服務的敏感資訊,如資料庫密碼和服務間通訊的金鑰。請務必將其中的預設值更換為您自己的安全字串。您可以使用 https://www.md5hashgenerator.com/ 來產生一個高強度隨機金鑰。


  1. 步驟二:增加容器的設置@ .docker-compose.yml

    1. 編輯原本的 docker-compose.yml 檔案。

      1. 在 n8n: 下的 environment: 中,新增以下參數 

               

 # (NEW) Task Runner

                - N8N_RUNNERS_ENABLED=true

                - N8N_RUNNERS_MODE=external

                - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0     

                - N8N_RUNNERS_AUTH_TOKEN=${TASK_RUNNER_AUTH_TOKEN}

                - N8N_RUNNERS_STDLIB_ALLOW="*"

                - N8N_RUNNERS_EXTERNAL_ALLOW="*"

  1. 新增 task-runners:

 task-runners:

    build:

        context: ./task-runner

    restart: always

    environment:

        - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679

        - N8N_RUNNERS_AUTH_TOKEN=${TASK_RUNNER_AUTH_TOKEN}

        - N8N_RUNNERS_MAX_CONCURRENCY=5

        - N8N_RUNNERS_STDLIB_ALLOW="*"

        - N8N_RUNNERS_EXTERNAL_ALLOW="*"

     volumes:

        - ./task-runner/n8n-task-runners.json:/etc/n8n-task-runners.json:ro

    

     networks:

        - internal

     depends_on:

        - n8n

  1. 將會根據 docker-compose.yml 的定義,同時啟動 n8n 主服務、PostgreSQL 資料庫以及 Python Task Runner 三個獨立但互相關聯的服務。


  1. 步驟三:新增 task-runner 資料夾

    1. 在 task-runner 資料夾中,新增 Dockerfile ,內容如下(注意 : runners 跟 n8n 版本號必須完全相同,如兩者皆是2.2.6)

FROM n8nio/runners:2.2.6

USER root

RUN pip install --no-cache-dir \   --target=/opt/runners/task-runner-python/.venv/lib/python3.13/site-packages \

    pandas numpy yt_dlp

COPY n8n-task-runners.json /etc/n8n-task-runners.json

  1. 在 task-runner 資料夾中,新增 n8n-task-runners.json。請直接至以下網址下載。

https://github.com/n8n-io/n8n/blob/master/docker/images/runners/n8n-task-runners.json


  1. 步驟四:重新安裝

    1. 停止並移除所有Container, 請確保你在 docker-compose.yml 檔案所在的目錄下執行 docker-compose down。執行前最好先備份資料庫: 這是您的核心資產所在。資料庫中儲存了您所有的工作流程定義、執行歷史紀錄以及加密後的憑證資料。

    2. 升級執行 n8ndocker pull n8nio/n8n:latest && docker-compose up -d --build --pull always --force-recreate


  1. 步驟五:驗證安裝

    1. 等待服務啟動完成後,在您的網頁瀏覽器中開啟 http://localhost:5678。如果您能看到 n8n 的設定或登入介面,即表示所有服務已成功啟動並正常運作。

    2. 執行以下 Python 程式在 Code node

import sys

import platform

import shutil  # 用來檢查檔案路徑

import numpy as np

import pandas as pd

import yt_dlp


# 1. 測試 Numpy: 產生隨機數據

data = np.random.randint(0, 100, size=(3, 2))


# 2. 測試 Pandas: 建立 DataFrame

df = pd.DataFrame(data, columns=['Column_A', 'Column_B'])


# 3. 取得系統資訊

system_info = {

    "os": platform.system(),

    "release": platform.release(),

    "python_version": sys.version.split()[0],

    "runner_hostname": platform.node()

}


# 4. [新增] 檢查 FFmpeg 位置

# 這一步很重要,確認我們剛剛從 static-ffmpeg 複製過來的檔案能被系統找到

ffmpeg_path = shutil.which('ffmpeg')

ffprobe_path = shutil.which('ffprobe')


# 5. 回傳結果

return [

    {

        "json": {

            "status": "Success! External Python Runner is working.",

            "library_check": {

                "numpy_version": np.__version__,

                "pandas_version": pd.__version__,

                

                # [新增] 顯示 yt_dlp 版本

                "yt_dlp_version": yt_dlp.version.__version__,

                

                # [新增] 顯示 FFmpeg 安裝狀態 (預期應該顯示 /usr/local/bin/ffmpeg)

                "ffmpeg_path": ffmpeg_path if ffmpeg_path else "NOT FOUND",

                "ffprobe_path": ffprobe_path if ffprobe_path else "NOT FOUND"

            },

            "data_preview": df.to_dict(),

            "environment_info": system_info

        }

    }

]

若看到以下畫面表示成功安裝 External Python Runner 了!


此部署方案的架構由以下幾個核心檔案定義:

  • docker-compose.yml: 這是整個服務架構的藍圖。它不僅定義了 n8n、資料庫和 Task Runner 三個獨立服務,更重要的是,它建立了它們之間的通訊網路、設定了共享的認證金鑰 (N8N_RUNNERS_AUTH_TOKEN),並透過 depends_on 確保了正確的啟動順序。

  • task-runner/Dockerfile: 用於建立自訂 Python 執行環境的映像檔定義檔。您可以在此檔案中新增或修改 pip install 指令,以安裝額外的 Python 套件。

  • n8n-task-runners.json: Python 模組的白名單設定檔。基於安全考量,只有在此檔案中明確列出的套件,才能在 Code 節點中被 import

環境部署完成後,接下來我們將探討如何實際使用及客製化這個強大的 Python 執行環境。


4. 使用與客製化:釋放 Python 執行環境的潛力

完成部署只是第一步,真正的價值在於如何利用這個環境來執行客製化程式碼,並根據您的特定需求擴充其功能。

新增額外的 Python 套件

若要擴充環境功能,例如加入youtube套件 yt-dlp,請遵循以下兩個步驟:

  1. 編輯 task-runner/Dockerfile 在該檔案中找到 RUN pip install 指令,並在後面追加您想安裝的套件名稱。如下所示

FROM n8nio/runners:2.2.6

USER root

# [新增步驟] 安裝 FFmpeg

# yt-dlp 強烈依賴這個工具來處理影音合併與轉檔

# [關鍵修改] 透過多階段構建,從靜態映像檔中直接複製 ffmpeg

# 這種方式不依賴 apt/apk/dnf,適用於任何 Linux 系統

COPY --from=mwader/static-ffmpeg:latest /ffmpeg /usr/local/bin/

COPY --from=mwader/static-ffmpeg:latest /ffprobe /usr/local/bin/

#  [新增關鍵] 設定權限

# 確保這些二進位檔案對所有使用者(包含 n8n runner user)都是可讀可執行的

RUN chmod 755 /usr/local/bin/ffmpeg /usr/local/bin/ffprobe

RUN pip install --no-cache-dir \

    --target=/opt/runners/task-runner-python/.venv/lib/python3.13/site-packages \

    pandas numpy yt_dlp

COPY n8n-task-runners.json /etc/n8n-task-runners.json


  1. 重建並重啟 Task Runner 容器,儲存 Dockerfile 後,回到終端機執行重新安裝指令。

即使有了完美的設定,在實際操作中仍可能遇到問題。因此,了解如何診斷和解決常見錯誤至關重要。請善用AI工具,方法可參考以下網站

https://willhsieh.blogspot.com/2026/01/n8n-gemini-workflow.html


5. 避雷指南:常見錯誤與解決方案

本章節綜合了官方文件、社群實戰經驗以及專案的常見問題,旨在提供一份快速排錯指南,幫助您迅速定位並解決在設定與使用 Task Runner 過程中可能遇到的挑戰。

問題:ModuleNotFoundError (找不到模組)

  • 原因分析: 您在 Code 節點中嘗試 import 的 Python 套件,尚未被安裝在 task-runner 的 Docker 容器中。

  • 解決方案: 請返回上一章節「新增額外的 Python 套件」的指引,修改 task-runner/Dockerfile 加入所需的套件,然後重建並重啟 task-runners 容器。

問題:Port5680被佔用錯誤

  • 原因分析: 5680 是系統內部用。

  • 解決方案: Task Runner 預設會連線到主 n8n 服務的 5679 埠(參考 N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679。)

問題:版本不匹配導致連線失敗

  • 原因分析: n8n 主程式與 Task Runner 之間的通訊協定對版本號高度敏感。兩者的映像版本必須完全一致

  • 解決方案: 仔細檢查 docker-compose.yml 檔案,確保 image: n8nio/n8nimage: n8nio/runners 所使用的標籤版本號完全相同。例如,若 n8n 使用 2.2.6,則 runners 映像也必須是 2.2.6


掌握這些常見問題的處理方式能為您節省大量除錯時間。接下來,我們將探討如何建立一套穩健的升級與備份策略。


6. 最佳實踐:升級與備份策略

在生產環境中,任何重大的操作——無論是升級 n8n 版本、修改 Docker 設定,還是遷移服務——都應以資料安全為最高前提。執行一套嚴謹的備份策略是不可或缺的保險措施,能有效防止因意外導致的不可逆資料損失。

在進行任何變更之前,請務必完成以下三大核心備份任務:

  • 備份資料庫: 這是您的核心資產所在。資料庫中儲存了您所有的工作流程定義、執行歷史紀錄以及加密後的憑證資料。

  • 備份 n8n 安裝資料夾 : 這個位於資料夾中包含關鍵設定檔。

  • 記錄並妥善保管您的加密金鑰 (Encryption Key): 此金鑰一旦遺失,將無法透過任何方式復原,所有已儲存的憑證將永久無法解密。 請務必將其備份至安全的密碼管理器中。

n8n 的 Task Runner 為自動化工作流程開啟了全新的可能性,讓複雜的資料處理與分析得以在平台內高效完成。遵循本指南提供的部署步驟、客製化方法與最佳實踐,您將能自信地將這一強大功能整合到您的自動化專案中,從而創造更大的價值。


7. 參考資料


沒有留言:

張貼留言