简介:这份资源面向需要在企业内部落地大模型应用的技术团队与运维人员,围绕Dify、Ollama与DeepSeek-r1三件套,提供一套可离线运行的私有化部署方案,解决数据不出内网、模型自主可控与业务集成的问题。压缩包共36个文件,约97.99MB,包含30张png部署过程截图、1份pdf说明文档、1个json与1个service配置文件、1个docker-compose-linux-x86_64编排文件、1个tgz离线安装包及1个主目录文件,覆盖环境准备、容器编排、服务注册与配置落地等环节。目前已有4766人学习下载。读者可据此获得从Docker环境搭建到Dify、Ollama、DeepSeek-r1联调的完整参考,借助截图与配置文件快速复现部署流程,理解各组件职责与集成方式,并沉淀可复用的私有化部署与排错思路,适合具备一定Linux与容器基础的中高级开发者。
1. 幕僚云私有化部署 Dify+Ollama+DeepSeek-r1:一套能落地的内网 AI 应用栈
很多团队在评估 AI 应用平台时,第一反应是直接用公有云 API,但真正把数据喂进去之前,合规和网络隔离这两关就过不去。幕僚云私有化部署 Dify+Ollama+DeepSeek-r1 这套组合,解决的就是这个问题:Dify 负责应用编排和前端交互,Ollama 负责本地模型推理,DeepSeek-r1 负责提供推理能力,三者全部跑在内网服务器上,数据不出机房。适合谁?适合有内网算力、需要把大模型能力封装成内部工具、又不想把业务数据交给第三方的团队。整套方案的核心价值不是“能跑”,而是“能稳定跑、能被人用、能持续维护”。下面按选型、部署、参数、排错、进阶的顺序拆开讲。
2. 为什么是 Dify+Ollama+DeepSeek-r1:选型逻辑与资源账
2.1 三个组件各自解决什么问题
Dify 在这个组合里扮演的是“应用层”角色。它提供可视化的工作流编排、知识库管理、对话历史、API 网关和多租户隔离。如果没有 Dify,你要自己写前端、自己管会话、自己做 RAG 检索,工作量至少翻三倍。Ollama 扮演的是“推理运行时”角色,它把模型加载、显存管理、并发调度这些脏活封装成一条命令,省掉了自己写推理服务的时间。DeepSeek-r1 扮演的是“推理能力”角色,它在数学、代码和逻辑推理任务上的表现,比同尺寸的通用对话模型更稳,适合做内部知识问答和辅助决策。
这三个组件的边界很清晰:Dify 不碰模型权重,Ollama 不碰应用逻辑,DeepSeek-r1 不碰业务数据。这种解耦带来的好处是,任何一个组件升级或替换,另外两个基本不用动。常见做法是,把 Dify 和 Ollama 部署在同一台 GPU 服务器上,通过 Docker 网络互通,减少网络延迟。
2.2 硬件资源怎么算才不翻车
DeepSeek-r1 有多个尺寸,私有化部署最常用的是 7B、14B、32B 三个量级。选哪个,取决于你的并发量和显存。下面这张表是我在几个内网环境里实测后整理的参考值,模型量化方式统一按 Q4_K_M 算:
| 模型尺寸 | 最低显存 | 推荐显存 | 并发 5 人时首 token 延迟 | 适用场景 |
|---|---|---|---|---|
| 7B | 6GB | 8GB | 0.8-1.2s | 个人助手、简单问答 |
| 14B | 10GB | 12GB | 1.5-2.5s | 小团队知识库 |
| 32B | 20GB | 24GB | 3-5s | 部门级推理任务 |
如果显存不够,Ollama 会直接报 out of memory,而不是自动降级。所以选型时宁可留 20% 余量,也不要卡着最低线跑。CPU 方面,至少 8 核,内存建议 32GB 起步,因为 Dify 的 API 服务和数据库也会占资源。磁盘方面,模型文件本身 7B 约 4-5GB,32B 约 20GB,加上 Dify 的镜像和日志,预留 100GB 比较稳妥。
2.3 网络与权限的边界设计
私有化部署不等于完全断网。Dify 在初始化时需要拉取镜像和依赖,Ollama 在拉取模型时也需要访问模型仓库。常见做法是,在一台能出网的机器上先把镜像和模型文件下载好,再通过内网传输到目标服务器。如果目标服务器完全不能出网,就需要提前准备离线包。
权限方面,Dify 默认用 PostgreSQL 存元数据,用 Redis 做缓存,用 MinIO 存文件。这三个服务如果暴露在公网,风险很大。我一般会把它们绑在 Docker 内部网络,只把 Dify 的 Web 端口映射到内网 IP,再通过反向代理加一层认证。Ollama 的 11434 端口也不要直接暴露,只允许 Dify 所在容器访问。
3. 用 Docker Compose 把 Dify 和 Ollama 跑起来
3.1 目录结构和环境变量准备
先规划目录,避免后期数据卷乱飞。我习惯在 /opt/ai-stack 下建三个子目录:dify、ollama、data。dify 放 compose 文件和配置,ollama 放模型,data 放数据库和文件存储。下面是一个最小化的目录结构:
/opt/ai-stack/ ├── dify/ │ ├── docker-compose.yml │ └── .env ├── ollama/ │ └── models/ └── data/ ├── postgres/ ├── redis/ └── minio/.env 文件里需要改的变量不多,但有几个必须改。Dify 的默认数据库密码和密钥都是弱口令,部署前一定要换掉。下面是我常用的 .env 片段:
# Dify 数据库配置 POSTGRES_PASSWORD=换成你自己的强密码 POSTGRES_DB=dify POSTGRES_USER=dify # Dify 密钥,用于加密会话 SECRET_KEY=用 openssl rand -base64 42 生成 # Ollama 地址,指向同一 Docker 网络内的服务名 OLLAMA_API_BASE_URL=http://ollama:11434 # Dify Web 端口 EXPOSE_NGINX_PORT=8080SECRET_KEY 不要用默认值,否则重启后会话会失效。生成命令是openssl rand -base64 42,这个长度足够。OLLAMA_API_BASE_URL 写服务名而不是 IP,是因为 Docker Compose 会自动做 DNS 解析,容器重建后 IP 变了也不影响。
3.2 编写 docker-compose.yml 并启动
下面这份 compose 文件是我在多个内网环境里验证过的版本,去掉了不必要的服务,只保留 Dify 核心组件和 Ollama。注意 ollama 服务加了 deploy.resources 限制,防止它把整台机器的显存吃满:
version: '3.8' services: ollama: image: ollama/ollama:latest container_name: ollama volumes: - /opt/ai-stack/ollama/models:/root/.ollama ports: - "127.0.0.1:11434:11434" deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] restart: unless-stopped dify-api: image: langgenius/dify-api:latest container_name: dify-api env_file: .env depends_on: - ollama - postgres - redis volumes: - /opt/ai-stack/data/minio:/app/storage restart: unless-stopped dify-web: image: langgenius/dify-web:latest container_name: dify-web environment: - CONSOLE_API_URL=http://dify-api:5001 ports: - "8080:3000" depends_on: - dify-api restart: unless-stopped postgres: image: postgres:15-alpine container_name: dify-postgres environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} volumes: - /opt/ai-stack/data/postgres:/var/lib/postgresql/data restart: unless-stopped redis: image: redis:7-alpine container_name: dify-redis volumes: - /opt/ai-stack/data/redis:/data restart: unless-stopped启动命令是docker compose up -d。第一次启动时,Dify 会自动执行数据库迁移,日志里看到Running migrations就说明在初始化。如果卡在迁移超过 2 分钟,大概率是数据库连接有问题,检查 POSTGRES_PASSWORD 是否和 postgres 服务里的一致。
Ollama 的 GPU 支持需要宿主机先装好 NVIDIA 驱动和 nvidia-container-toolkit。如果docker compose up后 ollama 容器起不来,先跑nvidia-smi确认驱动正常,再跑docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi确认容器能访问 GPU。
3.3 拉取 DeepSeek-r1 并验证推理
Ollama 启动后,进入容器拉模型。命令是docker exec -it ollama ollama pull deepseek-r1:7b。如果内网不能出网,需要提前在能出网的机器上ollama pull,然后把/root/.ollama/models整个目录拷贝到目标服务器的对应卷里。
拉完后验证:docker exec -it ollama ollama run deepseek-r1:7b,输入一句“用一句话解释递归”,看是否有正常输出。如果输出乱码或中断,先检查显存是否够。7B 模型 Q4 量化后约 4.5GB,如果显存只有 4GB,会直接 OOM。
验证通过后,在 Dify 里配置模型。登录 Dify 控制台,进入“设置-模型供应商”,选择 Ollama,Base URL 填http://ollama:11434,模型名称填deepseek-r1:7b。保存后,在“模型列表”里应该能看到这个模型。如果看不到,检查 Dify API 容器能否 ping 通 ollama 服务:docker exec -it dify-api ping ollama。
4. 参数调优:让 DeepSeek-r1 在 Dify 里跑得稳
4.1 Ollama 侧的关键参数
Ollama 默认的并发数是 1,意味着同时只能处理一个请求。如果团队有 5 个人同时用,后面的人会排队。可以通过环境变量OLLAMA_NUM_PARALLEL调整,但不要超过显存能承受的上限。7B 模型在 8GB 显存上,建议设为 2;14B 在 12GB 显存上,建议设为 1。
另一个参数是OLLAMA_KEEP_ALIVE,控制模型在内存里保留多久。默认是 5 分钟,如果团队使用频率高,可以设为-1让它常驻,避免反复加载。但常驻会一直占显存,如果服务器上还有别的任务,就要权衡。
在 compose 文件里加环境变量:
environment: - OLLAMA_NUM_PARALLEL=2 - OLLAMA_KEEP_ALIVE=-1 - OLLAMA_HOST=0.0.0.0OLLAMA_HOST 设为 0.0.0.0 是为了让 Dify 容器能访问,但端口映射只绑了 127.0.0.1,所以外部仍然访问不到。
4.2 Dify 侧的模型参数
Dify 在调用 Ollama 时,会传递 temperature、top_p、max_tokens 这些参数。DeepSeek-r1 对 temperature 比较敏感,做知识问答时建议 0.3-0.5,做创意生成时可以到 0.7-0.9。max_tokens 不要设太大,7B 模型在 8GB 显存上,输出 2048 token 就可能触发 OOM。我一般设 1024,够用且稳。
在 Dify 的“模型配置”里,有一个“流式输出”开关。如果内网带宽充足,建议打开,用户体验会好很多。但流式输出对 Ollama 的并发压力更大,如果发现响应变慢,可以先关掉测试。
4.3 知识库检索的参数配合
如果 Dify 里挂了知识库,检索参数会直接影响最终回答质量。Top K 设 3-5 比较合适,太大容易引入无关内容,太小可能漏掉关键信息。Score 阈值建议 0.5,低于这个值的片段直接丢弃。分块大小设 500-800 字符,重叠 50-100 字符,这个范围对中文文档比较友好。
这些参数没有绝对最优值,需要根据你的文档类型和问题分布来调。我一般会先跑 20 个典型问题,看召回率和准确率,再微调。如果发现回答经常“编造”知识库里没有的内容,先把 temperature 降到 0.3,再把 Score 阈值提到 0.6。
5. 避坑与排查:私有化部署里最容易翻车的 5 个点
5.1 容器启动后 Dify 页面打不开
现象:docker compose ps显示所有容器都是 Up,但浏览器访问 8080 端口超时。
原因:Dify Web 容器默认监听 3000 端口,映射到宿主机的 8080。如果宿主机防火墙没放行 8080,或者 Dify Web 容器内部启动失败,都会导致这个问题。
解决:先docker logs dify-web看日志,如果看到ready on http://0.0.0.0:3000,说明容器正常,问题在防火墙。用firewall-cmd --add-port=8080/tcp --permanent放行,再firewall-cmd --reload。如果日志里有报错,多半是 CONSOLE_API_URL 配错了,检查它是否指向 dify-api 的服务名和端口。
5.2 Ollama 拉模型时卡住不动
现象:ollama pull deepseek-r1:7b进度条长时间不动,或者报connection reset。
原因:模型仓库的网络不稳定,或者磁盘空间不足。Ollama 拉模型时会先下载到临时目录,再解压到 models 目录,如果磁盘剩余空间小于模型大小的 2 倍,就会失败。
解决:先df -h看磁盘,确保 /opt/ai-stack/ollama/models 所在分区有足够空间。如果是网络问题,可以换时间段重试,或者用离线方式:在能出网的机器上拉好,打包/root/.ollama/models目录,传到目标服务器解压。
5.3 Dify 调用模型时报 500 错误
现象:在 Dify 里测试模型,返回 500,日志里看到Connection refused或Timeout。
原因:Dify API 容器无法访问 Ollama 服务。常见原因是 Ollama 没有和 Dify 在同一个 Docker 网络里,或者 Ollama 的 OLLAMA_HOST 没设为 0.0.0.0。
解决:docker exec -it dify-api curl http://ollama:11434/api/tags,如果返回模型列表,说明网络通。如果不通,检查 compose 文件里两个服务是否在同一个 network 下。默认情况下,同一个 compose 文件里的服务会自动加入同一个网络,但如果你手动指定了 network,就要确保两边一致。
5.4 模型输出到一半突然中断
现象:对话进行到一半,输出突然停止,Dify 界面显示“连接中断”。
原因:Ollama 的默认超时时间较短,如果模型推理时间超过阈值,连接会被断开。另外,如果显存不足,Ollama 会杀掉当前推理进程。
解决:在 Dify 的模型配置里,把超时时间从默认的 60 秒调到 300 秒。同时检查nvidia-smi,看推理时显存占用是否接近上限。如果是,换更小的模型,或者降低 max_tokens。
5.5 重启后 Dify 数据丢失
现象:服务器重启后,Dify 里的应用、知识库、对话记录全部消失。
原因:compose 文件里没有把 PostgreSQL、Redis、MinIO 的数据目录挂载到宿主机。容器删除后,数据也跟着没了。
解决:检查 compose 文件里每个有状态服务的 volumes 配置。PostgreSQL 要挂/var/lib/postgresql/data,Redis 要挂/data,MinIO 要挂/app/storage。挂载后,即使容器重建,数据也在宿主机上。另外,定期备份/opt/ai-stack/data目录,这是最后的后悔药。
6. 进阶技巧:用 Dify 工作流把 DeepSeek-r1 封装成内部工具
6.1 用工作流做多步推理
Dify 的工作流功能可以把一个复杂任务拆成多个节点,每个节点调用一次模型。比如做一个“合同审查助手”:第一个节点提取合同关键条款,第二个节点对比内部规则库,第三个节点生成审查意见。每个节点都可以用 DeepSeek-r1,但 temperature 和 prompt 不同。
这种做法的好处是,每个节点的输出都可以被人工检查,避免一次性生成大段内容后难以定位错误。工作流的编排在 Dify 控制台里拖拽即可,不需要写代码。但要注意,每个节点都会消耗一次推理时间,如果节点太多,总延迟会很高。我一般控制在 3-4 个节点以内。
6.2 用 API 把能力开放给内部系统
Dify 每个应用都可以生成 API Key,内部系统通过 HTTP 调用。下面是一个 Python 调用示例:
import requests # Dify 应用的 API 地址,替换成你的内网 IP 和端口 url = "http://192.168.1.100:8080/v1/chat-messages" headers = { "Authorization": "Bearer app-xxxxxxxx", # 在 Dify 控制台生成 "Content-Type": "application/json" } payload = { "inputs": {}, "query": "帮我总结这份文档的要点", # 用户输入 "response_mode": "blocking", # 阻塞模式,等完整结果 "user": "internal-user-001" # 用户标识,用于区分会话 } response = requests.post(url, headers=headers, json=payload, timeout=300) print(response.json()["answer"])这段代码的关键参数是 response_mode,blocking 表示等模型生成完再返回,适合后台任务;streaming 表示流式返回,适合前端对话。timeout 要设大一点,DeepSeek-r1 在复杂问题上可能需要 1-2 分钟。user 字段用于 Dify 区分不同用户的会话历史,如果传同一个值,会话会串。
6.3 监控与日志:知道系统什么时候会挂
私有化部署最怕的是“悄无声息地挂了”。我一般会加两个监控:一是 Ollama 的显存占用,用nvidia-smi --query-gpu=memory.used --format=csv -l 5每 5 秒记录一次;二是 Dify 的 API 响应时间,在 Nginx 日志里统计 P95 延迟。
如果显存占用持续超过 90%,说明并发太高或模型太大,需要调整。如果 P95 延迟突然从 2 秒跳到 10 秒,多半是有人在跑长文本推理,可以限制单次请求的 max_tokens。
日志方面,Dify 的 API 日志在docker logs dify-api,Ollama 的日志在docker logs ollama。建议把这两个日志接到内部的日志系统里,出问题时能快速定位。我自己的习惯是,每次调整参数后,先跑 10 个典型问题,看日志里有没有异常,再放开给团队用。这套组合的稳定性,三分靠部署,七分靠调参和监控。希望帮到你。
本文还有配套的精品资源,点击获取