ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Dify 1.17 本地部署实战:Docker Compose与Ollama接入

2026/9/12 3:17:36 拓冰建站 浏览量
Dify 1.17 本地部署实战:Docker Compose与Ollama接入 1. 部署前先想清楚Dify 1.17 到底是什么值得折腾吗直接说结论Dify 1.17 是一个开源的 LLM 应用开发平台它把大模型接入、知识库管理、工作流编排、Agent 构建、API 发布这些能力做成了一个可视化的操作界面。你不需要从头写 Prompt 模板、不用自己维护向量数据库的连接代码也不用纠结多轮对话的会话状态怎么存Dify 把这些脏活累活都封装好了你只需要在网页上拖拖拽拽、填填参数就能把一个带知识库的聊天机器人或者一条多步骤的 Agent 工作流跑起来。所以这篇博文面向的读者特别明确第一类是刚接触 Dify、想在本地或者一台普通服务器上把它跑起来看看效果的人第二类是想把本地大模型比如 Ollama 拉下来的 DeepSeek、Qwen 这类开源模型接进 Dify做一个完全内网可用、数据不出门的问答系统的人第三类是已经被网上各种教程坑过用 Docker 部署了半天结果页面打不开、模型不回复、知识库解析失败想找个地方系统排查一遍的人。这三种需求本质上都绕不开“部署”和“问题排查”这两件事而这篇博文的目标就是让你照着做能在二十分钟左右拿到一个能登录、能建应用、能对话的 Dify 1.17。先说一个很重要的判断Dify 1.17 这个版本部署方式其实非常成熟了官方主推Docker Compose 方式。官方也提供了源码部署选项但源码部署要自己装 Node.js、Python、PostgreSQL、Redis、Weaviate 一堆依赖中间任何一个版本对不上都够你折腾半天的。对新手的建议只有一个老老实实走 Docker Compose 路线这是目前所有部署方式里对新手最友好、也最容易出成果的一条路。网上流传的很多老教程还在教“单独装后端、装前端、再装 worker”这种三件套流程那是早期 Dify 的部署方式现在早就被官方整合成一条 docker compose up 命令搞定了。但“docker compose up”看似简单里面涉及的细节其实不少。比如 Dify 依赖哪些中间件默认的 docker-compose.yaml 里那个大的配置文件包含了哪些服务为什么有人一上来就把所有服务全启了结果内存爆了这些坑我在部署过程中全部踩过一遍。这篇博文会先带你完成一套“精简版”部署不追求把所有组件都跑起来而是先把最核心的链路跑通然后针对最容易出问题的几个环节做一次排查梳理。还有一点值得说清楚Dify 1.17 这个版本发布之后整个平台在知识库的召回效果、工作流的编排能力、以及多租户支持上都有一些更新。对新手上手来说这些更新没有那么直观但“版本升级后配置文件的兼容性”这种问题会直接影响你能不能正常启动。所以这篇博文在写环境配置的时候也会专门提一下 1.17 版本的几个关键变化。注意本指南默认你已经安装好了 Docker 和 Docker Compose 插件。如果你还没装建议先去 Docker 官网下载 Docker DesktopWindows / macOS 用户或者用系统包管理器安装 docker-ce 和 docker-compose-pluginLinux 用户这部分网上资料很多这里不再重复。2. 部署方案选型为什么我推荐“精简 Docker Compose”而不是一键全量启动2.1 先看懂 Dify 1.17 官方部署文件的结构Dify 项目的 GitHub Release 页面提供了每个版本的源码压缩包解压后进入docker目录你会看到几个核心文件.env.example、docker-compose.yaml、以及一堆不同用途的 compose 覆盖文件。官方那个完整的docker-compose.yaml里包含了 Dify 后端 API 服务api、Worker 异步任务服务worker、Web 前端服务web、PostgreSQL 数据库db、Redis 缓存redis、Weaviate 向量数据库weaviate、Sandbox 服务sandbox、SSRF 防护服务ssrf_proxy、以及可选的 Nginx 和插件相关的服务。这种方式的好处是“开箱即用”一条命令把所有组件全拉起来适合内存大于 16GB、硬盘大于 40GB 的机器。但问题也很明显很多组件对于一个本地试用或者中小团队内网使用的场景来说属于多余的重负载。举个最典型的例子如果你只是想把 Dify 跑起来接一个 Ollama 本地模型做一个内部知识库问答机器人那服务端真正干活的就是 api、worker、web、db、redis 这几个。db 用来存应用配置、用户信息、会话记录redis 用来做缓存和异步任务队列api 是后端主服务worker 负责处理知识库文档解析、数据集索引这些异步任务web 是浏览器访问的前端页面。而 Weaviate 是向量数据库你要做“知识库”功能就一定需要它不然文档切片后的向量没地方存。sandbox 是官方用来安全执行工作流里 Python 代码的服务如果你短期内不会在工作流里写代码块它可以先不启动。ssrf_proxy 是用来防护服务端请求伪造的代理内网单机部署时优先级也不高。所以“精简部署”的思路就是保留 api、worker、web、db、redis、weaviate 这六个核心服务其余能省则省。你可能会问那官方的 docker-compose.yaml 能不能直接删掉几个服务答案是能但直接改官方文件有个风险——官方更新版本后你手动改过的文件可能会被覆盖而且如果你对 Docker Compose 的语法不熟删错一个依赖关系会导致 api 容器起不来。更稳妥的方式是用官方提供的精简版命令或者自己写一个最小化的 compose 文件。2.2 资源消耗的账算给你看很多新手上来就跟着教程执行docker compose up -d结果发现页面一直转圈、加载不出登录框打开 Docker Desktop 一看内存占用已经飙到 10GB 以上。为什么会这样因为默认配置下每一个容器都可能分到较多资源如果你机器总共只有 8GB 内存光 Dify 全家桶就能把内存吃满系统开始疯狂使用交换分区卡顿就随之而来。精简部署最大的价值就在这里。我实测在一台 4 核 8GB 内存的 Linux 服务器上只启动 api、worker、web、db、redis、weaviate 这六个服务系统空闲时内存占用大概在 2.5GB 到 3GB 左右运行知识库文档解析时峰值会到 4GB 左右。这个水平对于一台普通的云服务器或者一台老旧的 PC 来说是完全能接受的。如果你只有 4GB 内存那还有最后一招启动的时候不给 weaviate 分太多内存或者直接用sqlite模式临时顶一下Dify 1.17 对向量存储的支持里默认还是推荐向量数据库所以不建议长期这么干。另一个可行的思路是把向量数据库换成 Qdrant 或者 pgvector但这属于进阶优化新手没必要一开始就碰。2.3 用 docker-compose.yml 精简部署文件的直接示例我自己在实际部署时直接写了一个精简版 compose 文件内容不长完整贴出来供你参考version: 3.4 x-shared-env: shared-env LOG_LEVEL: INFO SECRET_KEY: your-strong-secret-key-change-me DB_HOST: db DB_PORT: 5432 DB_USERNAME: dify DB_PASSWORD: dify123456 DB_DATABASE: dify REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: VECTOR_STORE: weaviate WEAVIATE_ENDPOINT: http://weaviate:8080 WEAVIATE_API_KEY: WEAVIATE_BATCH_SIZE: 100 # 如果你要接 Ollama 本地模型下面这个域名很重要 OLLAMA_BASE_URL: http://host.docker.internal:11434 services: api: image: langgenius/dify-api:1.17.0 restart: always environment: : *shared-env MODE: api volumes: - ./volumes/app/storage:/app/api/storage depends_on: - db - redis - weaviate networks: - dify_network worker: image: langgenius/dify-api:1.17.0 restart: always environment: : *shared-env MODE: worker volumes: - ./volumes/app/storage:/app/api/storage depends_on: - db - redis - weaviate networks: - dify_network web: image: langgenius/dify-web:1.17.0 restart: always environment: CONSOLE_API_URL: APP_API_URL: APP_WEB_URL: ports: - 3000:3000 depends_on: - api - worker networks: - dify_network db: image: postgres:15-alpine restart: always environment: POSTGRES_PASSWORD: dify123456 POSTGRES_DB: dify POSTGRES_USER: dify volumes: - ./volumes/db/data:/var/lib/postgresql/data networks: - dify_network redis: image: redis:7-alpine restart: always volumes: - ./volumes/redis/data:/data networks: - dify_network weaviate: image: semitechnologies/weaviate:1.19.0 restart: always volumes: - ./volumes/weaviate:/var/lib/weaviate environment: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: true PERSISTENCE_DATA_PATH: /var/lib/weaviate DEFAULT_VECTORIZER_MODULE: none CLUSTER_HOSTNAME: node1 networks: - dify_network networks: dify_network: driver: bridge这个文件相对官方版本来说已经精简了很多没有 Nginx、没有 Sandbox、没有 SSRF 代理但核心功能全部保留。web 端直接通过 3000 端口访问api 和 worker 放在同一个镜像里通过 MODE 环境变量区分启动模式这是官方标准的做法。注意镜像版本号请以你实际下载的源码包中对应的镜像标签为准。如果你解压的是 1.17 某个具体 patch 版的源码建议直接看docker-compose.yaml里标注的 image 版本号不要盲目照抄我这里的1.17.0。3. 从零到一Dify 1.17 精简部署实操全记录3.1 第一步下载源码包并进入 docker 目录打开 Dify 的 GitHub Releases 页面找到 1.17 版本对应的源码压缩包下载后解压。在 Linux 服务器上通常这样操作wget https://github.com/langgenius/dify/releases/download/1.17.0/dify-1.17.0.zip unzip dify-1.17.0.zip cd dify-1.17.0/docker如果你是在 Windows 上解压后打开资源管理器进入dify-1.17.0文件夹下的docker子目录在地址栏输入cmd回车就能直接在当前路径下打开命令行窗口。这一步看似简单但很多人会在后面cp .env.example .env这一步因为路径不对而失败所以强调一下一定确保当前所在路径是含.env.example文件的 docker 目录。3.2 第二步准备 .env 配置文件并做三个关键修改.env.example是官方给的一份环境变量模板里面每一项基本都有默认值。复制一份为.envcp .env.example .env如果你按我前面写的精简版 compose 文件来部署.env文件里的部分配置其实是多余的因为那些变量已经在 compose 文件的环境变量里写死了。官方默认的 docker-compose.yaml 是从.env文件读取变量的而精简版文件直接用environment字段写死了核心配置两者选一种即可。我的建议是新手直接用官方 docker-compose.yaml 修改 .env 的方式这样兼容性最好。在编辑.env文件时有三个地方必须确认第一SECRET_KEY一定要换掉。默认值太常见了生产环境容易被别人猜到最重要的是它用于加密会话和 API 密钥用一个随机字符串替换它。可以用openssl rand -hex 32生成一个。第二POSTGRES_PASSWORD、DB_PASSWORD这两处要保证一致。.env里的DB_PASSWORD是 Dify api 用来连接数据库的密码而 compose 文件里db服务启动时会用POSTGRES_PASSWORD初始化数据库。如果两者不一致api 容器启动时连不上数据库你会看到一堆connection refused或者password authentication failed错误。第三VECTOR_STORE变量。如果你确定要用 Weaviate保持默认值weaviate就行。如果你把向量存储切换成qdrant或者milvuscompose 文件里的相关服务也需要对应调整新手不建议在这一步做切换。除此之外还有一个容易忽略但实际影响很大的配置EXPOSE_NGINX_PORT。官方默认用 Nginx 作为入口暴露 80 端口。很多人在服务器上已经有了别的 Web 服务占用 80 端口启动 Dify 时就会提示port is already allocated。解决方法是把它改成80:80之外的其他端口比如18080:80或者干脆用精简版 compose 直接通过 3000 端口访问 web。3.3 第三步启动服务并验证状态在 docker 目录下执行docker compose up -d第一次执行会拉取镜像镜像总大小大约 2GB 到 4GB取决于你拆分成多少服务。如果网络状况一般这一步可能要耐心等一会儿。拉取完成后Compose 会按依赖顺序启动 db、redis、weaviate再启动 api 和 worker最后启动 web。启动完成后用docker compose ps查看容器状态。理想状态下你会看到所有服务的状态都是Up而且 api、worker、web 这几个容器不能有频繁重启的记录Restarting状态就是有问题。如果某个容器一直重启第一步看日志docker compose logs api docker compose logs db日志信息会直接告诉你是数据库连接失败、端口冲突还是环境变量缺失。确认所有容器都处于运行状态后浏览器访问http://localhost:3000如果你用了 Nginx 入口则是http://localhost:18080。第一次打开会进入初始化页面设置管理员邮箱和密码。这一步通过后Dify 1.17 的界面就会正常展示出来。提示在线升级场景下如果你是从旧版本比如 1.15 或 1.16升级到 1.17官方会建议先备份数据库和 storage 目录再拉新镜像、执行docker compose down和docker compose up -d。升级前一定要看官方 Release Notes 里关于数据库迁移的说明。3.4 第四步在 Dify 里接入一个本地模型Ollama DeepSeek 示例Dify 部署完成只是第一步真正要让应用跑起来必须配置一个大模型。对新手最友好的本地模型方案是 Ollama。假设你已经在一台机器上安装好了 Ollama并且已经拉取了一个模型比如ollama pull deepseek-r1:7b接下来要做两件事。第一件事在 Dify 后台左侧菜单进入“设置”找到“模型供应商”选择 Ollama。填写模型名称必须和你在 Ollama 里拉取的模型标签一致比如deepseek-r1:7b、Base URL。这里有一个非常大的坑如果你的 Ollama 和 Dify 在同一台机器上Base URL 不能写http://localhost:11434而要写http://host.docker.internal:11434。因为在 Docker 容器里localhost指向的是容器自己不是宿主机。host.docker.internal是 Docker 提供的一个特殊域名用来从容器内部访问宿主机服务。如果你在 Linux 服务器上部署Docker 默认host.docker.internal 可能不会自动生效需要额外加一句extra_hosts配置把host.docker.internal:host-gateway映射进容器。所以我在精简版 compose 文件里给 api 和 worker 加上了这个配置否则这两个容器访问不到宿主机的 Ollama。第二件事在 Dify 里新建一个应用选择“聊天助手”类型然后把模型切换成你刚配置好的 Ollama 模型。随便输入一句话测试如果模型正常返回内容说明整条链路已经通了——浏览器请求 Dify Web、Dify 后端调 Ollama、Ollama 调本地模型全部打通。4. 问题排查实录Dify 1.17 部署中我踩过的 7 个坑4.1 镜像拉取慢或拉取失败Dify 的镜像都托管在 Docker Hub 上国内网络环境拉取时经常会出现超时或者速度极慢的情况。解决办法有两个一是给 Docker 配置镜像加速器这个每家云厂商都提供了二是用代理环境变量但这不在本篇讨论范围内建议通过配置 Registry Mirror 解决。实操中我觉得最靠谱的还是配置镜像加速器。打开 Docker Desktop 的 Settings - Docker Engine在 JSON 配置中加入registry-mirrors字段保存后 Docker 会自动重启。Linux 服务器上则修改/etc/docker/daemon.json同样加registry-mirrors然后systemctl restart docker。注意镜像加速器只能解决 Docker Hub 镜像的拉取速度不能解决某些需要登录的私有镜像仓库的认证问题。Dify 官方镜像都是公开的不存在这个问题。4.2 容器一直重启日志显示数据库连接失败这个问题八成出在数据库密码不一致。Dify 的 api 容器启动时会尝试连接 Postgres如果密码不对就会无限重启。排查步骤很简单先用docker compose exec db psql -U dify -d dify -c select 1;看数据库是否能本地登录如果能说明问题出在 api 容器读取的密码配置上。检查.env文件里的DB_PASSWORD是否和 compose 文件里 db 服务初始化时的POSTGRES_PASSWORD一致。很多人改了.env文件但没重启容器导致 api 容器用的还是旧环境变量。改完配置后务必执行docker compose up -d --force-recreate强制重新创建容器确保新配置生效。4.3 页面能打开但登录后提示“服务内部错误”这种问题一般发生在初始化管理员账号之后进入工作台时接口报 500。从日志看基本上都指向数据库表缺失或者迁移未执行。正常情况下api 容器启动后会自动执行数据库迁移但如果迁移过程中断比如数据库没准备好、容器崩了表结构就不完整。解决办法是手动执行一次迁移。进入 api 容器内部运行迁移命令docker compose exec api flask db upgrade执行完成后再刷新页面通常就能恢复正常。如果还是报错把完整的错误日志贴到 Dify 官方 GitHub Issues 里搜索不要自己在黑暗中摸索。4.4 模型配置正确但对话时一直转圈不回复这个问题要分两层看。第一层如果 Dify 里测试模型连接时返回成功但实际应用对话时没反应多半是“应用内部绑定的模型”和“模型供应商里配置好的模型”不是同一个。Dify 1.17 里每个应用都可以单独设置默认模型也可能在工作流里为某个节点单独指定模型。如果应用配置里选的模型供应商不是 Ollama对话当然走不通。到“应用编排”页面的“上下文/模型”区域检查一下当前选的是什么模型。第二层如果模型测试连接时直接报错重点检查 Base URL 是否填对。记住我前面强调的规律Dify 和 Ollama 在同一台机器上填http://host.docker.internal:11434Dify 和 Ollama 不在同一台机器上填 Ollama 所在机器的局域网 IP。还有一个很小的坑——Ollama 默认只监听 127.0.0.1不会监听外部网卡。你要让其他机器能访问它必须设置环境变量OLLAMA_HOST0.0.0.0:11434并重启 Ollama 服务。这个问题在网络排查里非常隐蔽我第一次部署时卡了整整两个小时。4.5 知识库文档上传后一直显示“待处理”或解析失败知识库文档的解析和索引由 worker 容器负责。如果 worker 容器没起来或者 worker 连接不到向量数据库文档就会一直卡在“待处理”状态。先看 worker 日志docker compose logs worker常见错误有两类一类是无法连接 Weaviate检查WEAVIATE_ENDPOINT配置是否指向http://weaviate:8080另一类是 Milvus/Weaviate 权限问题检查向量数据库的认证配置是否与.env里的WEAVIATE_API_KEY一致。还有一个容易被忽略的坑文档格式和解析方式。上传 PDF 或者 Word 时如果文档扫描质量差、文字无法复制Dify 的解析器也可能抽不出内容。这种情况不是部署问题是文档本身的问题。建议新手先用一个纯文本 txt 文件测试知识库功能通了再上复杂格式。4.6 升级到 1.17 后原有应用数据丢失或者工作流异常升级场景下最常见的问题是容器镜像版本和数据库迁移版本不匹配。部分用户在社区反馈升级后老工作流节点无法正常加载这往往是因为新版本改了内部数据结构但旧的数据库迁移没有完全执行。面对这种问题回归升级前的备份是首选。Dify 的官方升级文档里写得很清楚数据库和storage目录应用上传的文件、知识库文件都要提前备份。如果你已经升了才后悔也别慌。数据库备份文件还在的话可以把容器全部停掉用备份的 Postgres 数据目录替换./volumes/db/data下的内容再重新docker compose up -d。这个操作要非常小心务必先停掉 db 容器再操作否则文件被占用会导致数据损坏。4.7 多租户模式下用户同步数据一直转圈热词里有人提到“Dify 社区版 1.10 多租户”1.17 也涉及多租户能力。如果你创建了多个工作空间成员同步或数据同步时界面一直显示“同步数据中”先检查 api 容器是否因为内存不足被系统杀掉过。多租户场景下并发请求多内存占用会明显上升小内存机器容易出现容器被 OOM Killer 杀掉的情况。排查命令很简单docker inspect api 容器ID看State.OOMKilled字段是不是true。如果确实是内存不够提高 Docker 资源限制或者精简不必要的容器。多租户下 worker 的并发线程数CELERYD_CONCURRENCY也可以适当调低例如从默认的 8 改成 2能明显降低内存压力代价是文档解析和异步任务的速度会变慢。这是一个很实用的取舍。5. 部署后的三个小技巧让你的 Dify 更好用部署完成、模型接通、知识库能解析之后Dify 1.17 基本已经可以日常使用了。不过我这里还想分享三个能提升体验的细节都是我在实际使用过程中慢慢试出来的。第一个定期备份volumes目录。Dify 的全部状态——包括数据库文件、上传的知识库文档、应用图标、日志——基本都保存在 compose 文件所在目录下的volumes文件夹里。你不需要理解每个子目录的用途只需要知道备份整个volumes目录就等于备份了整个 Dify 实例。最土也最有效的办法是写个定时任务把volumes目录打包上传到对象存储或者另一台机器上。第二个把 api 容器的日志级别调成 WARNING。默认 INFO 级别的日志非常啰嗦一天能产生几百 MB 日志文件。虽然日志会按天轮转但频繁的磁盘写入对小型服务器来说确实是一种压力。在.env里把LOG_LEVEL改成WARNING观察几周下来日志量大幅下降排查问题的时候看 WARNING 和 ERROR 级别的日志反而更聚焦。第三个善用“发布为 WebApp”功能。Dify 里做好的聊天助手可以一键发布成一个独立的网页链接不需要登录后台也能对话。这对内网团队试用非常方便。你不需要把 Dify 后台的账号密码发给每个同事直接把这个链接分享出去就行。如果希望更多同事用起来还可以用 Nginx 把这个链接反代到内网域名上配上 HTTPS 证书体验完全像一个正规的 SaaS 应用。5.1 最后再分享一个小技巧如果你手头有不止一台空闲机器我建议你把 Dify 部署在局域网内带宽比较稳定的那台机器上然后把“大模型推理”和“Dify 服务”拆开跑。也就是说一台机器专门跑 Ollama 负责推理另一台跑 Dify 负责业务逻辑和知识库。这样做的最大好处是跑大模型时显卡和内存都会被打满如果 Dify 也在这台机器上用户访问后台都会变得很卡拆开之后两边都轻松问题摸排也会简单很多——模型不回复只看 Ollama 机器应用页面打不开只看 Dify 机器不会互相干扰。这个架构听起来复杂其实只是 Base URL 从host.docker.internal改成对端机器的 IP 而已但运维体验会好上一个档次。