☰
Dify私有化部署实战:Linux服务器+Docker Compose指南
2026/10/10 16:49:41 网站建设 项目流程

开头从一次真实的部署说起。有段时间我在Linux服务器上反复折腾容器应用,最头疼的还不是容器本身,而是应用之间的依赖关系、初始化顺序、数据卷到底应该怎么挂。后来接触到一个叫 Dify 的开源项目,发现它的定位很有意思:不是普通聊天机器人,而是把大模型应用开发里的提示词编排、知识库检索、Agent 工作流、模型管理等环节全部可视化,部署形式也是我熟悉的 Docker 容器。于是我用一台 Linux 服务器,通过 Docker Compose 把整套 Dify 拉起来,前后整理了不少配置细节和踩坑记录,今天一次性写出来。

这东西适合谁参考?如果你正在做 LLM 应用的快速原型,或者想把企业内部的知识库助手、客服问答机器人落地到自有服务器,又不想从零写编排代码,那么 Dify 就是你需要的平台。它本身支持私有化部署,数据在你自己手里,模型 API 可以接各家厂商,也可以接本地模型服务。无论你是后端开发、运维还是产品侧的技术负责人,只要熟悉基本 Linux 命令和 Docker 操作,照着下面的步骤走,基本能在一小时内把整套平台跑起来。

1. 整体设计思路与部署架构拆解

1.1 Dify 到底解决了什么问题

先理解 Dify 在技术栈里的位置。它属于大模型应用开发平台,底层还是调用外部大模型 API 或本地模型服务,但上层把业务方最常做的事封装成了可拖拽、可配置的积木。比如你想做一个带知识库的问答机器人,传统做法是写代码搭向量数据库、做文档切片、写召回逻辑、设计 Prompt 模板、处理会话上下文,再写一套管理后台。用 Dify 之后,这些能力以现成模块的形式出现在界面上,你只需要配置知识库来源、选择模型、编排工作流即可。

从部署者的角度看,Dify 不是一个单体程序,而是一组相互协作的服务集合。它包含 Web 前端、API 服务、异步任务 Worker、PostgreSQL 数据库、Redis 缓存、模型请求代理、安全沙箱等组件。这种架构天然适合容器化:每个组件是独立镜像,通过 Docker Compose 统一编排,启动顺序和数据卷都在一份配置里定义好。这也是我选择在 Linux 服务器上用 Docker 部署的核心理由。

1.2 为什么选用 Linux 服务器加 Docker 组合

先说 Linux 服务器。Dify 官方提供的部署方式里,最顺手的其实就是 Linux 加 Docker Compose。Windows 上虽然有 Docker Desktop,但 mount 路径、权限、换行符、端口监听这些细节容易出问题;macOS 本地跑跑没问题,但长期作为服务运行还是 Linux 更省心。Linux 环境下 systemd 管理方便,日志清理、开机自启、防火墙策略都更成熟。

再说 Docker。容器化带来的最大好处是可复现性。同一份 Compose 文件,在测试服务器上验证过之后,生产环境直接照搬,只要系统版本和端口不冲突,结果基本一样。另一个好处是隔离,Dify 依赖的 PostgreSQL 和 Redis 版本是自己要求的,如果直接装在宿主机上,很可能和服务器里已有的 MySQL、Redis 实例产生版本冲突。用容器之后,每个依赖都被隔离在独立环境里,升级 Dify 时只需要换镜像,不需要污染宿主机环境。

1.3 部署架构全景图

这套架构可以拆成三层来看。最外层是接入层,一般用 Nginx 或 Caddy 对外提供 HTTPS 访问;中间是 Dify 的核心服务群,包括 API 服务、Web 前端、Worker 异步任务、SSRF 代理、Sandbox;底层是基础设施服务,包括 PostgreSQL 和 Redis,以及可选的向量数据库。

需要注意的是,生产环境下千万不要直接把 PostgreSQL 和 Redis 的端口暴露到公网。它们只需要在 Docker 内网里被 Dify 各服务访问即可。对外真正需要暴露的是 Web 端口和 API 端口,建议通过宿主机的 Nginx 反代,而不是直接把容器端口裸奔出去。

2. 部署前的环境准备

2.1 服务器配置要求

先给出我实测过的配置底线。如果只是测试环境,2 核 CPU、4G 内存、40G 磁盘基本能跑,但体验会比较紧,尤其是首次启动时多个容器同时初始化,内存可能瞬间冲到 3G 以上。我建议个人使用或者小团队试用,至少 4 核 8G 内存;生产环境最好 8 核 16G 起步,磁盘预留 100G 以上。为什么磁盘要留这么多?因为知识库的文档解析、向量化、缓存和日志都会持续增长,我见过有人磁盘写满直接导致 PostgreSQL 容器异常退出,所以磁盘空间千万别卡线。

系统方面,主流发行版都可以,官方文档里常见的是 Ubuntu、Debian、CentOS 这类。我自己的服务器是 Debian 系,下面命令也按 Debian 系习惯来写。如果你是 CentOS 系,把 apt 换成 yum,防火墙命令改成 firewalld 即可。

2.2 安装 Docker 与 Compose 插件

现在 Docker 新版本默认自带 Compose 插件,不需要单独安装 docker-compose 二进制。先检查系统里有没有装过:

docker --version docker compose version

如果提示找不到命令,可以按官方源安装。以 Debian 系为例,几条核心命令是这样的:

sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) 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

安装完成后,把当前用户加入 docker 组,避免每次敲命令都要加 sudo:

sudo usermod -aG docker $USER

这一步之后重新登录 shell 或者执行 newgrp docker 生效。我遇到过很多人在这里跳过,导致后续所有命令都要用 sudo,非常影响操作体验。

2.3 端口、目录与防火墙规划

安装 Docker 之前,先规划好 Dify 对外服务的端口。默认部署包会用 80 端口给 Web 和 API,但服务器上如果有 Nginx 或者其他站点占用了 80,就会直接冲突。我建议在 .env 文件里把端口改成自定义值,比如 8080 和 8081,避免和现有服务纠缠。

数据目录规划同样重要。Dify 的 Compose 文件默认把数据卷交给 Docker 管理,虽然方便,但我更推荐在部署前就把整个目录挂载路径想清楚,比如统一放在 /opt/dify。后续做备份时,只需要停掉容器,打包对应目录即可。提前规划的好处是后期不用迁移数据。

防火墙方面,Debian 系一般用 ufw 或者 iptables。如果改了端口,记得放行对应端口,否则容器起来了,外部就是访问不到。这里经常有人踩坑,明明 curl localhost 有响应,但浏览器打不开,就是防火墙只放行了 80,没放行自定义端口。

2.4 获取 Dify 部署文件

Dify 社区版在 GitHub 上直接有部署仓库,里面包含了 docker-compose.yaml、.env.example、相关配置目录。获取方式很简单:

git clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env

需要注意,Dify 迭代速度很快,master 分支可能是开发版本。我个人的习惯是 checkout 到最新的稳定发布 tag,而不是直接用 master。因为开发分支有时候镜像 tag 还没推送完整,启动时会出现拉取不到镜像的诡异报错。

3. 核心配置解析:环境变量与 Compose 文件

3.1 .env 环境变量逐项拆解

进入 dify/docker 目录后,真正决定部署行为的是 .env 文件。我建议不要直接改 docker-compose.yaml,而是把可变参数都放到 .env 里。这个文件里最关键的几个参数如下:

EXPOSE_NGINX_PORT=80 EXPOSE_NGINX_SSL_PORT=443 NGINX_SERVER_NAME=localhost POSTGRES_PASSWORD=changeme POSTGRES_DB=dify REDIS_PASSWORD=changeme DIFY_PORT=8080

其中 POSTGRES_PASSWORD 和 REDIS_PASSWORD 一定要改成强密码。默认密码太简单,如果端口被误暴露,数据库等于裸奔。NGINX_SERVER_NAME 在实际生产环境里要改成你自己的域名,否则后面配 HTTPS 证书时会遇到域名不匹配的问题。

如果你想调整向量数据库,比如使用 Weaviate 或 Qdrant,也需要在这个文件里配置。默认情况下,Dify 使用内置的 Weaviate 或者 PostgreSQL 的向量扩展,具体版本要看部署包的默认配置。我自己的经验是,如果知识库数据量不大,默认配置够用;如果要做大规模 RAG,建议单独部署独立的向量数据库,再用 Dify 的接入功能连过去。

3.2 docker-compose.yaml 的服务组成

打开 docker-compose.yaml,核心服务包括:

  • api:提供给前后端调用的 API 服务,也就是业务逻辑入口
  • worker:负责执行异步任务,比如文档索引、知识库更新、邮件发送
  • web:前端静态资源服务
  • db:PostgreSQL 数据库
  • redis:缓存与任务队列
  • nginx:容器内部的反向代理
  • ssrf_proxy:防止 SSRF 攻击的代理服务
  • sandbox:安全执行 Agent 代码的沙箱环境

这里面最容易被忽略的是 ssrf_proxy 和 sandbox。ssrf_proxy 把外部模型 API 的请求做了一层过滤和代理,避免模型插件发起意外的内网请求;sandbox 为 Agent 里的代码执行提供隔离环境。生产环境不要禁用它们,否则会引入安全隐患。

Compose 服务之间的依赖关系是通过 depends_on 控制的。数据库和 Redis 会先启动,等健康检查通过后再启动 API 服务。这里有个小细节:健康检查的间隔和超时参数已经写在 Compose 里,如果服务器性能较差,启动时间会拉长,不要看到某个容器还在 restarting 就急着中断。

3.3 数据存储与持久化策略

Dify 的数据主要存在 PostgreSQL 中,包括用户、应用、工作流、文档索引元数据等。Redis 里存的是会话状态和异步任务队列。向量数据根据配置可能存在单独向量库中,默认会在 PostgreSQL 里面。此外,上传的原始文档、处理后的文档、图片、图标等文件,会存放在 API 服务挂载的 volume 里。

部署之前要想清楚三个持久化点:

  • PostgreSQL 数据卷
  • Redis 数据卷
  • Dify 文件存储目录

这三个点做好持久化,容器删掉重来都不怕丢数据。我在服务器上会把 Compose 文件里的 volume 定义改成具名卷或者宿主目录绑定,原则是至少确认这些卷不会随着容器删除被自动清空。Docker 的匿名卷在容器重建后可能残留,但容易混淆,不如直接用具名卷清晰。

4. 完整部署实操流程

4.1 启动整套服务

配置好 .env 之后,执行:

docker compose up -d

如果你用的是旧版 docker-compose 命令,就执行 docker-compose up -d。首次启动会拉取所有镜像,耗时取决于网络和机器性能。启动完成后,依次检查各容器状态:

docker compose ps

正常时,所有服务状态都应该是 Up。如果有容器一直显示 Restarting 或 unhealthy,先不要急着访问,看日志找原因。

docker compose logs -f api docker compose logs -f db

我会习惯先检查 db 和 api 两个服务的日志,因为数据库初始化往往是最耗时的环节。等 db 日志里出现 ready to accept connections 类似信息,再确认 api 日志没有报错,这时候整个系统基本就绪。

4.2 首次访问与管理员账号创建

打开浏览器,访问 http://服务器IP/install。第一次进入会要求设置管理员邮箱和密码。这里我多提醒一句:管理员密码一定要用密码管理器生成,不要图省事。因为 Dify 管理后台权限极大,可以管理所有用户、模型和应用,密码泄露等于整套平台被人拿捏。

安装完成后,登录后台。默认首页会引导你创建第一个应用。先别急着接真实模型,可以创建一个空白应用,把界面流程熟悉一遍。Dify 的应用类型包括聊天助手、文本生成应用、Agent、工作流,还有 Chatflow 和 Workflow 两种编排模式,核心区别在于一个是对话式流程,一个是纯任务处理流程。

4.3 接入模型供应商

模型配置是部署之后最关键的一步。Dify 在设置里提供了模型供应商管理界面,支持配置多种大模型服务。这里有两种接法:

第一种是接第三方云 API,直接在界面里填 API Key、模型名称、Base URL 等信息。只要你的模型供应商提供 OpenAI 兼容接口,Dify 基本都能通过自定义模型供应商方式接入。

第二种是自己部署本地模型,比如通过本地推理服务把模型封装成兼容接口,然后在 Dify 里设置 Base URL 指向本地服务。这种方式不需要外网流量,数据全部留在内网,适合对数据合规要求高的场景。

配置完成后,务必点击“测试”按钮验证连通性。我见过不少人配置完模型没测试,结果应用创建好之后,对话时才发现 Key 配错、模型名写错,浪费了大量时间。测试通过后再去设计应用流程,效率会高很多。

4.4 通过 Nginx 反代与 HTTPS 配置

默认部署中,外部访问直接走 Docker 内置 Nginx 的 80 端口。如果只是内网试用,这样足够了。但生产环境建议在宿主机上再套一层 Nginx,将所有 HTTP 请求转发到 Dify 的 Nginx 端口,同时完成 HTTPS 证书配置。这样证书和域名解析都集中在宿主机管理,升级 Dify 时不需要改动证书路径。

宿主机 Nginx 配置片段大概长这样:

server { listen 443 ssl http2; server_name your-domain.example; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; 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; } }

这里有一个关键配置:请求头必须带上 X-Forwarded-Proto,否则平台内部生成的回调地址和文件链接可能变成 HTTP,导致部分功能异常。另一个容易忽略的点是 websocket 支持,Dify 的部分能力依赖 WebSocket,所以 proxy_read_timeout 和 proxy_send_timeout 不要设得太短,建议至少 60s。

5. 踩坑记录与问题排查

5.1 容器启动失败:端口冲突与内存不足

最常碰到的启动失败原因有两个:端口冲突和内存不足。先看端口,启动前用 ss -lntp 检查端口占用;如果 80 被占用,就会报 bind: address already in use。解决办法不是强 kill 占用进程,而是改 .env 里的端口。

内存不足的表现更隐蔽,容器日志里可能只显示数据库进程被 kill,或者出现 Memory cgroup out of memory。这时候用 free -m 看下内存,如果确实吃紧,建议加 swap 或者升级配置。我的经验是测试环境 4G 内存跑 Dify 太勉强,至少 6G 比较稳。

5.2 模型 API 调用超时与配置报错

模型调用超时,先排查网络路径。在容器内部用 curl 测试模型 API 的连通性:

docker exec -it dify-api-1 curl -I https://api.example.com

如果容器内能通而应用提示超时,重点检查 .env 和模型供应商配置里的 Base URL 是否写错。另一个常见问题是模型名写错,比如云端模型版本号更新后,旧模型名已经不可用,但界面里没同步更新。每次模型供应商更新模型列表后,建议到 Dify 后台重新拉取一次模型列表并核对默认模型。

5.3 知识库文档处理失败或检索结果为空

知识库上传文档后需要经过切片、向量化,这个流程由 worker 服务执行。如果上传文档后状态一直停留在“处理中”,先查 worker 日志,再从三个角度排查:第一,向量数据库是否正常连接;第二,模型供应商里配置的 Embedding 模型是否可用;第三,文档格式是否被支持。

Embedding 模型是最容易被忽略的点。有些模型供应商的默认模型不支持 Embedding 任务,但你只在对话模型里配了 Key,没有单独配置 Embedding 模型,知识库就会始终没法完成向量化。配置方式是在模型供应商设置里,把 Embedding 类型的模型单独指定一个可用模型。

5.4 文件上传失败与权限问题

文件上传失败时,如果日志里出现 permission denied,多半是容器内工作目录对挂载卷没有写权限。检查宿主机挂载目录的属主和权限,比如:

chown -R 1000:1000 /opt/dify/volumes

因为容器内 API 服务通常以 UID 1000 运行,宿主机目录如果归属 root,容器内进程可能无法写入。这个权限问题我在初次部署时踩过,后来统一把 Dify 相关数据目录的属主设置成 1000,世界清静了很多。

5.5 常见问题速查表

现象可能原因排查方向
80 端口无法访问防火墙未放行或端口被占用ss -lntp、ufw status
容器一直 restarting内存不足或配置里密码错误free -m、docker compose logs
对话报模型 404模型名写错或模型未部署检查模型供应商测试按钮
知识库不回复内容Embedding 模型未单独配置检查 embedding 类型模型
上传文件失败挂载目录权限不对chown -R 1000:1000
刷新后登录态丢失Redis 数据卷未持久化检查 Redis volume 配置

6. 运维扩展与升级维护

6.1 日常运维操作

日常最常用的运维命令主要是看状态、看日志、重启服务。

docker compose ps docker compose logs -f api docker compose restart api

修改 .env 后,要让配置生效,一般需要重新创建容器:

docker compose up -d --force-recreate

注意,修改镜像 tag 或环境变量后,直接 docker compose up -d 可能不会重建容器,一定要加 --force-recreate,或者先 docker compose down 再 up,否则容易出现配置改了但容器还是旧参数的问题。

6.2 升级 Dify 版本

升级前先备份。Dify 升级的基本流程是:拉取最新部署仓库或更新当前仓库,查看新增的环境变量,然后重新拉镜像并启动。

git pull docker compose pull docker compose up -d

升级时最容易出问题的是数据库迁移。新版本可能需要执行额外的数据库迁移,官方一般会在升级文档里说明。我的建议是小版本升级可以大胆试,大版本升级前务必在测试环境先跑一遍,尤其是跨主版本时,环境变量名称可能有破坏性变化。

6.3 备份与恢复策略

备份至少要覆盖三块:PostgreSQL、Redis、文件数据。PostgreSQL 备份最简单的方式是用容器内置的 pg_dump:

docker exec -i <db容器名> pg_dump -U postgres dify > dify_backup.sql

Redis 备份则用持久化文件加上定期拷贝。文件数据直接打包对应 volume 目录即可。恢复的话,先启动一套空环境,再把 SQL 导入数据库,把文件解压回对应目录,最后重启服务。完整恢复流程可以在测试机器上演练一次,真到出问题时就不用手忙脚乱。

6.4 资源限制与高可用扩展

如果服务器上还跑着其他服务,建议给 Dify 容器设置资源上限,防止某个容器把整台机器拖垮。在 Compose 文件里给服务加 deploy.resources.limits,或者直接在 docker run 时设置。例如限制 API 服务最多使用 2 核和 2G 内存:

deploy: resources: limits: cpus: '2' memory: 2G

高可用层面,Dify 的 API 服务和 Worker 其实都可以横向扩容。数据库和 Redis 建议已有主从或备份机制时再做扩容,否则只是增加 API 副本,数据库反而成为瓶颈。对多数团队来说,先保证备份完整,比盲目堆副本更实在。

写到这里,我再分享一点个人体会。Dify 这套平台用 Docker 部署,真正麻烦的地方往往不是 Docker 本身,而是对环境变量的理解、对数据卷的把控、以及对模型服务的理解。我第一次部署时,因为想省事没改默认密码,结果第二天发现有人在尝试登录后台,虽然没成功,但那种后背发凉的感觉至今记得。后来我养成了几个习惯:部署前先把 .env 改成强密码和自定义端口,部署后立刻做一次全量备份,升级前先在测试环境验证一遍。这几点看着简单,但每一条都能帮你避免一次深夜事故。如果你也在规划私有化的大模型应用平台,照着这套思路走,至少不会掉进同一个坑里。

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

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

立即咨询