n8n Docker 部署教程:从零搭建第一个自动化工作流

n8n 是一款 fair-code 模式的工作流自动化平台,可以用可视化画布拼装节点,也能插入 JavaScript、Python 代码片段,覆盖 1500+ 集成。对于想把自动化能力放在自己服务器上、又不想被 SaaS 绑定的团队来说,Docker 部署是最常见的入口。本文从零开始,用 Docker Compose 搭建一个带 PostgreSQL 的 n8n 实例,并完成第一个 RSS → 邮件的工作流。

n8n 可视化画布的总览界面,多个节点通过连线串联-1

准备工作

开始之前,需要确认三件事:

  • Docker 与 Docker Compose:推荐使用较新版本的 Docker(自带 docker compose 子命令,老版本才需要单独的 docker-compose 二进制)。可以用 docker --versiondocker compose version 验证。
  • 内存:n8n 本身是 Node.js 应用,单实例最低建议 1GB 内存。如果跑大型工作流或多并发执行,建议 2GB 及以上。
  • 端口:默认使用 5678,确保宿主机该端口可用;如果被占用,可以改成别的端口(比如 5688)。

宿主机操作系统没有强制要求,Linux、macOS、Windows(WSL2)都可以跑通。下面以 Linux 为例演示,命令在 macOS 上基本一致。

编写 docker-compose.yml

为了让数据真正”活下来”,建议用 PostgreSQL 替换默认的 SQLite 数据库,并把数据目录挂载到宿主机。这样即使容器被删,重建也不会丢东西。

新建一个目录,比如 ~/n8n-deploy,进入后创建 docker-compose.yml

version: "3.8"

services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=n8npass
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 10s
timeout: 5s
retries: 5

n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
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=n8npass
- GENERIC_TIMEZONE=Asia/Shanghai
- TZ=Asia/Shanghai
- N8N_HOST=localhost
- N8N_PORT=5678
- N8N_PROTOCOL=http
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy

volumes:
postgres_data:
n8n_data:

几个关键点说明:

  • image: docker.n8n.io/n8nio/n8n 是官方镜像源,与 README 中的 docker run 命令保持一致。
  • GENERIC_TIMEZONETZ 设为 Asia/Shanghai,避免节点里出现”今天 8 点跑成昨天 16 点”这种时区错乱。
  • volumes: 部分把所有可变数据挂到命名卷,方便后续备份与迁移。
  • depends_on 加了健康检查条件,避免数据库还没准备好 n8n 就启动失败。
    https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png

    ### 启动与初始化

docker-compose.yml 所在目录执行:

docker compose up -d

-d 表示后台运行。第一次会拉取镜像,时间稍长。可以用 docker compose ps 查看运行状态,看到两个服务的 State 都是 runningpostgres 健康检查通过就算成功。

打开浏览器访问 http://localhost:5678,第一次进入会要求设置一个拥有者账号(owner account)。这一步建议用一个强密码,因为这个账号拥有所有权限。之后可以再邀请其他用户。

如果一切顺利,就能看到 n8n 的画布界面,左侧是节点面板,中间是工作流编辑区,右侧是节点配置面板。

n8n-screenshot.png

### 数据持久化与备份

n8n 的所有重要数据都集中在挂载卷里:

  • n8n_data:工作流定义、凭证加密信息、执行历史等。
  • postgres_data:使用 PostgreSQL 时的数据库文件(如果用 SQLite,则全部在 n8n_data 内)。

定期备份这两份卷就够了。可以用一个简单的脚本:

#!/bin/bash
BACKUP_DIR=~/n8n-backups/$(date +%F)
mkdir -p "$BACKUP_DIR"

docker run --rm \
-v n8n-deploy_postgres_data:/source:ro \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/postgres_data.tar.gz -C /source .

docker run --rm \
-v n8n-deploy_n8n_data:/source:ro \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/n8n_data.tar.gz -C /source .

卷名 n8n-deploy_postgres_data 这种带前缀的格式,是 Docker Compose 自动生成的,格式为 _。如果项目目录改了名字,这里也要相应修改,建议把项目目录直接放在一个稳定路径下,比如 /opt/n8n

恢复时把 tar 包解开回原卷即可。需要迁移到新服务器,只要把这两个卷的内容搬过去,就能保留全部工作流和凭证。

反向代理与 HTTPS

直接用 5678 端口对外服务在生产环境不太合适:要么端口号奇怪,要么没有 HTTPS。前端放一层 Nginx 或 Caddy 是更稳妥的做法。

Nginx 示例

server {
listen 80;
server_name n8n.example.com;

location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_buffering off;
client_max_body_size 50m;
}
}

proxy_buffering offUpgrade/Connection 头是 n8n 文档明确强调的——它依赖 SSE/WebSocket 推送执行日志,开启缓冲会导致节点看起来”卡住”。

Caddy 示例

Caddy 自动申请证书,配置更短:

n8n.example.com {
reverse_proxy 127.0.0.1:5678 {
header_up Host {host}
header_up X-Real-IP {remote_addr}
header_up X-Forwarded-For {remote_addrs}
header_up X-Forwarded-Proto https
}
}

同时记得把 docker-compose.yml 里的 N8N_PROTOCOL 改成 https,并把 N8N_HOST 改成实际域名,否则触发器回调、OAuth 跳转会出现”地址错配”的问题。

### 第一个工作流:定时抓 RSS 发邮件

接下来做一个真正能跑的小工作流:每小时抓取指定 RSS 源,发现新条目就通过 SMTP 发邮件汇总。用它把整个”画布 + 凭证 + 触发器 + 条件判断”链路串起来。

新建工作流,按顺序添加以下节点:

  1. Schedule Trigger:设置 ModeEvery Hour,点击 Cron 模式可自定义更复杂的规则。
  2. RSS Feed Read:在 URL 填入想要订阅的 RSS 地址,比如某个博客的 feed。
  3. Code 节点(可选):用一段 JS 把上一次的”已发送标题”和这次的标题对比,过滤掉已发送项。也可以用 n8n 内置的 Remove Duplicates 节点按 URL 去重,省事一些。
  4. Send Email:选择 SMTP 凭证(首次使用时点 Create New Credential,填入发件邮箱的 SMTP 信息;端口和授权码需要到对应邮箱服务商的设置里查找,建议以官方文档为准)。
  5. 在节点之间画好连线,把 RSS 节点输出的 items[] 接到 Code / 邮件节点的输入。

点击右上角 Save,再点 Execute Workflow 手动跑一次,看到收件箱收到邮件就算成功。最后把右上角的开关切到 Active,工作流就会按 Schedule 自动运行。

### 常见坑与排查

实际部署中几个容易踩的坑:

  • 时区错位:默认 UTC 跑出来的”每天 8 点”在国内是下午 4 点。务必在 docker-compose.yml 里设置 GENERIC_TIMEZONETZ,重启后生效。
  • 用户权限问题:n8n 容器内默认以 node 用户运行,挂载到宿主机的目录如果权限太严会导致启动失败。如果必须用 root,可以在 environment 里加 N8N_USER_FOLDER 指定可写目录,或者放宽宿主机目录权限。
  • 大工作流内存飙升:跑批量处理、调用大模型时,Node.js 堆内存可能膨胀。可以加环境变量 NODE_OPTIONS=--max-old-space-size=2048 限制上限,再相应提高容器内存限制(deploy.resources.limits.memory)。
  • 凭证丢失:备份只复制了卷文件,但忘了备份 n8n_data 里的加密密钥(config 文件)。换服务器后即使恢复了数据,凭证依然解不开——必须同时迁移密钥文件。
  • Webhook 回调失败:很多节点(如 Telegram、GitHub)需要公网回调地址。如果只在内网访问,触发器测试通过但生产环境收不到消息,这时就要靠上面提到的反向代理 + HTTPS 来打通。

部署完成后,n8n 的玩法就完全打开了:从简单的”表单提交 → 写库”,到”AI Agent 拉取文档 → 总结 → 推送到飞书”,都靠同一个画布拼接。建议先从无代码的官方模板入手,把流程跑通再考虑自定义代码节点。需要更深入的配置细节(队列模式、执行模式、多实例),可以查看 n8n 官方文档,那里覆盖了从安装到生产调优的完整链路。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。