n8n 安装与部署:从 Docker 到 queue mode
安装与部署:从 Docker 到 queue mode
方式一:单容器 Docker 运行
最快的试跑方式。数据目录挂到卷上,否则容器删了数据就没了。
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e GENERIC_TIMEZONE="Asia/Shanghai" \
-e TZ="Asia/Shanghai" \
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
启动后访问 http://localhost:5678。默认用 SQLite 存数据,适合单机、流程量不大的场景。注意容器内进程以 node 用户(UID 1000)运行,如果用 bind mount 挂宿主机目录,要把目录属主改成 1000,否则会报权限错误。
方式二:docker compose 加 PostgreSQL
生产环境至少应该把数据库换成 PostgreSQL。SQLite 在并发执行、大量历史记录时容易成为瓶颈。
services:
postgres:
image: postgres:16
restart: always
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: change_me
POSTGRES_DB: n8n
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
interval: 10s
retries: 5
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "5678:5678"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: change_me
N8N_ENCRYPTION_KEY: replace_with_a_long_random_string
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
N8N_PORT: 5678
WEBHOOK_URL: https://n8n.example.com/
N8N_PROXY_HOPS: 1
GENERIC_TIMEZONE: Asia/Shanghai
TZ: Asia/Shanghai
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
volumes:
pg_data:
n8n_data:
几个环境变量必须讲清楚。N8N_ENCRYPTION_KEY 用来加密 credential,一旦设定就不能随意更换,换了以后所有已保存的凭据都解不开;多实例部署时所有实例必须用同一个值。WEBHOOK_URL 决定生成的 webhook 地址对外长什么样,放在反向代理后面时如果只填了容器地址,外部服务收到的回调地址就会指向内网。N8N_HOST 加 N8N_PROTOCOL 共同决定编辑器地址和 OAuth 回调地址,配错会导致第三方 OAuth 授权跳回失败。N8N_PROXY_HOPS 告诉 n8n 信任几层代理的 X-Forwarded-For,配错会让界面显示错误的客户端 IP,或在 https 终止于代理时出现 cookie 无法写入。EXECUTIONS_DATA_PRUNE 和 EXECUTIONS_DATA_MAX_AGE 按小时控制执行记录的保留时长,不设的话历史记录会一直堆积。
方式三:queue mode(Redis 加 worker 横向扩容)
单进程模式下所有执行都跑在主进程里,流程一多就会互相拖慢,主进程重启还会打断正在跑的任务。queue mode 把职责拆开:主进程只负责编辑器和调度,执行任务丢进 Redis 队列,由若干 worker 容器消费。
services:
redis:
image: redis:7
restart: always
volumes:
- redis_data:/data
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
command: start
environment:
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
QUEUE_BULL_REDIS_DB: 0
N8N_ENCRYPTION_KEY: replace_with_a_long_random_string
DB_TYPE: postgresdb
ports:
- "5678:5678"
n8n-worker:
image: docker.n8n.io/n8nio/n8n
restart: always
command: worker --concurrency=10
deploy:
replicas: 3
environment:
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: 6379
N8N_ENCRYPTION_KEY: replace_with_a_long_random_string
DB_TYPE: postgresdb
n8n-webhook:
image: docker.n8n.io/n8nio/n8n
restart: always
command: webhook
environment:
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
N8N_ENCRYPTION_KEY: replace_with_a_long_random_string
这一层有三个容易忽略的约束。第一,所有角色必须共用同一个 N8N_ENCRYPTION_KEY 和同一个数据库,否则 worker 解不开主进程写进去的凭据。第二,webhook 接收建议单独用 webhook 角色进程处理,因为 webhook 请求要求低延迟响应,不能和重执行任务抢资源。第三,queue mode 下 workflow 的激活状态由主进程统一管理,worker 不需要也不能自己开编辑器。并发数通过 worker --concurrency 调整,具体上限取决于节点的内存占用,以官方文档和你的压测结果为准。
方式四:npm 全局安装
不想用容器、想直接跑在宿主机上时:
npm install n8n -g
n8n start
临时想从公网接收 webhook 做调试,可以用内置隧道:
n8n start --tunnel
生产环境不要用隧道,它只适合本地调试。npm 安装方式要求 Node 版本满足官方要求,升级前先看 release note,大版本之间可能有 breaking change。
常见报错与排查
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 启动即报 credential 解密失败 | N8N_ENCRYPTION_KEY 变了或各实例不一致 | 恢复原 key;确认所有容器环境变量完全一致 |
| webhook 返回 404 | workflow 未激活,或用了测试地址而测试监听已停 | 测试期用 /webhook-test/ 并保持编辑器页面打开;生产用激活后的 /webhook/ 地址 |
| webhook 地址指向内网或 localhost | 未设置 WEBHOOK_URL | 设为对外可达的完整地址,含协议和结尾斜杠 |
| Cookie 无法写入、登录后立刻掉线 | https 反代下仍要求 secure cookie,或代理层数没声明 | 设置 N8N_PROXY_HOPS;仅在纯内网 http 调试时才考虑关闭 secure cookie |
| Code 节点报 Cannot find module | Code 节点默认只能使用内置模块 | 改用 HTTP Request 节点,或按官方说明显式放开外部模块白名单 |
| worker 连不上 Redis | 主机名、端口、密码或网络不通 | 进 worker 容器内用 redis-cli 验证连通性 |
| 执行记录把磁盘写满 | 未开启执行记录清理 | 开启 EXECUTIONS_DATA_PRUNE 并设置保留时长 |

