Docker n8n 部署完整教學:Compose、費用與 12 個翻車點
Docker n8n 部署教學:複製 Compose 架好 PostgreSQL、SSL 與備份,實算自架費用並排除 12 個常見錯誤。
Docker n8n 部署完整教學:Compose、費用與 12 個翻車點
Docker n8n,就是用容器自架 n8n。搭配 Compose、PostgreSQL 與 HTTPS,可以處理部署、資料保存和外部 Webhook。
建議從 2 vCPU、4GB RAM 起步;熟悉 Docker 的人約 30 分鐘可完成基礎上線,VPS 預算約 NT$100~360/月。正式營運還得處理備份、監控與更新;如果只想先跑第一條流程,可先看 n8n 新手入門指南。
| 需求 | 建議 |
|---|---|
| 個人試玩 | SQLite 單容器 |
| 客戶流程或多人使用 | PostgreSQL+反向代理+SSL |
| 大量同時執行、單機開始排隊 | Queue Mode+Redis+worker |
先算錢:Docker 自架與 n8n Cloud 怎麼選?
2026 年 7 月費用對照
| 項目 | Cloud Starter | Cloud Pro | Docker 自架 Community Edition |
|---|---|---|---|
| 月費 | €20,約 NT$700 | €50,約 NT$1,750 | 軟體 NT$0;VPS 約 NT$100~360 |
| 月執行量 | 2,500 次 | 10,000 次 | 無方案額度,但受硬體限制 |
| 同時執行 | 5 | 20 | 依主機與設定調整 |
| 維運 | n8n 負責 | n8n 負責 | 更新、備份、監控都由你負責 |
Cloud 數字依 n8n 官方定價 2026 年 7 月 21 日頁面;換算以 €1=NT$35、US$1=NT$30 估算,刷卡匯率與稅金另計。拿入門 VPS 比較,Starter 一年主機價差約 NT$4,080~7,200,Pro 約 NT$16,680~19,800,但這段價差不能直接當成省下來的錢。若每月維運超過 2 小時,且人力每小時值 NT$700 以上,Cloud 通常更划算。外部的 Docker 託管平台則是介於兩者之間的市場方案,不是本站服務。完整選型可讀 n8n 自架與 Cloud 比較。
決定自架前,先替五項隱藏成本指定負責人:
- 版本更新:誰讀 breaking changes、誰決定升級窗?
- HTTPS:憑證續期失敗時,多久能收到告警?
- 資料備份:每天備份到哪裡、保留幾天?
- 監控告警:容器停止、磁碟滿、Webhook 失敗要通知誰?
- 資安加固:誰負責防火牆、帳號權限與安全更新?
沒有負責人、告警管道和還原時限,低月租只代表帳單便宜,不代表總成本低。
部署前準備:規格、資料庫與目錄
2 vCPU/4GB 是中小型流程的建議起點,不是保證值;只有 SQLite、低頻任務時,2GB 也能起跑。檔案、瀏覽器或 AI 節點很吃記憶體,請用 docker stats 與 OOM 紀錄判斷是否升級。
n8n 官方文件 說明自架預設使用 SQLite。單人試玩可以沿用;正式環境、多人使用或準備上 Queue Mode,直接選 PostgreSQL,免得之後搬資料。建立 ~/n8n/,放入 compose.yaml、.env、Caddyfile 與 local-files/;記得把 .env 加進 .gitignore,不要提交密碼或 N8N_ENCRYPTION_KEY。
最小可用版:SQLite 單容器
compose.yaml:
services: n8n: image: docker.n8n.io/n8nio/n8n:${N8N_VERSION} restart: unless-stopped ports: - “5678:5678” # 僅限內網或短期測試 environment: GENERIC_TIMEZONE: Asia/Taipei TZ: Asia/Taipei WEBHOOK_URL: ${WEBHOOK_URL} N8N_SECURE_COOKIE: ${N8N_SECURE_COOKIE} N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: “true” N8N_RUNNERS_ENABLED: “true” volumes: - n8n_data:/home/node/.n8n volumes: n8n_data:
.env:
N8N_VERSION=2.30.8 WEBHOOK_URL=http://192.168.1.20:5678/ N8N_SECURE_COOKIE=false
本文發布時 stable 為 n8n 2.30.8;正式環境固定版本,可以避免意外跨版。GENERIC_TIMEZONE 控制 Schedule 類節點,WEBHOOK_URL 決定外部服務看到的回呼網址。N8N_SECURE_COOKIE=false 只用於純 HTTP 內網測試;公開環境一律改用 HTTPS,並移除此設定。執行 docker compose up -d,開啟 http://伺服器IP:5678 建立 owner;失敗就先看 docker compose logs -f n8n。
正式環境:PostgreSQL、反向代理與 SSL
下面的 Compose 把 n8n、PostgreSQL 與外部工具 Caddy 放在同一網路,只有 Caddy 對外開放 80/443:
services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [“CMD-SHELL”, “pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB”] interval: 10s timeout: 5s retries: 10
n8n: image: docker.n8n.io/n8nio/n8n:${N8N_VERSION} restart: unless-stopped depends_on: postgres: condition: service_healthy environment: DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_PORT: 5432 DB_POSTGRESDB_DATABASE: ${POSTGRES_DB} DB_POSTGRESDB_USER: ${POSTGRES_USER} DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD} N8N_HOST: ${DOMAIN} N8N_PROTOCOL: https WEBHOOK_URL: https://${DOMAIN}/ N8N_PROXY_HOPS: 1 N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY} GENERIC_TIMEZONE: Asia/Taipei TZ: Asia/Taipei N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: “true” N8N_RUNNERS_ENABLED: “true” volumes: - n8n_data:/home/node/.n8n - ./local-files:/files
caddy: image: caddy:2-alpine restart: unless-stopped environment: DOMAIN: ${DOMAIN} ports: [“80:80”, “443:443”] volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data depends_on: [n8n]
volumes: postgres_data: n8n_data: caddy_data:
正式環境的 .env 至少要有以下欄位;兩個 replace-with-... 請分別用 openssl rand -hex 32 產生新值:
N8N_VERSION=2.30.8 DOMAIN=n8n.example.com POSTGRES_USER=n8n POSTGRES_PASSWORD=replace-with-random-password POSTGRES_DB=n8n N8N_ENCRYPTION_KEY=replace-with-random-key
Caddyfile 只要三行:
{$DOMAIN} { reverse_proxy n8n:5678 }
Caddy 會自動處理 TLS 與 WebSocket。若改用 Nginx,才要確認 Upgrade/Connection headers 與 proxy_read_timeout;Traefik 適合容器較多、想用 labels 管路由的環境。n8n 反代文件 另要求 WEBHOOK_URL、N8N_PROXY_HOPS=1 與正確的 forwarded headers。上線後,應用流量只放行 80/443,另外保留限制來源的 SSH 管理規則;不要把 5678 公開。
台灣環境:時區、浮動 IP 與國內串接
容器同時設定 TZ=Asia/Taipei 與 GENERIC_TIMEZONE=Asia/Taipei:前者影響系統時間,後者是 Schedule 節點的預設時區。若某工作流在 Workflow Settings 另行指定時區,該設定會覆蓋預設值。
家用網路沒有固定 IP 時,可以把 Cloudflare Tunnel 當成外部整合選項;cloudflared 透過 outbound-only 連線公開服務,不必開入站 port,此時 WEBHOOK_URL 要填 Tunnel 網域。注意,Tunnel 解決的是「外部連進來」,不會提供固定出口 IP;金流商若要求來源 IP 白名單,仍要另備固定 egress。LINE Messaging API 的 webhook 必須使用 HTTPS;傳送中文檔名時,檢查 UTF-8、URL encoding 與 Content-Disposition。
升級、備份與資料持久化
升級前先讀 release notes,再備份資料庫與 .n8n。後者包含自動產生的加密金鑰等重要資料;若已明確設定 N8N_ENCRYPTION_KEY,也要把 .env 存進受控的密碼庫,而不是 Git。
mkdir -p backups docker compose exec -T postgres sh -c ‘pg_dump -U “$POSTGRES_USER” “$POSTGRES_DB”’ > “backups/n8n-$(date +%F).sql” docker run —rm -v n8n_n8n_data:/data -v “$PWD/backups:/backup” alpine tar czf “/backup/n8n-data-$(date +%F).tgz” -C /data .
第三行的 n8n_n8n_data 要換成 docker volume ls 顯示的實際 volume 名稱。
把這三行存成 /opt/n8n/backup.sh 並先手動執行成功,再用以下三行加入每日 03:00 排程:
chmod 700 /opt/n8n/backup.sh { crontab -l 2>/dev/null | grep -v ‘/opt/n8n/backup.sh’; echo ‘0 3 * * * cd /opt/n8n && ./backup.sh >> backups/backup.log 2>&1’; } | crontab - crontab -l
備份成功不等於可還原。至少每季在另一台測試機匯入 PostgreSQL dump、掛回 .n8n,確認 owner 能登入、credentials 可解密,並實際跑過一條不會寫入正式資料的測試流程。
確認備份可讀後,更新 .env 的固定版本,再執行:
docker compose pull docker compose up -d
最後跑 docker compose ps、查看錯誤 log,並送一筆測試 webhook。需要備份的項目是 PostgreSQL dump、.n8n volume、.env、Compose 與 Caddyfile;至少每日排程、異地保留一份,並定期演練還原。
什麼時候該上 Queue Mode?
| 每日執行量 | 起始架構建議 |
|---|---|
| 少於 1,000 | 單一 main+PostgreSQL |
| 1,000~10,000 且有排隊 | Queue Mode+1 個 worker |
| 超過 10,000 或 webhook 尖峰 | 多 worker;量測後再評估 webhook processors |
這些數字是容量規劃的起點,不是 n8n 官方硬門檻;流程耗時、尖峰併發與檔案大小,比日總量更重要。Queue Mode 需要 PostgreSQL、Redis,以及 main/worker 共用同一個 N8N_ENCRYPTION_KEY:
environment: EXECUTIONS_MODE: queue QUEUE_BULL_REDIS_HOST: redis command: worker —concurrency=10
官方 Queue Mode 文件 指出 worker concurrency 預設為 10,並建議至少 5。重記憶體流程可從 5 起跑,輕量 API 任務可先用 10;不要只按 CPU 核心數猜,應以 RAM、CPU、Redis、資料庫連線池與等待時間壓測後再調到 20。使用二進位檔案者還要先確認 Queue Mode 的儲存限制。
12 個常見錯誤訊息與解法
| 症狀/錯誤 | 真正原因 | 解法 |
|---|---|---|
| 重啟後工作流不見 | /home/node/.n8n 未持久化 | 先查 docker volume ls;補掛 volume,無舊 volume 才需重建 |
Webhook 顯示 localhost:5678 | 未設 WEBHOOK_URL | 填公開 HTTPS 網域後重啟 |
| 外部 webhook 沒反應 | DNS、443、反代或路徑錯 | 逐層用 curl 查公開網址;不要開 5678 繞過反代 |
| 登入頁一直跳回 | HTTP 搭配 secure cookie | 公開環境上 HTTPS;只在內網測試設 N8N_SECURE_COOKIE=false |
Queued 一直不動 | worker 未啟動或 Redis/DB 不通 | 查 worker log、Redis host 與資料庫連線 |
ECONNREFUSED redis:6379 | service 名稱或網路錯 | 確認同一 Compose network 與 QUEUE_BULL_REDIS_HOST=redis |
| 排程差 8 小時 | 預設時區未改或 workflow 覆蓋 | 檢查 TZ、GENERIC_TIMEZONE、Workflow Settings |
| 升級後憑證解不開 | 加密金鑰改變 | 還原原始 N8N_ENCRYPTION_KEY 或 .n8n 備份 |
| 容器 exit 137/OOM | RAM 不足 | 降低 worker concurrency、減少大檔案或升級 RAM |
| 編輯器顯示 connection lost | 反代未支援 WebSocket 或 timeout 太短 | 修正 Nginx headers/timeout;Caddy 預設支援 WebSocket |
password authentication failed | PostgreSQL 帳密或舊 volume 不一致 | 對照 .env;舊資料卷不會因改 env 自動換密碼 |
| 更新後版本沒變 | image tag 固定但未改 N8N_VERSION | 改成已審閱的版本,再 pull 與重建容器 |
Webhook 問題仍卡住,可照 n8n Webhook 除錯指南 逐項檢查。
架好之後:別從空白畫布開始
n8n 裝好只是執行環境,實際花時間的是節點選擇、欄位映射、錯誤處理與重試。你可以把 JSON 直接匯入自架實例,再換成自己的 credentials;若不想從零搭建,可先從本站 1,700+ n8n 工作流模板中找接近需求的流程再修改。
常見問題 FAQ
Docker 自架 n8n 是免費的嗎?
Community Edition 沒有軟體訂閱費,也沒有 Cloud 方案的執行次數額度,但 VPS、網域與維運仍要付費。n8n 採 fair-code 的 Sustainable Use License;內部商務使用通常可行,轉售託管、白牌或產品嵌入前請核對 官方授權條款。
該用 SQLite 還是 PostgreSQL?
單人試玩選 SQLite;正式環境或預計使用 Queue Mode,直接選 PostgreSQL。分散式 Queue Mode 不支援 SQLite。
Webhook 收不到資料怎麼辦?
依序檢查 WEBHOOK_URL、DNS 與 HTTPS、反向代理路徑、forwarded headers、防火牆的 443;不要把開放 5678 當成正式修法。
升級 n8n 會弄丟工作流嗎?
正確掛載 volume 並保留 PostgreSQL 後,重建容器不會主動刪除資料。但跨版本仍可能有 migration 或 breaking changes,升級前一定要備份並閱讀 release notes。
需要多大的機器?
每日 1,000 次以下可先用 2 vCPU/4GB,再按 docker stats、執行時間與尖峰併發調整。大檔案、瀏覽器與多 worker 流程不能只看執行次數。
執行一直卡在 Queued 是什麼問題?
先確認 worker 有啟動,再檢查 Redis、PostgreSQL 與所有程序的 N8N_ENCRYPTION_KEY 是否一致;最直接的證據是 main 與 worker log,不是重啟整台機器。