☰
群晖部署 Dify 安装包:从容器编排到内网知识库落地的完整指南
2026/10/13 1:35:53 网站建设 项目流程

简介:面向群辉NAS用户,这是一份用于在群辉设备上部署Dify应用的压缩包,大小约二十点二兆字节,内含文件总数达两千个。其中,一千三百余个Python脚本构成主要程序逻辑,三百多个JSON文件承担配置与数据交换,百余个CSS与数十个JavaScript文件用于前端界面展示,二十余个YAML及十余个Shell脚本负责容器编排与启动控制,另有Markdown说明、SQL及XML等文件辅助部署与初始化。Dify部署不仅涉及文件放置,还需处理运行环境、依赖关系、服务端口与自动启动等配置,包内文件按模块组织,便于对照调整。目前已有约一千三百六十八人学习下载,适合计划在群辉上搭建AI应用平台、熟悉NAS第三方套件安装的用户,可借助此包快速理解Dify的目录结构与关键配置,减少自行收集和整理依赖的时间,提升部署效率。

1. 群辉部署dify安装包:为什么放着台式机不用,非要用 NAS 去跑它

如果你手里有一台长期开机的群晖,又想在本地跑一套开源大模型应用平台,大概率会搜到一个关键词:群辉部署dify安装包。Dify 把「接入多个模型、搭建知识库、拖拽工作流」包装成一组 Docker 镜像,官方发布的安装包解开后就是一套完整的 docker-compose.yml 和 .env 模板,只要 NAS 能运行容器,就能把这套服务托起来。平时不用花大价钱买 GPU 机器,只要模型 API 和网络条件允许,内网里跑个人知识库、客服机器人、自动化流程都够用。这篇文章面向的是那些手里有一台 x86 架构群晖、想在内网里跑通 Dify 的从业者和折腾派,不涉及大规模生产集群,也不讨论复杂二次开发,只把部署前后最有价值的路走干净。

2. 部署前准备:判断硬件、打开容器环境、整理安装包

2.1 先从型号判断能不能跑:CPU、内存、存储三件事

群晖并不是每一台都能流畅带 Dify。社区里常见的翻车场景是:老旧 ARM 型号强行跑,镜像拉到一半就失败,或者容器起来了但 Web 页面持续白屏。Dify 当前对外发布的社区版镜像基本面向 x86_64 架构,所以我判断机器的第一标准就是 CPU 架构。白群晖里的 x86 型号,例如 DS920+、DS1520+ 这类,或者组装的黑群晖,只要 DSM 自带 Container Manager,都可以继续往下走;而 ARM 机型虽然有些镜像能靠编译转译勉强启动,但 api、worker、插件守护进程三个容器同时跑起来后,内存和 CPU 会长期处于高水位,出问题后日志排查成本也高,我一般不建议在这类设备上浪费时间。

内存方面,Dify 全家桶至少会拉起 PostgreSQL、Redis、向量库、api、worker、web 等容器,官方给的基准看起来不高,实际跑起来 8GB 内存只够轻量试用。如果你还想在同一台 NAS 上挂 Ollama 跑本地小模型,内存建议直接上 16GB 或更大,否则 worker 启动时就会因为内存不足被群晖的 OOM 机制杀掉,表现是后台任务点一下转圈半分钟然后超时。存储方面,建议单独建一个共享文件夹给 Dify,不要把容器数据散落在系统盘。我会把 Docker 根目录和项目目录都指向一个专门的数据卷,比如/volume1/dify,这样后续备份、迁移都有明确边界。

2.2 装上 Container Manager,把 SSH 打开但不依赖 root

DSM 7.2 之后,群晖官方把原来的 Docker 套件改叫 Container Manager,功能其实还是容器管理那一套。打开套件中心,搜索安装Container Manager,它同时提供图形化项目管理和底层 Docker Compose 支持。如果你还在 DSM 7.0 或更早,套件名会显示为 Docker,操作入口不同但核心能力差不多。

我习惯同时开启 SSH,不是为了炫操作,而是因为后面查看容器日志、手动执行 docker compose 命令时,终端比图形界面直观。开启方式在「控制面板 → 终端机和 SNMP → 启用 SSH 功能」,默认端口 22,按自己习惯改高端口也行。连接后先用管理员账号登录,大部分 docker 命令需要权限,可以直接用sudo执行。要注意的是,群晖的终端环境比标准 Linux 精简一些,有些命令不存在很正常,比如unzip可能没装。这时不必在系统上装一堆工具,直接用 File Station 右键解压压缩包更省事。

2.3 准备安装包:官方 Release 压缩包比“一键脚本”可靠

所谓“Dify 安装包”,最稳妥的来源是 Dify 官方 GitHub 仓库的 Release 页面,下载对应版本的 zip 或 tar.gz。解开之后,里面会有一个docker目录,这才是部署真正需要的东西:docker-compose.yaml、.env.example、以及一些子配置。网上也有不少热心人打包好的“群晖一键安装包”,但这类二次封装的安装包往往会固定某个旧版本,还可能夹带作者自己的参数调整。安装包本身不大,我仍然建议自己下载官方 Release,原因是部署完之后你手里有一份干净的原始配置,出问题时能对照官方文档排查,而不是去猜一键包里到底改了什么。

下载完成后,建议把目录整理成清晰的层级。我的固定做法是建/volume1/dify,把 Release 解压后的docker目录复制到这一层,之后所有操作都在/volume1/dify/docker下进行,路径短,方便在 SSH 里输入,也方便将来整体备份。整理目录的步骤可以这样走:

# 用管理员账号登录 SSH,切到数据卷 cd /volume1/dify # 将 Release 压缩包放到这里后解压,File Station 右键解压也可以 unzip dify-*.zip # 如果 unzip 命令不存在,用 File Station 图形界面解压到当前目录即可 # 真正要用的编排目录复制到固定工作目录,避免直接在源码夹里改动 cp -r dify-src/docker ./docker ls -l ./docker

这段命令做的事情很直接:先进入计划放数据的目录,再把 Release 包里真正用得到的 docker 编排目录复制出来固定命名。这里复制而不是直接改源码目录的原因,是为了给后续升级留个干净对照。群晖上的 docker 命令默认会从当前目录寻找 compose 文件,所以后续每次执行docker compose up -d前,记得先cd /volume1/dify/docker。如果你把项目放在其他共享文件夹,路径要相应换成自己的实际挂载点。

3. 把官方 compose 按群晖的习惯改一改:九个容器和四个必调项

3.1 官方 compose 里有哪些服务,为什么不能照抄

打开官方docker-compose.yaml后别急着执行up,先看清楚这套系统有哪些角色。社区版由多个服务组成,常见组合是:nginx负责对外入口和 TLS 终结,web提供前端页面,api处理业务 API,worker消费异步任务队列,postgres存业务数据,redis做缓存与消息队列,向量库负责知识库的向量存储和检索,还有sandbox用来隔离运行代码解释器的代码。新版本里通常还带着plugin_daemon,负责插件生命周期管理。它们之间通过网络互联,单独停掉worker不会让页面打不开,但知识库索引和文档解析这类异步任务会一直排队。

把这套 compose 直接拿到群晖上跑,多数情况下不会崩溃,但会踩几个很现实的问题。第一个是端口冲突,群晖的 DSM 管理界面自己占了 5000 和 5001,如果你把 Dify 的入口也映射到 5000,启动时 nginx 容器就会报端口被占用,表现为容器一直在 restart。第二个是数据卷路径不清晰,官方模板默认用命名卷来保存数据库和存储文件,过程中容器重启不丢数据,但如果群晖系统崩溃要迁移,命名卷查找和搬运都比较绕。第三个是资源不受限,官方 compose 里多数服务没有设置内存上限,worker 在解析大文档时可能把 NAS 内存吃满。所以我在群晖上部署时不会照抄,而是按下面三处调整。

3.2 端口、卷映射、资源上限:三个必改点

以官方 compose 为蓝本,我把关键片段摘出来改一遍。下面这段不是完整文件,只展示与群晖环境强相关的改动位置:

services: nginx: ports: - "${EXPOSE_NGINX_PORT:-18080}:80" volumes: - ./volumes/ssl:/etc/nginx/ssl api: volumes: - ./volumes/app/disk:/app/api/storage - ./volumes/pgvector:/var/lib/postgresql/data # 给容器设置内存上限,防止 worker 解析文档时拖垮整机 deploy: resources: limits: memory: 4g worker: volumes: - ./volumes/app/disk:/app/api/storage deploy: resources: limits: memory: 4g

这套片段解决三件事。第一,把 nginx 宿主机监听端口改成环境变量控制,默认值我用18080而不是 80,避免和群晖上跑了其他 Web 服务冲突,也避免路由器端口转发逻辑混乱;15000 这类端口同理,按自己内网占用情况调整就好。第二,把命名卷改成./volumes/...这样的相对目录挂载,这样数据会实实在在落在/volume1/dify/docker/volumes下,备份时直接压缩目录就行。第三,用deploy.resources.limits限制 api 和 worker 的内存,群晖系统本身还要留内存给 DSM 和磁盘缓存,不能让 Docker 把内存全部吃光。需要注意,这种deploy写法在群晖的 Container Manager 里可以被 docker compose 解析,但如果你用的是老版本 docker-compose 插件,可能不会识别deploy段,这个我在第 4 章展开说。

3.3 在 .env 模板上务必改的参数

官方安装包里的.env.example字段非常多,初看容易晕,但群晖上真正需要手动确认的就几项。先把.env.example复制为.env,再重点检查下面这组参数:

参数名作用群晖上怎么配合
SECRET_KEY会话和加密相关必须改成随机值,别用默认值
POSTGRES_PASSWORD数据库密码也改成高强度随机串
DIFY_BIND_PORTAPI 内部端口保持默认即可,除非端口冲突
EXPOSE_NGINX_PORT对外访问端口与 nginx 段保持一致,例如 18080
UNSTRUCTURED_API_URL文档解析服务地址未启用对应服务时留空,否则设成容器服务名地址

其中SECRET_KEY和POSTGRES_PASSWORD是最容易被忽略的,新手直接把.env.example改名就用,这在纯内网环境问题不大,但如果你打算把服务暴露到网络,默认密钥就是明文入口。生成密钥匙可以用群晖终端里执行这条命令:

# 生成 16 字节随机十六进制串,用作 SECRET_KEY 和数据库密码 openssl rand -hex 16

生成的字符串复制到.env对应字段即可。其他参数,比如POSTGRES_HOST、REDIS_HOST这类,在 compose 服务名不变的前提下保持默认,因为它们指向的是同一网络里的容器名,用 localhost 反而连不上。这里有个群晖常见误区:有人在.env里把DB_HOST改成127.0.0.1,觉得自己在 NAS 上能看到数据库,结果 api 容器一直报数据库连接失败。原因很简单,容器内访问不了宿主机的回环地址,要用db这类 compose 服务名。

4. 在群晖上从零把 Dify 跑起来的操作序列

4.1 方法 A:用 Container Manager 图形界面导入项目

如果你对终端不熟,群晖的 Container Manager 提供了一条相对温和的路径:在「项目」里新建项目,填一个项目名,路径选择刚才整理好的/volume1/dify或者直接选到包含 compose 文件的目录,再选择“使用现有 docker-compose.yml”。Container Manager 会自动识别目录下的docker-compose.yaml,然后开始拉取镜像并启动服务。

这个方法的好处是过程可视,容器状态、重启次数、日志都能在界面上看到。但有两个别扭的地方:一是 DSM 系统语言不同时,按钮叫法会变,比如「项目」在英文界面里是 Project,很多人找不到入口;二是图形界面启动时,如果.env文件里存在语法级错误,界面只报告“项目启动失败”,不会明确告诉你是哪一行有问题。所以无论用哪种方式,我建议同时保留 SSH 终端作为排查通道,图形界面只负责“看状态”,真正出问题时回到命令行看日志。

4.2 方法 B:SSH 终端启动,日志清晰可查

我更习惯直接走 SSH,因为docker compose up -d的输出能第一时间暴露错误,比如端口占用、镜像拉取失败、环境变量缺失。操作序列如下:

# 先进入安装包整理好的工作目录 cd /volume1/dify/docker # 从模板生成 .env,并用编辑器修改 SECRET_KEY 等参数 cp .env.example .env # 后台拉起整套服务,-d 表示在后台运行 docker compose up -d # 查看当前所有容器状态,确认没有 restart 循环 docker compose ps # 持续跟踪 api 和 worker 日志,第一次启动需要看数据库初始化是否完成 docker compose logs -f api worker web

第一命令进入工作目录,保证 compose 文件读取路径正确;第二命令生成环境变量文件,是部署前最后一步准备;第三命令才是真正的拉起动作,其中-d让容器在后台运行,不加这个参数的话一关终端服务就跟着停了。docker compose ps用来核对容器是否进入 Up 状态,如果看到某个容器一直显示 restarting,先用docker compose logs <服务名>单独看它的日志。docker compose logs -f api worker web这个命令会持续输出三个服务的日志流,-f是 follow 的意思,新日志会实时滚出来,按Ctrl+C退出但不影响容器运行。

要特别提醒一下命令区别:新版 Docker Compose 建议使用docker compose(中间有空格),旧版本习惯是docker-compose。群晖 Container Manager 附带的是新版插件,所以统一用带空格的形式就行,少打一个横杠不会出现“命令不存在”的问题。如果系统提示找不到docker compose,说明没有安装 docker-compose 插件,回到套件中心确认 Container Manager 是最新版。

4.3 第一次打开 /install 页面并配置模型供应商

等日志里不再滚动新内容,数据库初始化完成,容器状态稳定后,浏览器访问http://群晖IP:18080/install,页面一般会第一次进入设置管理员账号的引导。这里提个细节:如果页面停在初始化界面很久,不要反复刷新,先去看 api 容器日志里有没有报数据库迁移失败的错。群晖上最容易出现的问题是 postgres 容器启动慢,而 api 容器在它前面先启动了,导致连接被拒,系统等一会儿会自动重连,并不是真的死锁。

管理员账号建好后,进入 Dify 后端,第一件事不是创建应用,而是配置模型供应商。如果你想用 OpenAI 兼容接口,在「设置 → 模型供应商」里找到对应类型,填入 API 地址和密钥即可;如果你打算完全走本地,常见做法是先在 NAS 上装 Ollama,然后在 Dify 的模型供应商里选 Ollama,把 base URL 填成http://宿主机IP:11434,模型名填你拉下来的模型名称。注意不要填localhost或127.0.0.1,因为 Dify 容器访问宿主机时,需要的是群晖的内网 IP;如果 Docker 版本支持host.docker.internal,也可以直接用这个特殊域名,但群晖环境支持情况不稳定,我一般直接写内网 IP 更省事。

5. 群晖上部署 Dify 的常见问题与避坑:五条高频踩坑记录

5.1 页面总报“dify ssl错误”:多数不是证书过期,是转发配置不一致

现象:访问 Dify 时浏览器提示证书错误或者 SSL 相关告警,有时地址栏甚至跳到https://然后又回到http://,反复横跳。

原因:大多数情况并非证书真的过期,而是请求入口和实际服务出口不一致。比如你在群晖的「控制面板 → 登录门户 → 转发规则」里给 Dify 配置了转发,但转发协议是 HTTPS,而后端 Dify 只监听 HTTP;或者在.env里把EXPOSE_NGINX_PORT改成了 18080,但转发规则还指向旧端口。

解决:先把 Dify 侧统一成 HTTP,确认通过http://群晖IP:18080能正常打开;然后回到群晖转发规则里,只保留一条转发,目标端口写 18080,并确保转发规则自身的证书状态正常。如果一定要用域名和 HTTPS 访问,正确做法是让群晖转发规则完成证书终结,Dify 内部继续保持 HTTP,不要同时开启两套 TLS,否则必然出现证书错配,这是我反复踩过的坑。

5.2 知识库文档解析失败:提示 "unstructured api url is not configured for doc file processing."

现象:在知识库里上传 PDF、docx 文件,任务列表一直显示解析中,最终失败,日志里出现unstructured api url is not configured for doc file processing.这串英文,同时 API 服务日志没有其他明显异常,上传者一头雾水。

原因:Dify 社区版的文档解析流程依赖一个独立的 Unstructured 服务。默认启动的 compose 项目里并没有把该服务完整跑起来,或者.env里没有配置对应的 API 地址,导致 api 服务拿到文件后不知道往哪里送去解析。网上很多教程默认 host 环境支持完整服务,但在群晖上因为资源限制,这个组件经常处于未启用状态。

解决:先确认当前安装包里提供的docker-compose.yaml是否包含unstructured服务,如果包含,启动时把它一起带上:

# 如果官方 compose 中把 unstructured 放在 profile 里,则用 --profile 启动 docker compose --profile unstructured up -d # 重启 api 和 worker,让配置生效 docker compose restart api worker

如果你用的安装包较旧,根本没有这个服务但问题依旧,那就需要在.env里配置UNSTRUCTURED_API_URL指向自己部署的解析服务地址。这里不需要自己写容器编排,先看官方模板里是否给出了unstructured服务段;实在找不到,就不要强行上传文档,先用纯文本来建知识库,避开这个功能缺口。为了一个大文件把整机内存吃满,不值得。

5.3 工作流跑起来后“上下文超长”,任务直接中断

现象:在多轮对话或工作流里加入知识库检索结果后,任务执行到一半报上下文超长,模型请求失败。有些场景下日志里能看到 token 相关错误,实际后台里就是「上下文超长」四个字,特别在群晖这样资源有限的设备上出现频率更高。

原因:Dify 工作流会自动把检索结果、系统提示词和历史会话拼进一次模型调用,当你把 chunk 设置得太大、检索结果条数太多,一次提示词可能超过模型窗口限制。群晖内存有限,模型供应商又是远端 API 时,请求体过大也会让 worker 处理时间变长,进而再次触发超时。

解决:进入知识库的检索设置,把召回条数从默认的多条调低,比如先试 3 条,同时把 chunk 大小控制在 500 到 800 字之间。另外在工作流最前面加一个「问题分类」节点,把不相关的内容直接拦掉,比全都塞进上下文更省 token。模型选择上,如果你接的是支持长上下文的模型,把模型窗口参数调大即可;如果用的是本地 Ollama 小模型,它本身窗口就小,就只能从削减上下文入手。这个场景本质上是资源规划问题,群晖不是性能怪,工作流设计得越贪心,任务越容易翻车。

5.4 黑群辉ipv6远程访问配置后,外网还是连不上 Dify

现象:家里宽带有 IPv6,NAS 端也设置了 DDNS,但从外部网络访问 Dify 的 IPV6 地址时经常打不开,手机上倒是偶尔能成,换网络就不行。

原因:IPv6 地址本身通常带有随机临时地址,并不是固定不变的;群晖的转发规则和防火墙默认只会将入口流量转发给 IPv4 的端口映射,不会自动处理 IPv6 路由。更隐蔽的一个原因是,路由器上虽然开启了 IPv6,但防火墙默认拦截了入站端口,即使 NAS 拿到了 IPv6 地址,外部请求也进不来。

解决:在 DSM 的「控制面板 → 网络 → IPv6」里,确认 NAS 已获得全局 IPv6 地址;再去路由器后台放行对应 TCP 端口,而不是只放行 DSM 的 5000 端口。DDNS 层面选择支持 IPv6 AAAA 记录更新的服务商,否则域名解析只返回 IPv4 地址,外部网永远找不到你的机器。做完这些后,从外网访问http://域名:18080测试。注意不要把完整的 Dify 管理页暴露在公网上,建议只在路由器上暴露一个窄端口做转发,Dify 自身不要开管理员自动注册,否则就相当于把后台交出去了。

5.5 升级或迁移后“旧数据丢失”,应用列表变空

现象:为了给 Dify 安装包升级版本,重新拉镜像后启动,发现以前创建的应用、知识库全没影了,或者插件市场一直转圈,之前装好的插件全部消失。

原因:大多数人升级时直接执行docker compose pull和docker compose up -d,看起来没问题,但如果你的卷映射发生过改动,比如第一次安装用命名卷,第二次调整 compose 时改成了./volumes,PostgreSQL 其实扫到了完全空的数据目录,自然建出全新的空库。还有一种情况是之前升级过,旧的 postgres 数据卷还在项目里占着位置,容器重名导致启动异常,界面表现为“数据库连接失败”。

解决:升级前一定要记录当前 compose 文件和.env,并执行一次完整目录备份:把/volume1/dify/docker压缩保存,同时用docker compose down停掉整套服务,再拉新镜像。要是你已经升级完发现应用列表空了,不要继续创建新应用覆盖数据,先停容器,检查旧卷目录是否还在,确认备份里有没有postgres数据目录。如果有,把新卷路径改回旧路径,再启动一次,一般数据能找回来。这里我的经验是:不要相信群晖的 Snapshot,容器数据库在写入时快照一致性并不总是可靠,文件级压缩备份才是后悔药。

6. 安装完成后建议尽快做的三组验证:别让部署停在“页面能打开”

第一组验证是基础对话链路。新建一个空白应用,关掉知识库,直接向模型发一条“你好”。这一步能确认 web、api、模型供应商三者连通,很多部署停在“登录成功但应用发不了消息”,就是模型供应商配置有问题。如果这里失败,优先看 api 日志,通不过的情况里一半是 API 地址写错,一半是密钥被误填了空格。

第二组验证走 API。在应用管理里申请 API 密钥,然后在群晖终端或者任意一台内网机器上发一个最小请求:

# 用 API 密钥调用对话接口,response_mode 选阻塞式便于直接看结果 curl -X POST 'http://群晖IP:18080/v1/chat-messages' \ -H "Authorization: Bearer app-这里填你的密钥" \ -H 'Content-Type: application/json' \ -d '{"inputs":{},"query":"你好,测试一下","response_mode":"blocking","user":"verify"}'

这条 curl 如果返回带answer字段的 JSON,说明整套后端链路真的通了,而不只是页面能打开。response_mode用了blocking,表示等待模型完整返回再响应,请求体里user随意填,但必须存在。这个验证的好处是,将来如果你要做外部系统接入,可以直接复用同样的鉴权和 URL 格式。

第三组验证是知识库完整流程。上传一份大于 20 页的 PDF,让它完成解析、分段、召回到最终回答的全流程。这一步会暴露出 5.2 里讲的文档解析问题,也能观察群晖内存在分割大文档时是否吃紧。我一般会刻意选那种带目录的书签 PDF,因为这类文件最容易触发解析格式问题。

部署完成后我还有一个习惯:把部署当天使用的安装包版本号、.env里改过哪些参数、compose 文件做了哪些修改,全部记成一个简短备忘录,放在/volume1/dify目录下。这样一来,两个月后再升级时,打开备忘录就知道上次动了什么,不会再踩一遍自己挖的坑。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询