前阵子在一台Ubuntu 24.04的云主机上部署n8n旁边朋友对它的要求很一致中文界面、能长期稳定跑。官方镜像本身自带多语言支持但网上很多教程直接把语言、时区、加密密钥这几个点绕过去了结果就是你看着界面是英文、计划任务总差8小时、重启容器后历史数据打不开。这篇把我在实操里确认过的选型、配置和排错过程完整过一遍内容偏实战不是文档复读。先给没接触过的朋友一句话介绍n8n是一个开源的工作流自动化平台用来把不同服务串起来。比如收到一个表单就往数据库写一条记录定时抓网页内容再推到群里调大模型接口处理文本后写回表格这些流程都能在网页里用可视化方式编排。部署在自己服务器上数据不出内网。适合自托管爱好者、需要打通内部系统的开发者以及不想为每个自动化场景单独付订阅费的个人或小团队。下面默认你已经有一台能远程登录的Ubuntu 24.04机器并且知道什么是SSH和基本命令。1. 为什么我选Docker Compose而不是“一条命令跑起来”很多人第一次接触n8n看到官网上写着docker run -it --rm --name n8n -p 5678:5678 n8nio/n8n就以为三步算部署完成。这条命令拿来体验没问题但真要长期用你会发现命令行里塞了一堆参数重启后容器丢了数据落在哪里也说不清楚。所以我一开始就直接用Docker Compose把环境、数据、端口、语言全部写进一个文件里。1.1 四种部署方式的横向对比我简单对比过几类常见部署思路表格里的评价基于我实际折腾后的体会部署方式上手速度长期维护数据可迁移性我的评价Node.js 直接跑最快依赖环境容易乱升级麻烦一般适合临时体验不适合当服务docker run 单容器快参数全在命令行里不直观取决于你挂载的数据卷适合验证镜像Docker Compose中等配置集中在一个文件可版本管理很直接生产环境首选各类面板或一键脚本快面板本身也在占用系统资源绑定环境图省事可以后续问题多直跑那个方案我试过一次npm 全局装 n8n看着省事等你想升级或者换机器依赖冲突、权限残留、进程守护全都要重新弄一遍。docker run 比直跑好一点但每次改一个环境变量就得把命令行翻出来改时间一长自己也记不住当时到底设了哪些参数。1.2 Compose方案最让我放心的地方选 Docker Compose 有四个具体原因。第一是可复制。整个部署状态就是一个docker-compose.yml文件加一个数据目录新机器上只需要把这两个东西拷过去docker compose up -d就能起一个完全一样的环境。第二是环境隔离n8n 跑在容器里系统库里装了什么、Python 版本是多少都不影响宿主机对带 Node.js、Python 的混合环境尤其友好。第三是升级干净官方镜像一发新版改一下版本号再docker compose pull docker compose up -d回滚也只需要把版本号改回去。第四是排错集中日志用docker compose logs看问题基本都集中在配置和数据目录上不用满系统翻文件。这套思路也符合 n8n 官方文档的默认姿势。后面在社区提问别人让你贴 compose 配置你至少能以一个标准格式和别人交流。2. Ubuntu 24.04环境准备装好Docker只是开始在Ubuntu 24.04上装Docker不算难但有一个地方容易栽系统自带的docker.io包和你从 Docker 官方源装的docker-ce会打架。Ubuntu 仓库里的 docker 版本通常比官方源落后而且不一定带新的docker composev2 插件。我建议直接把官方源作为标准路线省得之后各种“命令不存在”的报错。2.1 安装Docker引擎时我选的路线我走的完整安装流程如下直接在 SSH 终端里执行# 如果之前装过系统自带的docker先清理干净避免版本冲突 sudo apt remove -y docker.io docker-doc docker-compose docker-compose-v2 docker-ce docker-ce-cli containerd runc sudo apt autoremove -y # 添加Docker官方软件源 sudo apt update sudo apt install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc /dev/null sudo chmod ar /etc/apt/keyrings/docker.asc echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo \$VERSION_CODENAME\) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl enable --now docker # 验证Compose插件是否可用 docker compose version最后一个命令如果能正常输出版本号说明docker compose这个新式命令已经就绪。注意新式命令是docker compose中间有空格老式的docker-compose是另一个独立命令不要搞混。2.2 免 sudo 操作 Docker用户组配置默认情况下直接执行docker ps会提示权限不足很多人第一反应是给 docker 命令加 sudo。加 sudo 能用但每次都要输密码很烦而且后续写脚本、配自动化也不方便。标准做法是把自己加入 docker 用户组sudo usermod -aG docker $USER修改用户组之后需要重新登录 SSH 或执行newgrp docker让组生效。这里有两个额外提醒别图省事直接chmod 777 /var/run/docker.sockdocker 组用户实际上等同于拥有 root 权限能对宿主机做很多操作这个组的成员只能放可信账号。如果你是用普通用户创建的 SSH 会话加了组之后当前会话未必马上生效重新断开再登录最稳妥。2.3 镜像加速与Docker数据目录迁移国内网络拉取 Docker Hub 镜像经常超时这是部署过程中最容易被忽略的环节。解决方案是在/etc/docker/daemon.json里配置镜像加速地址一般你的云服务商控制台都会提供专属加速地址不同厂商格式不同直接复制到配置里即可{ registry-mirrors: [https://你的云服务商控制台提供的加速地址], data-root: /data/docker }这里我还加了一个>sudo systemctl stop docker sudo rsync -avz /var/lib/docker/ /data/docker/ sudo systemctl start docker同步完确认能正常启动再决定要不要清空/var/lib/docker旧文件建议先保留一段时间。3. 生产环境用的Compose文件逐项说清楚到了核心部分。下面这份docker-compose.yml是我实际在 Ubuntu 24.04 上部署 n8n 用的配置结合了中文界面、时区、持久化和密钥管理。你可以直接复制只需要改 IP、密钥和数据目录路径。3.1 完整配置和生成密钥的命令先把配置贴出来version: 3.8 services: n8n: image: docker.io/n8nio/n8n:latest container_name: n8n restart: unless-stopped ports: - 5678:5678 environment: - GENERIC_TIMEZONEAsia/Shanghai - TZAsia/Shanghai - N8N_PORT5678 - N8N_HOST你的服务器IP或域名 - N8N_PROTOCOLhttp - N8N_DEFAULT_LOCALEzh - N8N_ENCRYPTION_KEY第一串随机字符 - N8N_USER_MANAGEMENT_JWT_SECRET第二串随机字符 - LANGC.UTF-8 volumes: - ./n8n_data:/home/node/.n8n部署之前先创建数据目录并赋予正确权限mkdir -p n8n_data sudo chown -R 1000:1000 n8n_data然后生成两串密钥openssl rand -hex 16 openssl rand -hex 24把两串结果分别填到上面的N8N_ENCRYPTION_KEY和N8N_USER_MANAGEMENT_JWT_SECRET。最后启动docker compose up -d首次启动会拉取镜像等一会儿访问http://你的服务器IP:5678就能看到 n8n 的欢迎页。3.2 环境变量里真正影响运行的几个很多人看到一堆环境变量不知道哪个该动我按重要程度排一下TZ和GENERIC_TIMEZONE都设成Asia/Shanghai。不设的话n8n 内部的计划任务、日志时间戳、邮件模板时间全按 UTC 走北京时间会相差8小时。N8N_HOST这是对外访问的地址。如果你直接填localhost那么 n8n 里生成的 Webhook 回调地址会变成localhost第三方服务根本回调不进来。实际部署时改成服务器的公网 IP 或解析好的域名。N8N_PORT和N8N_PROTOCOL端口默认 5678协议如果是 HTTP 就写http将来接了 HTTPS 反向代理再改成https。N8N_DEFAULT_LOCALEzh让新用户默认使用中文界面。N8N_ENCRYPTION_KEY和N8N_USER_MANAGEMENT_JWT_SECRET这两个是你最该手动设置的密钥。如果不设n8n 会自动生成并保存到数据目录但一旦你重建容器或者把数据目录恢复到新机器上自动生成的密钥对不上历史凭据就会解密失败。手动固定一份并备份到密码管理器里基本就不会遇到这种问题。N8N_PERSONALIZATION_ENABLEDfalse这个不是必填但设置为 false 可以关掉启动时的个性化引导问卷省得每次新装都要多点几下。3.3 数据目录权限最常见的Permission denied来源n8n 官方镜像内部默认以node用户运行uid 是 1000不是 root。如果你用 bind mount 方式把宿主机目录挂到容器里这个目录的属主必须是 uid 1000否则容器启动后写不进数据库文件日志里会报 EACCES 或 Permission denied。所以上面那步chown -R 1000:1000 n8n_data非常关键。如果你创建的目录本身属主就是你自己而你的 uid 恰好是 1000那可以跳过但通常云主机登录用户是 root 或 uid 1001所以这步别省。数据映射到/home/node/.n8n之后整个 n8n 的配置、SQLite 数据库、密钥文件都在这个目录里。以后备份只需要把这个目录打包升级前用它做回滚非常方便。4. 中文版n8n语言、时区、编码一次配齐“中文版”这三个字容易让人误解以为有专门的中文安装包。事实上n8n 官方镜像就是全语言包所谓的中文版就是正确设置语言、时区和编码环境变量之后的产物。没有额外镜像没有特殊渠道就两个配置开关加一点运行环境调整。4.1 “中文版”不是特制镜像是两个配置开关界面中文化有两个层级第一个层级是N8N_DEFAULT_LOCALEzh它决定新创建的用户默认语言是简体中文。第二个层级是用户个人设置如果你用默认管理员账号登录需要在左下角头像菜单里找到 Settings再找 Display Language选择“简体中文”。两个层级配合使用团队里不同成员也可以各自选偏好的语言互不影响。还有一个细节容易被忽略如果浏览器本身首选语言是英文n8n 部分页面可能优先显示英文。遇到这种情况到用户设置里强制切一次“简体中文”刷新后就固定下来了。4.2 页面切换和翻译不完整的现状n8n 的汉化由社区贡献者维护版本迭代比较快的时候一部分新功能、新节点的字段说明还没来得及翻译界面会出现中英混杂的情况。这不算 bug也不代表你没配置成功。核心菜单、节点名称、字段标签大部分已经是中文小部分英文主要是社区翻译进度问题不影响使用。我自己在几个版本上都观察过编辑器画布、节点库、触发器描述、错误提示这些高频区域中文覆盖率已经很高了。真正可能全是英文的是新发布不到一两周的小众集成节点以及个别错误日志。只要你是用最新镜像把N8N_DEFAULT_LOCALEzh设好日常使用基本没有语言障碍。4.3 时区直接决定计划任务的“准点”中文界面配好之后最容易暴露的是时间问题。n8n 里所有按 cron 表达式或固定间隔触发的计划任务默认读取的是容器时区。你如果不设置TZAsia/Shanghai容器默认 UTC在北京时间已经是下午四点的时候n8n 依然按上午八点去触发任务。我早期踩过一个很实际的坑设置了一个每天 9 点把报表推送到群里的流程第二天发现 9 点没发反而下午 5 点发了。排查半天才发现是 UTC 和北京时间差了 8 小时调度时间被整个平移了。所以 compose 文件里GENERIC_TIMEZONEAsia/Shanghai和TZAsia/Shanghai两个都写上保证日志、邮件时间戳和计划任务全部对齐。如果你工作流里涉及数据库时间字段也要留意数据库连接串里有没有配置时区。容器时区只管 n8n 自身运行时的new Date()第三方数据库默认时区跟它没有必然关系两边的时区不一致会产生新的偏差。4.4 容器编码和中文文本处理中文界面的另一边是中文数据。n8n 官方镜像默认的 locale 是C.UTF-8也就是说容器本身支持 UTF-8 字符集能正确处理中文。你在 compose 里写LANGC.UTF-8就够了不需要专门生成zh_CN.UTF-8locale也不建议为了界面语言去自定义镜像日常使用没必要。真正容易出问题的地方在 Code 节点。如果你用 Python 节点处理中文内容Node 的执行环境里 Python 脚本默认 stdout 编码可能不是 UTF-8打印或者返回中文时偶尔会出现乱码。稳妥的做法是在脚本开头显式指定编码import sys sys.stdout.reconfigure(encodingutf-8)Shell 脚本也是同理尽量在脚本开头声明export LANGC.UTF-8避免管道传输过程中把中文内容按 ASCII 解析。这些细节在中文环境下特别重要一旦出现乱码很多人第一反应是代码逻辑问题其实是编码环境没有锁定。5. 部署完最容易踩的四个坑完整排查链路即便配置照着上面写了部署后也可能会遇到一些环境相关的问题。下面四个坑是我在实际操作里真正遇到的按照“现象-排查-解决”的思路写方便你出了问题按步骤定位。5.1 坑端口映射正确浏览器就是进不去现象是容器已经正常启动docker ps能看到端口映射SSH 到服务器上执行curl http://127.0.0.1:5678也有响应但你从本地浏览器访问公网地址就是超时。排查链路# 第一步确认容器确实在监听 ss -tlnp | grep 5678 # 第二步在服务器本机验证业务是否正常 curl http://127.0.0.1:5678 # 第三步检查Ubuntu防火墙 sudo ufw status verbose大概率是防火墙没有放行 5678 端口执行sudo ufw allow 5678/tcp如果你用的是云服务器还有第四步去云控制台的安全组或防火墙规则里确认入方向放行了 5678。这一步非常容易漏因为服务器的 ufw 和安全组是两个独立的地方任何一个没放行外部流量都进不来。我见过不止一个人在本机 ufw 放行后仍然超时最后发现是安全组规则里压根没加端口。5.2 坑重建容器之后历史工作流打不开凭据全部失效现象是第一次部署完一切正常后来为了升级执行了docker compose down docker compose up -d启动后登录没问题但点开历史工作流会报错或者连接第三方服务的凭据全部失效。根因基本都出在加密密钥和数据目录上。n8n 会把数据库里保存的 API Key、密码、OAuth Token 等敏感字段用N8N_ENCRYPTION_KEY加密。如果你没有手动设置这个密钥n8n 会自动生成一份并存在数据目录里。如果重建容器时数据目录挂载路径写错了或者干脆没用数据卷那么自动生成的密钥就丢了历史数据自然解密不了。排查时先确认数据目录确实存在内容ls -l n8n_data/ docker compose exec n8n ls -l /home/node/.n8n然后回到 compose 文件确认N8N_ENCRYPTION_KEY和N8N_USER_MANAGEMENT_JWT_SECRET已经手动写好。这也是为什么我强调把密钥固定下来并备份到密码管理器因为自动生成的随机字符串只存在于数据目录里一旦目录丢失就永远找不回来。5.3 坑docker compose命令不存在现象是你按照网上的文章执行docker compose up -d结果提示docker: compose is not a docker command原因通常是系统安装的只是docker.io包没有安装 Compose v2 插件。Ubuntu 24.04 不同安装源的包名有差异如果通过apt install docker.io安装需要再安装专门的 Compose 插件包# 用 apt 搜一下本机可用的 compose 插件包名 apt search docker-compose sudo apt install docker-compose-v2如果你走的是 Docker 官方源上面第 2 章安装流程里已经包含了docker-compose-plugin装完就会自带docker compose命令。还有一点值得注意老式docker-compose带横线是独立的 Python 版 v1 命令和新式docker compose带空格是两套东西配置语法有差异尽量统一使用新式命令。5.4 坑容器启动后反复退出状态永远是Restarting现象是docker compose up -d之后容器没有稳定运行几十秒后状态变成 Restarting 或 Exited。先看日志docker logs n8n --tail 50如果日志末尾出现Killed或者退出码是 137基本就是内存不够进程被系统 OOM Killer 干掉了。n8n 默认是 Node.js 进程空闲状态下一般会占用 500MB 到 800MB 内存随着工作流数量增加还会往上涨。如果机器内存本来就小或者同时跑了数据库、其他服务触发 OOM 并不奇怪。临时验证方法是用free -h看一下宿主机剩余内存。长期解决方案有两个第一给容器设置内存上限避免无限膨胀services: n8n: mem_limit: 2g第二为服务器增加 swap 空间。对轻量使用场景2GB swap 基本够用。设置 mem_limit 的意义不只是限制资源更重要的是让容器在内存接近上限时能被 Docker 主动限制而不是直接拖垮整个宿主机的其他服务。最后想说的两句经验这套流程走下来从空系统到能打开中文界面顺利的话十几分钟真正的成本都在环境变量和数据目录上。我最初踩得最狠的一个坑是没有固定加密密钥导致一次升级后所有凭据报废从那以后我每次部署都会把N8N_ENCRYPTION_KEY和N8N_USER_MANAGEMENT_JWT_SECRET先写进密码管理器再把 compose 文件里的占位符替换掉数据目录用 tar 打包备份。后来养成了习惯每次升级前先备份 n8n_data 目录再改镜像版本号。这样即使新版本有兼容问题也能一分钟内回到旧版本。如果你也想长期跑 n8n这两条习惯比任何高级配置都值钱。
阅读完成 · 觉得有帮助?