前言

最近,华为把零代码智能体平台 Nexent 开源到了 AtomGit 上,归在魔擎社区(ModelEngine)名下。它的口号是"一个提示词,无限种可能",在工作台用自然语言描述需求,平台直接产出可运行的智能体,不用画流程图,也不用写代码。看到这个定位,我决定在自己的 Windows 机器上完整跑一遍部署。

跑完全程,部署脚本本身没让我操什么心,生成密钥、等 Elasticsearch 就绪、创建超管账号,它全替你做好了。

真正卡住我的是三个坑:

  • 坑一,WSL2 默认分给 Docker 的内存不够,容器一起来就被 OOM Kill;
  • 坑二,国内镜像源对高频并发请求限流,大镜像拉到一半失败;
  • 坑三,新版本的镜像 tag 还没同步到国内源,部署脚本严格按 VERSION 文件找镜像,直接 not found。

另外部署脚本必须用 bash 终端跑,这件小事官方文档也没讲透,Windows 新手容易在第一步就卡住。它算不上坑,装个软件就解决,第二节的环境准备里一并说清。

这篇就把全流程记录下来,从环境检查一直到登录验证,每一步都有命令、截图和实测输出。跟着走完,你会得到一个能在 http://localhost:3000 登录的 Nexent 实例。

一、Nexent 是什么:13 个容器的构成

先把它是谁讲清楚,免得你点进来发现找错了东西。Nexent 是一个零代码 AI 智能体生成平台,对部署决策影响最大的几个特点如下。
在这里插入图片描述

  • 多模型接入。兼容任意 OpenAI 协议的服务商,LLM、Embedding、VLM、语音识别、语音合成全覆盖,不绑定厂商。
  • 零代码生成。在工作台用自然语言描述需求,直接产出可执行的智能体,不需要画流程图。
  • 个人级知识库。支持 20 多种文档格式实时导入与智能检索,自动摘要,权限能控到单个资源。
  • MCP 工具生态。外部工具即插即用。
  • 多租户与 RBAC。租户隔离、角色权限、资源级管控,这也是默认组件里带着 Supabase 的原因。

基础设施(Elasticsearch、PostgreSQL、Redis、MinIO)、应用服务、数据处理 Worker、Supabase 账号体系,这些组件加起来一共 13 个容器,标题里"13 个容器"说的就是它。

仓库和文档先放在这里,后面会反复用到。

二、环境准备:资源自查与两个必装软件

2.1 官方资源要求

官方文档列出的资源要求如下,先对照自己的机器看一眼。

资源最低要求推荐配置
CPU4 核8 核
内存8 GiB16 GiB
磁盘40 GiB100 GiB
架构x86_64 / ARM64不限
软件Docker Engine 24+,Docker Compose v2保持更新

这张表里内存最容易被忽略。很多人的第一反应是"我机器 16 GB,肯定够"。在 Windows 上这句话不一定成立,因为 Docker 能用多少内存是 WSL2 说了算,下一节就查这件事。

2.2 先查 Docker 实际能用的内存

不用翻文档猜,直接问 Docker 最快。在 PowerShell 或 CMD 里执行下面这条命令。

docker info --format "Mem={{.MemTotal}} CPUs={{.NCPU}}"

用 docker info 查看 Docker 可用的内存与 CPU

图 1|用 docker info 查 Docker 实际可用的内存与核数(实测输出见下方)

我这次实测的输出如下。

Mem=8012890112 CPUs=8

Mem 是 Docker 能用的总内存(字节),换算过来约 7.46 GiB,CPUs 是核数。如果你用的是 Windows + Docker Desktop(WSL2 后端),这个数字大概率比你预期的物理内存小不少。小多少、怎么调,第三节(坑一)专门讲。

2.3 需要装的两个软件

Windows 新手从这里开始,整个部署只需要两样东西。

软件用途下载
Docker Desktop部署的载体,没有它一切免谈www.docker.com/products/docker-desktop
Git for Windows一次安装两样东西到手,git clone 用的 git 命令,以及部署必须的 bash 终端(还自带 openssl,部署脚本生成密钥要用它)git-scm.com/download/win

关于 Git for Windows 多说两句,这是官方文档含糊过去的地方。部署全程只会用到一条 git 命令,就是 clone 仓库,Git 本身用得不深。少不了的是它顺带装上的那个 Git Bash,因为部署脚本 deploy.sh 是 bash 脚本,官方文档只在中间提了一句"使用 Git Bash 或 WSL 执行",没有告诉 Windows 新手该先装哪个、去哪里下。

不想装 Git 也有替代路径,用 WSL2(wsl --install 装个 Ubuntu,里面自带 git 和 bash)。代价是要多做几步配置,Docker Desktop 的 WSL 集成得开,仓库还得放进 WSL 文件系统,否则 I/O 很慢。对只想先把平台跑起来的人,Git for Windows 是阻力最小的一条路。

三、坑一:把 WSL2 内存调够,Windows 上最容易翻车的一步

这是 Windows 用户最常见的翻车点,麻烦在于报错完全不指路。内存不够时,容器一起来就被 OOM Kill,日志里只有一行 Killed,看不出和内存有任何关系。

3.1 默认分配规则为什么不够

如果 C:\Users\<你的用户名>\.wslconfig 里没有写 memory= 这一项,WSL2 的默认行为如下。

把物理内存的 50% 分给虚拟机,CPU 逻辑核全部给出。

未配置 .wslconfig 时 Docker 可见的内存

图 2|未配置 .wslconfig 时,Docker 可见内存只有约 7.46 GiB,低于官方最低要求

我这台机器物理内存 16 GB,Docker 一开始能看到的只有 8012890112 字节,约 7.46 GiB。官方最低要求是 8 GiB,刚好差一点。也就是说,一台全新安装的 Windows 机器,什么都不改,也可能需要手动调高这个值。

3.2 被人为调小过的情况

还有一种更隐蔽的情况,为了不让 Docker 抢内存,主动设过上限。比如觉得 Docker Desktop 太吃内存,在 .wslconfig 里写过下面这样的配置。

[wsl2]
memory=3GB
processors=4

跑轻量应用这完全够用,跑 Nexent 就会直接 OOM。这种配置平时完全无感,直到部署一个重应用才会暴露。所以部署前第一件事是用 2.2 那条命令查当前值,别假设默认值没问题。

3.3 修改 .wslconfig 并重启验证

用记事本编辑 C:\Users\<你的用户名>\.wslconfig,没有这个文件就新建一个。我实际使用的配置如下,可以直接抄。

[wsl2]
memory=9GB         # 官方最低 8GiB,留一点余量
swap=4GB           # 交换文件放 WSL 虚拟磁盘内,避免启动阶段被 OOM Kill
processors=8       # 容器多的时候差别明显
pageReporting=true # 允许 WSL 把空闲内存还给 Windows

.wslconfig 的实际内容

图 3|记事本中的 .wslconfig:memory=9GB、swap=4GB、processors=8

改完必须完全重启 WSL,只重启 Docker Desktop 不行。

wsl --shutdown

一个容易漏的细节:WSL 被关掉后 Docker Desktop 不会立刻跟着起来,等它自动拉起或手动打开它,再执行下面的查询,否则 docker info 会连不上守护进程。

wsl --shutdown 前后 Docker 可见内存的变化

图 4|wsl --shutdown 前后对比:Mem 从 8012890112 变为 9373941760

修改是否生效,还是用 2.2 那条命令验证。两次实测输出贴在下面。

# 修改前(默认 50% 分配)
Mem=8012890112 CPUs=8      # ≈ 7.46 GiB

# wsl --shutdown 后(memory=9GB 生效)
Mem=9373941760 CPUs=8      # ≈ 8.73 GiB

同一台机器,重启 WSL 之后 Docker 可见内存从约 7.46 GiB 涨到约 8.73 GiB,正好对上 memory=9GB 的设置,差的零头是系统保留。

最后提醒一个容易混淆的点。Docker Desktop 设置界面里也有一个内存滑块,在 WSL2 后端下这个滑块改不到 WSL 的内存配额,要调还是得改 .wslconfig。

四、正式部署:一条命令与六步向导

4.1 拉代码并启动部署脚本

在准备放仓库的目录下右键,选择 Open Git Bash here。Git Bash 里粘贴用鼠标右键或 Shift+Ins。

在目标目录右键打开 Git Bash

图 5|在目标目录右键,Open Git Bash here

在 Git Bash 里依次执行三条命令。

git clone https://atomgit.com/ModelEngine/nexent.git
cd nexent
bash deploy.sh docker

clone 完成并进入部署向导

图 6|clone 完成,进入 deploy.sh 交互式向导(顶上可见 App version v2.8.0)

这里拉取的是源码。我这次 clone 一共 137,956 个对象、约 155 MiB,18 MiB/s 的速度下十几秒完成,检出 7,702 个文件。大头在后面,部署脚本会继续拉取 Docker 镜像。

4.2 耗时预期

先把预期摆出来,看到进度条长时间不动时心里有数。默认组件集下,部署会从国内源拉 12 个镜像,磁盘占用合计约 18 GB(docker images 汇总实测),压缩层下载量约 12 GB,是全流程最慢的环节。

下载速度纯拉取耗时(约)
5 MB/s(40M 宽带量级)40 分钟
10 MB/s(百兆宽带量级)20 分钟
25 MB/s(千兆/公司网络)8 分钟

我这边从配置完成到部署成功,含第五节坑二、坑三的修复与重跑,一共花了约 50 分钟。

4.3 组件选择

脚本启动后是交互式向导,依次让你选部署组件、端口策略、镜像源、沙箱模式、HTTPS 模式和数据目录,勾了 monitoring 还会多一步选监控 provider。第一步的组件界面长这样,顶上能看到 App version v2.8.0。

部署组件选择界面

图 7|组件选择界面:带 [*] 的为官方默认组件集

四个带 [*] 的是官方默认组件集(源码常量 DEPLOYMENT_COMPONENTS_DEFAULT),逐个说。

  • infrastructure 是必选项,按空格也关不掉,里面是 Elasticsearch、PostgreSQL、Redis、MinIO 这些核心依赖。
  • supabase 承载账号体系,用户、租户、登录、邀请码、权限全靠它,务必保持勾选。
  • data-process 是知识库文档解析的 Worker,不选它知识库就用不了。
  • terminal(OpenSSH 容器)和 monitoring(OpenTelemetry Collector 加链路追踪看板)按需选,本地体验可以不勾。

4.4 端口策略

默认 development,选中后回车即可。

端口策略选择

图 8|端口策略:默认选 development

development 会把调试和内部服务端口全部映射到宿主机,官方默认组件集下合计 17 个端口,部署时脚本会打印 Docker published ports 并逐个检查可用性。

用途端口
Web UI3000
后端 API(config)5010
Runtime API5014
MCP 管理与工具服务5011 / 5015
Northbound API5013
数据处理 API5012
Celery Flower(任务队列看板)5555
Elasticsearch9210 / 9310
PostgreSQL5434
Redis6379
MinIO9010 / 9011
Supabase Kong8000 / 8443
Supabase DB5436

生产环境建议选 production,只暴露 Web 的 3000 和 Northbound 的 5013(勾了 terminal 再加 2222),其余服务走 Docker 内部网络。本地体验不用纠结,development 就好。

4.5 镜像源

TUI 里三个选项对应的镜像 tag 一目了然,红箭头处是选中的 mainland。

镜像源选择

图 9|镜像源选择:红箭头处为选中的 mainland

general 走 Docker Hub,mainland 走腾讯云源,国内环境选 mainland。对应关系写在 deploy/env/image-source.mainland.env 里,贴一段感受一下。

NEXENT_IMAGE=ccr.ccs.tencentyun.com/nexent-hub/nexent:${APP_VERSION}
ELASTICSEARCH_IMAGE=elastic.m.daocloud.io/elasticsearch/elasticsearch:8.17.4
POSTGRESQL_IMAGE=docker.m.daocloud.io/postgres:15-alpine

4.6 沙箱模式

三个选项的真实差别写在源码 common.sh 的 2174 到 2196 行。

模式执行级别沙箱镜像适合
disabledlocal,无隔离跳过拉取,省约 2GB只想先看对话功能、内存极紧
lightweight(默认)docker 隔离nexent-sandbox,约 2GB首次部署选这个,智能体的代码执行能力开箱即用
fulldocker 隔离nexent-sandbox-full,更重需要沙箱内置更完整工具链时

两个帮你决策的事实。沙箱容器按需启动,智能体实际执行代码时才拉起,限 2GB 内存、1 核、30 秒超时,平时不占资源。disabled 的代价是代码执行类工具退化为本机直跑、没有隔离,源码注释把这条 local 回退标注为向后兼容行为。首次部署跟着默认 lightweight 走即可。

4.7 HTTPS 模式与数据目录

向导最后两步。HTTPS 保持默认 disabled 即可,本地体验用不上证书,要开的话选 self-signed,证书会自动生成。

HTTPS 模式选择

图 10|HTTPS 模式:本地体验保持 disabled

最后一步问数据目录 ROOT_DIR,部署数据(ES/PG/Redis/MinIO 的数据、日志、Skills)都放这里,直接回车用默认值($HOME/nexent-data)即可。

五、坑二与坑三:镜像源的两类报错

先打个预防针,坑二和坑三都出在镜像拉取环节,共同点是报错信息完全指不到原因,撞上时先别怀疑自己的操作,更不用推倒重来。走 mainland 源的读者,坑三几乎必撞。

5.1 坑二:镜像源限流

走 mainland 源拉大镜像时可能失败,报错长这样。

error from registry: 请求过于频繁,请稍后再试

这个报错没有任何上下文,看不出是哪个仓库、哪一层被限流。实际原因是国内加速链路(daocloud)对高频并发请求的频控,一个镜像几十层同时发起请求,很容易触发。

解法是改从不限流的 AWS ECR 拉取,再打回原名,让 compose 认得它。实测 supabase/postgres 走 ECR 一次成功。

docker pull public.ecr.aws/supabase/postgres:15.8.1.060
docker tag public.ecr.aws/supabase/postgres:15.8.1.060 docker.m.daocloud.io/supabase/postgres:15.8.1.060

kong 和 gotrue 我实测在原源重试一两次就能通过,不用换源。

5.2 坑三:目标 tag 还没同步到国内源

到核心服务阶段会起不来,报错如下。

Error response from daemon: failed to resolve reference
"ccr.ccs.tencentyun.com/nexent-hub/nexent:v2.8.0": not found

操作没有错,脚本也没有错。部署脚本从仓库的 VERSION 文件读版本号(当前是 v2.8.0),国内源同步这个 tag 有滞后,脚本又严格按 VERSION 找镜像,两头一夹就 not found 了。走 mainland 源的读者几乎都会在这里撞一次,属于必经步骤。

说明一下这个坑的时效性:它和 v2.8.0 强相关。如果哪天国内源把这个 tag 同步上了,直接 pull 就能成功,这一节可以整段跳过;再报 not found,回来按下面的操作处理。

解法是拉 latest 再打回版本号,五个应用镜像一条命令补齐。

ver=$(tr -d '[:space:]' < VERSION)
hub="ccr.ccs.tencentyun.com/nexent-hub"
for name in nexent nexent-web nexent-data-process nexent-mcp nexent-sandbox; do
  docker pull "$hub/$name:latest" && \
  docker tag "$hub/$name:latest" "$hub/$name:$ver" && echo "✅ $name:$ver"
done

5.3 坑二坑三一起兜底的一键脚本

嫌逐个修麻烦,把下面整段粘进 Git Bash,在仓库根目录执行,脚本会自动读 VERSION。它检查 12 个所需镜像,已有的跳过,Supabase 系镜像一开始就走不限流的 AWS ECR,ccr 镜像缺 tag 的用 latest 补齐,循环重试直到全部就绪。

ver=$(tr -d '[:space:]' < VERSION)          # 自动读出 v2.8.0
hub="ccr.ccs.tencentyun.com/nexent-hub"
dc="docker.m.daocloud.io"

images=(
  "$hub/nexent:$ver"                "$hub/nexent-web:$ver"
  "$hub/nexent-data-process:$ver"   "$hub/nexent-mcp:$ver"
  "$hub/nexent-sandbox:$ver"
  "elastic.m.daocloud.io/elasticsearch/elasticsearch:8.17.4"
  "$dc/postgres:15-alpine"   "$dc/redis:alpine"
  "$hub/minio:RELEASE.2023-12-20T01-00-02Z"
  "$dc/kong:2.8.1"   "$dc/supabase/gotrue:v2.170.0"   "$dc/supabase/postgres:15.8.1.060"
)

for round in 1 2 3; do
  missing=0
  for img in "${images[@]}"; do
    docker image inspect "$img" >/dev/null 2>&1 && continue      # 已有就跳过
    missing=$((missing+1))
    echo "⏳ [$round] 补齐 $img"

    case "$img" in
      "$dc/supabase/"*)   # 坑二:限流高发,一开始就走不限流的 AWS ECR
        ecr="public.ecr.aws/supabase/${img##*/}"
        if docker pull "$ecr" >/dev/null 2>&1; then
          docker tag "$ecr" "$img" && echo "   ✅ 已走 ECR(不限流)"; continue
        fi ;;
    esac

    if docker pull "$img" >/dev/null 2>&1; then echo "   ✅ 成功"; continue; fi   # 普通镜像原源直拉

    case "$img" in
      "$hub/"*)     # 坑三:tag 未同步 → 拉 latest 打回版本号
        base="${img##*/}"; base="${base%%:*}"
        if docker pull "$hub/$base:latest" >/dev/null 2>&1; then
          docker tag "$hub/$base:latest" "$img" && echo "   ✅ 已用 latest 补齐 tag"; continue
        fi ;;
    esac
    echo "   ⚠️ 失败,下一轮再试"
  done
  [ "$missing" -eq 0 ] && echo "🎉 全部镜像就绪" && break
  [ "$round" -lt 3 ] && echo "=== 还差 $missing 个,15 秒后重试 ===" && sleep 15
done
[ "$missing" -ne 0 ] && echo "⚠️ 仍有 $missing 个未就绪,稍等几分钟后重跑本脚本"

镜像清单对应 v2.8.0 的默认组件集。其中 Supabase 三件套(kong、gotrue、postgres)的默认 tag 写在 deploy/common/common.sh,mainland 源的覆盖值在 deploy/env/image-source.mainland.env,官方升级版本后以这两个文件为准。脚本对 Supabase 系先试 ECR,失败自动退回原源重试;kong 这类 ECR 上没有的镜像走原源重试即可,都是小镜像,限流概率低。

镜像补齐后,重新执行 bash deploy.sh docker 起剩余服务。这里有个让人安心的细节,脚本对本地已存在的镜像会打印 MCP image already exists locally 这样的提示并跳过拉取,所以重跑不会重复下载,前面拉好的都还在。

六、验证部署结果

6.1 部署脚本的完成输出

一切顺利的话,脚本最后会打印部署成功的横幅、超管账号的创建过程和访问地址。

部署完成时的终端输出

图 11|部署完成:超管账号创建成功与访问地址

把我这次实测的完成输出原样贴在下面,重跑时可以逐行对照。

✔ Core services started successfully

----------------------------

🔍 Checking if super admin user exists...
⚠️ Super admin user (suadmin@nexent.com) does not exist. Proceeding with creation...
🔨 Creating super admin user...
✔ Default super admin user has been successfully created.

    Please save the following credentials carefully.
📧 Email:    suadmin@nexent.com
🔑 Password: Nexent@123
✔ user_tenant_t schema is ready.
🔨 Inserting super admin user into user_tenant_t table...
✔ Super admin user inserted into user_tenant_t table successfully.

----------------------------

📦 Checking MCP Docker image...
🖼️ Image: ccr.ccs.tencentyun.com/nexent-hub/nexent-mcp:v2.8.0
✔ MCP image already exists locally
💡 Skipping pull, using existing image

----------------------------

📦 Checking sandbox Docker image...
🖼️ Image: ccr.ccs.tencentyun.com/nexent-hub/nexent-sandbox:v2.8.0
✔ Sandbox image already exists locally
💡 Skipping pull, using existing image

----------------------------

🎉 Deployment completed successfully!
🌐 You can now access the application at http://localhost:3000

输出里有两个细节值得注意。一是超管的邮箱和密码直接打印在终端,务必当时就存下来;二是两处 MCP image already exists locally,说明脚本对本地已有镜像会跳过拉取,第五节修复后重跑不会重复下载,靠的就是这个机制。

打印了成功还不算完,下面三步验证别省。

6.2 看一眼容器状态

一条命令数清容器。

docker ps --format "table {{.Names}}\t{{.Status}}"

默认组件集下应输出 13 行,STATUS 一列全部为 Up,和第一节的组件清单对得上。个别带健康检查的容器可能短暂显示 health: starting,等一两分钟再看。出现 Exited 或 Restarting 的,直接跳到第七节的诊断命令。

6.3 打开登录页

浏览器访问 http://localhost:3000/,出现 Nexent 的登录弹窗就是 Web 服务正常。首屏可能要等 10 到 20 秒,Next.js 首次渲染慢属于正常现象,等等再刷新。

localhost:3000 的登录页

图 12|http://localhost:3000 登录页

6.4 确认账号真的建好了

这一步很多人会漏,页面能打开不代表有账号。查一下 Supabase 的用户表,一行命令的事。

docker exec supabase-db-mini psql -U postgres -d supabase -c "SELECT email FROM auth.users;"

查询 auth.users 表确认账号已创建

图 13|auth.users 表查询结果:超管与租户管理员两个账号

我这里的实际输出如下。

         email
------------------------
 suadmin@nexent.com
 admin@nextent.com
(2 rows)

有输出就说明账号体系正常。默认会有一条 suadmin@nexent.com,我这里多出来的第二条,是部署后在平台里配置租户管理员时创建的账号。如果查询结果是空的,说明 supabase 组件没起来或者超管创建失败,回去检查组件选择,再翻一遍部署输出。

6.5 登录密码在哪

超管邮箱固定是 suadmin@nexent.com,密码以 deploy/env/.env 里的 NEXENT_SUPER_ADMIN_PASSWORD 为准,部署完成时终端也会把实际使用的密码打印出来(6.1 贴的输出里那行 Password)。用这组凭据填进登录框,能进主界面,这次部署就算完成了。

七、失败诊断:四条命令定位问题

部署没走到 6.1 那个成功横幅,或者容器起不来,先别急着推倒重来。下面四条命令按顺序跑,绝大多数问题都能定位。

# 1. 总览:哪些容器没起来(Exited / Restarting 的是哪几个)
docker ps -a --format "table {{.Names}}\t{{.Status}}"

# 2. 查容器是否被 OOM Kill(坑一的典型症状,true 说明内存还是不够)
docker inspect --format "OOMKilled={{.State.OOMKilled}} Status={{.State.Status}}" <容器名>

# 3. 看出问题的容器最后 100 行日志(容器名来自第 1 条命令)
docker logs <容器名> --tail 100

# 4. 端口被占用时(日志报 bind: address already in use)
netstat -ano | findstr :3000

对着结果对症下药。

  • OOMKilled=true:回到第三节把 memory 再调大一点,wsl --shutdown 后重跑 bash deploy.sh docker,已拉取的镜像不会重复下载。
  • 日志里是镜像拉取报错:限流或 tag 缺失,用 5.3 的一键脚本补齐镜像后重跑。
  • 端口占用:netstat 最后一列是占用进程的 PID,任务管理器里结束它,或者换个端口重跑部署。
  • 卡在等 Elasticsearch 就绪:先用第 3 条命令看 ES 容器日志,health: starting 超过五分钟多半是内存不足导致它反复重启,按第一条处理。

容器名不用记,第 1 条命令的 NAMES 列里都有。改完任何配置重跑部署脚本都是安全的,脚本对已存在的镜像和容器会复用,不会从零再来。

八、写在最后

回头看,Nexent 的部署脚本工程质量确实高。自动生成密钥、等 Elasticsearch 健康再起应用、自动创建超管、失败时给明确的错误提示,很多同类开源项目做不到这些。我花的 50 分钟里,真正用在"部署"上的不到一半。

花时间的是两件事。一件是国内镜像源的 tag 同步滞后,mainland 源解决了直连问题,但新版本 tag 的同步跟不上,部署脚本又严格按 VERSION 找镜像,两头一夹就成了必经的坑。这里给官方提个改进意见,检测到 tag 不存在时自动回退 latest 并打印提示,用户就不用对着 not found 猜原因了。另一件是部署完成离能用还有一段距离,容器全绿只是第一步,建租户、配模型这些初始化操作平台里都有引导,就不在这篇展开了。

参考资料

Logo

更多推荐