这段时间给自己公司一台 Linux 服务器折腾了一次 Dify 部署前前后后踩了不少坑正好把这套流程沉淀下来。Dify 很多人不陌生简单说它是一个开源的大模型应用开发平台可以在网页上直接编排 Agent 工作流、做文档知识库、发布 API相当于给 AI 应用搭了一条可视化流水线。部署它最省心的方式就是在 Linux 服务器上用 Docker 把一套编排文件拉起前端、后端接口、异步任务、数据库、向量库全都包含在里面。这篇文章主要记录我在一台全新 Ubuntu 服务器上从环境准备到服务稳定运行的完整过程包括配置细节、启动命令和各类避坑经验。如果你也准备在公司服务器或自己的云主机上装一套 Dify这篇可以直接当操作手册用。1. 部署前先想清楚为什么要用 Docker 在 Linux 上跑 Dify1.1 Dify 到底是什么能解决什么问题Dify 的定位很明确它是一个大模型应用开发平台核心目标是让人不用从零写代码就能把 LLM 应用做出来。我在没有接触它之前一直以为就是个套壳的聊天机器人后台实际操作之后才发现它做的事情比想象的要多。它主要管四类事情第一是模型管理把不同厂商的大模型接口统一接入到同一个后台业务代码不用关心底层调的是哪家模型切换模型只是界面上点一个按钮的事第二是应用编排支持用可视化的方式把提示词、模型参数、上下文、工具调用串成一条工作流甚至可以做多轮 Agent第三是知识库和 RAG把文档上传进去系统会自动完成切片、向量化、检索和引用标注第四是发布管理做完的应用可以直接发布成 Web 页面也可以开放成 API 接口给外部系统调用。对于一个中小团队来说Dify 解决的问题非常实际。假设产品经理想做一个基于公司内部文档的问答机器人传统做法是找开发人员从零搭 RAG 管道先处理文档、做切片、选向量库、写检索逻辑、封装接口工作量很大。而在 Dify 里只要把文档传到知识库选一个模型配置好提示词几分钟就能跑起来。这种把基础设施、模型接入和推理编排全部封装好的思路特别适合项目周期紧、又不想被模型 API 细节拖住的团队。第一次接触它的人可能会问既然有现成的模型厂商平台为什么还要自己部署 Dify最直接的一个原因就是数据。很多企业场景下文档内容不适合全部打到第三方平台上跑自己服务器上部署一套数据链路完全在自己手里文档切片、向量化索引、检索和推理调用都在内部网络里完成。另一个原因是定制化自己部署之后可以随意改流程、改 UI 外壳、接内部系统自由度比 SaaS 方案高得多。1.2 单容器不是不行但 Compose 编排才是常态部署 Dify 的时候网络上能看到不少“一条命令跑起来”的教程确实存在单容器镜像但我个人强烈不建议在正经环境里这样用。原因很简单Dify 本质上不是一个单体程序它由多个服务组成单容器方式只是把多个进程强行塞进同一个容器里看起来省事实际上牺牲了稳定性、可扩展性和可观测性。官方推荐的 Docker Compose 编排方式是把每个职责独立的服务放进单独的容器API 服务处理业务请求Worker 消费异步任务Web 提供前端静态资源数据库用 PostgreSQL缓存用 Redis向量库用专门的向量引擎还有若干辅助容器。每个服务单独管理日志分开输出资源分别限制哪个挂了单独重启不互相拖累。这种设计思路跟微服务理念一脉相承虽然第一次部署时感觉容器很多但跑起来之后运维非常直观。我在正式环境里用 Docker Compose 部署还有一个更实际的考量升级方便。Dify 版本迭代比较快模型能力一更新平台往往也跟着更新。Compose 编排模式下升级就是改一下镜像版本号然后重新拉起数据全部存在挂载卷里不会因为升级丢数据。如果是单容器方式升级往往意味着替换整个容器稍有不慎就会出问题。当然Compose 不是唯一方案有基础的人也可以用 Kubernetes 跑 Dify官方也提供了 Helm Chart。但如果你只是要在一台服务器上稳定运行Kubernetes 引入的复杂度完全没必要。一台 Linux 服务器加 Docker Compose已经是性价比最高的组合。1.3 部署之前先看懂容器分工刚开始部署的时候我看着目录里的 docker-compose 文件有点懵里面的服务加起来将近十个一时间不知道谁是核心、谁是辅助。跑过几轮之后我大致梳理了一下这些容器可以分成四层这样理解起来就清楚多了。第一层是核心业务层包括 api、worker 和 web。api 是后端服务负责处理前端的请求、调用模型、读写数据库worker 是异步任务消费者专门处理文档解析、向量化这类耗时操作web 是前端静态资源服务用户打开的界面就是它提供的。第二层是数据层包括 PostgreSQL 数据库和 Redis 缓存这部分是系统的基座所有结构化数据都存在数据库里异步任务和缓存依赖 Redis。第三层是向量检索层也就是向量库容器知识库的 Embedding 向量存这里做 RAG 时依赖它做相似度检索。第四层是辅助层包括 Nginx 入口、代码沙箱和请求过滤组件Nginx 统一接收外部流量并转发到内部服务沙箱用于安全执行用户代码请求过滤组件负责限制服务端出站请求防止内网被随意探测。搞清楚这层关系之后遇到问题就知道先查哪里了。比如页面能打开但知识库上传一直转圈多半是 worker 或者向量库的问题比如页面都打不开那大概率是 Nginx 或者 api 的问题。部署 Dify 做运维排障懂这个分工比背一堆命令都管用。2. 动手前先把环境准备好服务器、Docker 与项目文件2.1 服务器配置建议与端口规划先说配置。Dify 对内存的需求比想象中大原因在于它同时要跑数据库、Redis、向量库、API 服务和异步 Worker每个容器都有一定的内存开销。我个人的经验是2GB 内存的机器只能勉强启动进入界面之后操作很容易卡死4GB 内存能做基础体验但知识库处理大文档时会让系统变得很慢8GB 内存是推荐起步配置能支撑小团队日常使用如果企业里要用得比较重16GB 以上才会比较从容。CPU 方面没有太高要求普通的 2 核到 4 核就能满足。磁盘反而是容易忽略的点Dify 的数据都写在 volumes 目录下包含了数据库文件、向量索引、上传的文档附件随着使用会越来越大。建议至少预留 50GB 空间并且把 Docker 的数据目录放到数据盘上别放在系统盘里否则后期磁盘满了很麻烦。端口规划是部署前必须确定的。Dify 默认用 80 端口作为 Web 入口如果服务器上已经跑了其他网站或服务需要提前改掉。我在一台机器上部署时就踩过这个坑Nginx 容器一直起不来查了半天发现是 80 端口早就被系统自带的 Nginx 占了。建议部署前先跑一下sudo ss -tlnp | grep -E :80|:443确认端口空闲不空闲就提前规划好替代端口比如用 8080 或者 18080 这种容易记的端口后续代码里统一改。2.2 安装 Docker Engine 和 Compose 插件服务器环境我以 Ubuntu 22.04 LTS 为例其他 Debian 系系统大同小异。安装 Docker 我推荐直接用系统软件源里的 docker.io 包虽然版本不是最新的但胜在稳定省事。命令就几行sudo apt update sudo apt install -y docker.io docker-compose-v2 docker-compose-plugin sudo systemctl enable --now docker安装完成后先确认一下版本Dify 需要 Compose V2 语法也就是docker compose这种不带横杠的写法docker --version docker compose version如果系统是 CentOS 或者较老的版本可能需要先去 Docker 官方仓库配置源再安装这里不展开。装好之后有个细节值得注意如果服务器上还有普通用户需要执行 Docker 命令把用户加入 docker 组即可sudo usermod -aG docker $USER newgrp docker顺手把 Docker 日志轮转配置也做了在/etc/docker/daemon.json里限制日志文件大小避免容器日志把磁盘写满。这个是我吃过亏之后养成的习惯Dify 服务比较多一个配置没做好过半个月磁盘就被日志塞满了。2.3 拿到 Dify 项目文件并解读目录结构Dify 项目本身是开源的部署用的文件在官方代码仓库里。我建议直接拉代码仓库因为后续升级要用到 git 操作。在我自己机器上习惯把项目放在/opt/dify这样的目录下sudo mkdir -p /opt cd /opt sudo git clone https://github.com/langgenius/dify.git仓库克隆下来之后实际部署相关的文件都在docker目录下。第一次打开这个目录眼睛都花了但拆开看主要有三类东西docker-compose.yaml定义了所有容器服务.env.example是环境变量模板volumes目录是数据持久化目录数据库文件、向量索引、上传附件全在这里。还有一个nginx子目录里面放着前端静态文件和 Nginx 配置模板。这里有一个非常关键的细节也是很多教程没讲清楚的.env.example不会自动生效必须手动复制成.env文件。Dify 的 docker-compose 编排在启动时会自动读取 Docker 目录下的.env文件把里面的变量替换到容器配置里。也就是说所有对外端口、数据库密码、密钥、向量库类型的配置都从这个文件里读。复制命令非常简单cd /opt/dify/docker cp .env.example .env不同版本的仓库文件结构可能略有差异但思路是一样的。接下来要做的就是认真对待这个.env文件它几乎决定了整个部署体验。3. 核心配置一份 .env 决定部署体验的上限3.1 从模板生成 .env该改哪些关键项把.env.example复制成.env之后不要急着启动先打开这个文件看一遍。文件里的配置项非常多但真正需要手动改的没几项改错反而会出问题。我的建议是只改你知道用途的变量不确定的就保持默认。第一类是安全相关的必须改。文件里的SECRET_KEY默认值是个占位符保持原样会有安全隐患。我习惯用系统自带的 openssl 生成一个随机密钥openssl rand -base64 42生成的字符串替换到SECRET_KEY后面。同理POSTGRES_PASSWORD和DB_PASSWORD也属于必须改的项这两个是数据库密码默认值太常见了不开放在公网上问题不大一旦对外开放就很危险。第二类是端口映射。前面说的端口冲突就是在这里解决关键变量是EXPOSE_NGINX_PORT它控制着外部访问 Dify 的端口。默认是 80如果跟现有服务冲突改成 8080 或者其他端口即可。改完端口之后访问地址就要带上端口号。第三类是长期运行需要关注的持久化配置。DIFY_IMAGE这一项标记了镜像版本后面升级的时候改它。VECTOR_STORE决定使用哪种向量数据库默认通常是weaviate这个我们等会儿单独说。我只做这三个方向的调整其余配置保持默认。Dify 的默认配置在实际部署中已经能跑得很稳过度修改反而引入了不稳定因素。3.2 模型接入界面配还是环境变量配很多人在部署阶段就急着在.env里写模型 API Key想着一次性配置到位。我的实际体验是没必要而且容易出问题。.env里确实预留了模型厂商的配置位置但它更适合做静态的全局配置模型接入这种需要频繁切换、调试的操作放在 Dify 后台界面里做要直观得多。部署完成之后登录管理员账号进入“设置 - 模型供应商”页面找到对应厂商填写 API Key 和 Base URL 就能完成接入。这个界面的好处是即改即生效不需要重启任何容器也不需要重新编排。如果是在内网环境里接企业自己的模型网关只要网关提供 OpenAI 兼容接口在界面里选好模型类型填上网关地址和 Key 就行。接本地模型的情况稍特殊一些。如果服务器上跑着本地推理引擎比如 Ollama 之类那就需要在模型供应商页面填一个自定义的地址指向本地推理引擎的端口并且模型名称要跟实际部署的模型一致。这一步很容易踩坑模型名差一个字母都调不通。另外要注意的是Dify 的容器和本地推理引擎如果跑在同一台机器上要填局域网 IP 而不能填 127.0.0.1因为在容器网络里127.0.0.1 指向的是容器自己不是宿主机。3.3 docker-compose.yaml 里几个值得留意的容器虽然前面说不用改 docker-compose.yaml但花几分钟了解一下每个服务的作用对排障和调优帮助很大。我用的是一个相对默认的编排里面除了 api、worker、web 三个核心服务外还有几个容易被忽略的容器。PostgreSQL 是系统的核心数据存储用户信息、应用配置、会话记录都在里面。Redis 做缓存和异步任务队列worker 进程通过它拿到待处理的任务。向量库默认是 Weaviate负责知识库的向量数据如果希望切换成 Qdrant需要把.env里的VECTOR_STORE改成qdrant同时把 docker-compose.yaml 里对应的容器定义和存储卷一起切换。这个操作建议在首次启动之前做好因为启动之后再切向量库需要重新向量化已有文档比较折腾。还有两个小容器值得一提。一个是沙箱容器Dify 某些代码执行功能需要它来隔离运行如果这个容器起不来涉及代码执行的功能就会报错。另一个是请求过滤容器它限制服务端发起的出站请求范围避免 SSRF 攻击生产环境一定要保留它。这两个容器平时看起来很不起眼但它们挂了业务表面上不会立即全挂但各种诡异报错会陆续出现。这也是为什么运维 Dify 的时候一定要养成看全部容器状态的习惯而不是只盯着 api 和 web。4. 实操记录从拉镜像到服务跑通4.1 初始化配置与启动命令配置改完之后进入 Docker 目录先确认一下文件是否就位cd /opt/dify/docker ls -la .env确认.env存在后第一步是拉取镜像。Dify 涉及的镜像较多包括业务镜像、数据库镜像、向量库镜像等首次拉取可能需要一些时间。如果服务器网络拉取 Docker Hub 比较慢可以配置一个可用的镜像源。这一步打好底子后面启动就会顺畅很多docker compose pull拉取完成后启动容器docker compose up -d启动命令执行后不要急着访问页面Dify 首次启动会有一个初始化过程。API 服务要等数据库准备好、执行数据库迁移向量库也要初始化索引。这个过程通常持续几十秒到几分钟不等取决于服务器性能和磁盘速度。判断是否启动完成最直接的方式是看容器运行状态docker compose ps正常状态下所有服务的 STATUS 列都应该是Up或者healthy如果看到Restarting或者Exited说明有问题需要处理。可以用docker compose logs -f实时看日志也可以指定某个服务看docker compose logs -f api等所有容器都稳定之后再做下一步操作。4.2 健康检查与管理员账号初始化容器都起来了不代表服务真正可用我习惯先做一个后端健康检查。Dify 的 API 服务暴露了一个健康检查接口直接在服务器本地请求一下curl http://localhost/api/health正常情况下会返回类似{result: ok}的 JSON看到这个说明后端 API 服务已经正常。如果 curl 没反应先确认端口映射是否正确再看 api 容器日志。做完这一步再用浏览器访问服务器 IP 加端口比如http://服务器IP:8080第一次打开会进入管理员初始化页面。初始化管理员账号是整个部署唯一需要在网页上操作的步骤。设置管理员邮箱和密码之后系统会停留在登录页用刚设置的管理员账号登录就正式进入 Dify 主界面了。到这里一套基础环境就算部署完成。此时可以先去“模型供应商”页面把模型接入好然后试着创建一个应用跑一下最简单的对话确认整条链路是通的。我在这个环节有个习惯创建应用并成功跑通一次对话之后再进知识库上传一个文档确认 Worker 和向量库也正常工作。很多部署问题都是隐藏的页面能打开、对话能跑但文档处理挂掉了等真正用知识库的时候才发现那时候排查成本反而更高。所以第一步就把所有核心功能都验证一遍省得后面踩坑。4.3 让 Dify 更稳的几项额外设置基础部署完成之后我通常还会做几项加固和优化让系统更稳定也更方便日后维护。第一是资源限制。Dify 容器多如果不做限制某个服务异常时可能吃掉整个服务器的内存导致其他服务跟着挂。可以在 docker-compose.yaml 里的服务定义下增加资源限制比如限制容器最多使用 2GB 内存。这个操作需要重启容器生效适合部署初期就做好。第二是定期备份。Dify 的数据都放在/opt/dify/docker/volumes目录下备份的方式就是把这个目录复制一份或者针对 PostgreSQL 单独做数据库备份。数据库备份更精细直接在容器里执行docker compose exec db pg_dump -U postgres dify dify_backup_$(date %Y%m%d).sql备份出来的 SQL 文件存放位置要放在 volumes 目录之外避免跟容器数据混在一起万一磁盘整块坏了也还有个异地副本兜底。我吃过教训之后养成了每周自动备份的习惯用 crontab 跑一个简单的备份脚本把 SQL 文件压缩后同步到另一个存储位置。第三是日志清理。前面提到配置 daemon.json 做日志轮转这里还要提一下Dify 自己的容器也会在 volumes 目录里产生日志文件时间长了也会膨胀。定期清理不常用的旧日志对磁盘空间管理很有帮助。5. 常见问题与排查技巧实录5.1 端口被占、容器反复重启先说我踩过的第一个坑执行docker compose up -d之后nginx 容器反复重启docker compose ps里能看到 STATUS 显示Restarting。用docker compose logs nginx看日志里面报端口 bind 失败一查发现宿主机 80 端口已经被系统自带的 Nginx 占用了。解决办法有两个方向。一个是对外端口改成 8080只改.env里的EXPOSE_NGINX_PORT然后重新创建容器。另一个是停掉占用端口的服务。我建议如果是专门跑 Dify 的服务器直接停掉系统自带 Nginx如果服务器上还有别的网站那就改端口。还有一种更隐蔽的情况是端口没被占用但 IPv6 绑定冲突看日志时留意一下 bind 的具体 IP 和端口。容器反复重启还有个常见原因健康检查失败。Dify 的编排里部分容器定义了健康检查比如数据库和 API 服务。健康检查失败会被 Docker 标记为 unhealthy如果配合了其他服务的等待机制看起来就像是不断重启。这种情况要区分是健康检查本身太严格还是服务真的有问题。先看对应容器日志确认服务是否正常响应再决定是调整健康检查参数还是排查服务本身。5.2 API 服务起不来数据库拔河API 服务起不来是 Dify 部署中出现频率最高的故障之一。常见表现是 api 容器处于退出状态日志里报数据库连接失败比如connection refused或者password authentication failed。仔细看会发现API 容器的启动依赖数据库逻辑准备好但数据库容器的初始化需要时间尤其是首次启动时PostgreSQL 要初始化数据目录、创建用户和数据库这个过程可能是几十秒API 服务如果在数据库就绪之前就开始连接就会报错退出。遇到这种情况我的处理方式是先看数据库容器状态docker compose ps db如果 db 容器还在初始化耐心等一会儿再启动 api 服务docker compose restart api多次重启之后还连不上就要检查数据库密码是否匹配。.env里的POSTGRES_PASSWORD和 API 服务连接数据库的密码必须一致。如果修改过.env里的密码之前已经初始化的数据库卷不会自动同步密码需要把 volumes 里的 PostgreSQL 数据目录清掉重新初始化或者手动在数据库里修改密码。这个坑我在升级过程中踩过一次印象非常深刻。所以一定要记住凡是改了数据库密码要么清掉旧数据卷重新初始化要么同步修改数据库里的实际密码否则 API 服务永远连不上。5.3 模型接入后请求不通页面正常、应用也建好了但一对话就报模型调用错误这是另一个高频问题。排这个问题的思路是先区分是模型层的问题还是 Dify 系统的问题。最简单的方法是在 Dify 后台“模型供应商”页面选一个已配置的模型做一次连通测试如果测试失败问题就在模型接入配置上。常见原因有几个。一是模型 API Key 配置错误包括多复制了一个空格、填错了 Key 本身。二是 Base URL 填的不对如果接的是 OpenAI 兼容接口一般需要填到/v1这一级有些网关实际地址不带/v1就要以供应商文档为准。三是模型名称填错Dify 要填模型的实际标识名而不是任意的显示名称。四是超时设置太短大模型响应慢默认超时在某些场景下不够用模型供应商页面里可以把超时时间调大一些试试。还有一个很容易忽略的点容器能不能访问目标模型的接口。如果模型网关在内网要确认 Dify 容器所在的网络能路由到网关地址如果模型接口需要额外的网络策略放行光改了配置也白搭。碰到请求报超时先到 api 容器里用命令行工具做一次最简单的请求测试能通再看 Dify 的配置不能通就先解决网络问题。5.4 备份、升级与数据安全Dify 升级迭代速度不慢隔几个月就想升一次。升级本身不算复杂但顺序错了容易丢数据我个人总结了一套固定的升级路径。第一步永远是备份。把volumes目录整体复制一份再单独做一次 PostgreSQL 逻辑备份。第二步是更新代码仓库把 Dify 项目代码切到目标版本用git pull拉取最新内容或者直接切换到目标 Release 版本。第三步是更新.env里的镜像版本号然后依次执行docker compose down docker compose pull docker compose up -d执行docker compose down只是停止容器数据卷不会被删除所以不用担心数据丢失。但这里有一个细节必须提醒docker compose down和docker compose down -v是两回事带-v会连同数据卷一起删除。除非你有意清空所有数据否则千万别加-v。升级过程中如果容器启动后一直不健康优先看数据库迁移是否正常完成。Dify 升级时如果涉及数据库结构变化API 服务启动时会自动执行迁移耗时可能较长。迁移过程中不要频繁重启容器否则容易导致迁移中断。等日志输出稳定之后再做健康检查会稳妥很多。5.5 快速排查口诀速查表把上面这些常见的坑整理成表格方便读者在服务器前快速对照症状优先排查方向快速命令页面打不开Nginx 端口是否被占sudo ss -tlnp | grep 80容器反复重启看日志和健康检查结果docker compose logs nginxAPI 起不来数据库是否就绪、密码是否一致docker compose logs api知识库上传一直转圈Worker 是否存活、向量库状态docker compose ps worker weaviate对话模型报错模型 Key、Base URL、网络后台模型供应商页做连通测试磁盘空间暴涨日志与 volumes 目录大小du -sh /opt/dify/docker/volumes这个表是我每次去现场排障时脑子里过的第一遍流程。先看范围是页面问题还是某个功能问题再定位容器是哪个服务异常最后看日志找到具体报错。把握好这三步大部分问题都能很快收敛。最后说一点我个人的体会。Dify 这类平台的部署难度并不高真正有门槛的是部署之后的日常维护。容器化带来的便利是巨大的但如果对架构不熟悉、对数据持久化没概念出了问题很容易一头雾水。我建议每一个准备部署的人都花十分钟把 docker-compose.yaml 里的服务列表和 volumes 挂载关系看一遍弄明白数据存在哪、每个容器干什么。这份基础功夫会在未来的每一次升级和排障中加倍回报你。