Ollama+DeepSeek+Docker+Dify本地RAG知识库部署
简介面向希望在本地搭建个人知识库的开发者与 AI 爱好者这份文档以 ollama、deepseek、docker 与 Dify 四件工具的协同为主线梳理从零搭建自用问答系统的完整路径适合具备基础命令行操作能力、想低成本跑通本地大模型检索方案的中级学习者。压缩包内为 1 个 doc 文档约 5.19MB以图文混排方式记录各环节的关键界面与参数涵盖模型下载与环境变量设置、docker-desktop 安装、Dify 容器化启动、知识库分词配置以及聊天应用接入 ollama 端口等内容。文档对易错处保留了提示式说明例如模型体积与下载耗时的取舍、命令行窗口需保持运行以维持模型服务、容器内访问宿主机端口的地址写法等便于读者对照排查。目前已有 3400 人学习可作为搭建私有知识库时的手边参照。1. 从一台 16G 内存的 Windows 开始ollama deepseek Docker Dify 这套组合到底能干什么很多人第一次把 deepseek 跑在自己电脑上是在命令行里敲一句ollama run问两句“你好”然后就关掉了。这其实只走完了半程——真正让本地大模型有用的是后半截Dify 把 ollama 提供的本地模型接口和你硬盘里那堆 PDF、Word、Markdown 接起来让模型只基于你自己的资料回答。这套 ollama deepseek Docker Dify 的组合本质是把“模型推理”和“知识检索”拆成两个独立进程再用 HTTP 把它们缝在一起。它适合手上有几十份内部文档、又不想把资料传到外部接口的从业者也适合想搞懂 RAG 到底怎么落地的新手因为整条链路都在自己机器上每一层都能打开看。网上流传的这类部署课程资源不少但大多只给命令不讲链路照着敲完一旦连不上就卡死这篇就按我实际拆过的顺序把每一步的判断依据和翻车点摊开讲。2. 装 ollama 并让模型离开 C 盘Windows 安装、环境变量与 deepseek-r1 拉取ollama 在这套架构里扮演的是“模型运行时”它负责把权重加载进显存、对外暴露一个 HTTP 接口、把推理结果吐回来。把它当作本地版的模型服务端来理解后面所有配置就顺了Dify 是客户端ollama 是服务端两者通过 11434 端口对话。这一章先把服务端装稳、把模型放到正确的盘上不然后面容器一跑C 盘直接告急。2.1 安装包落地与第一次版本校验Windows 上的安装没什么花活官网下载对应安装包双击一路下一步装完托盘里会多一个羊驼图标表示后台服务已经起来了。真正的坑在“装完之后怎么确认它是真的可用”而不是“图标亮了就算成功”。装完先别急着拉模型用两条命令把客户端和服务端的状态摸清楚。# 打开 PowerShell确认 ollama 已经进了 PATH ollama --version # 列出当前已下载的模型刚装完应该是一张空表 ollama list # 查看服务端监听状态确认 11434 端口有人守着 Get-NetTCPConnection -LocalPort 11434 -ErrorAction SilentlyContinueollama --version验证的是命令行客户端能不能被找到如果这条报“不是内部或外部命令”说明安装时 PATH 没写进去重装或者手动把安装目录加进系统变量都行。ollama list走的是客户端到服务端的本地调用它能正常返回空表说明后台服务已经跑起来了——这比看托盘图标靠谱得多。第三条是个很多人会忽略的动作11434 是 ollama 的默认端口后面 Dify 要连的就是它这里先确认端口处于监听状态等于提前排掉一类“容器连不上”的问题。需要提醒的是Windows 托盘启动的 ollama 和你手动ollama serve启动的是同一个东西别重复启动否则会撞端口。如果托盘已经常驻就不要再开一个命令行窗口跑 serve。2.2 用 OLLAMA_MODELS 把权重挪出系统盘deepseek-r1 的 1.5B 版本体积还算克制但只要你顺手拉了 7B、8B或者以后想加一个 embedding 模型几十 GB 的权重默认全塞在C:\Users\用户名\.ollama\models下系统盘很快就红。我的习惯是装机第一步就把模型目录挪走而不是等满了再搬——搬一次要停服务、要移动大文件、要改环境变量中途断电就是一堆半截文件。正确顺序是“先停服务、再搬文件、最后设变量”三步顺序错了会出现“设了变量但 ollama 还在读老路径”的玄学现象。原因是 ollama 启动时读一次环境变量运行期间不会重读你在服务还活着的时候改系统变量它当然无感。# 1. 先把托盘里的 Ollama 完全退出确认没有残留进程 Get-Process ollama* -ErrorAction SilentlyContinue | Stop-Process -Force # 2. 建新目录把已有模型整体搬过去 New-Item -ItemType Directory -Force -Path D:\ollama\models | Out-Null Move-Item $env:USERPROFILE\.ollama\models\* D:\ollama\models\ -Force # 3. 写入用户级环境变量重开终端后生效 setx OLLAMA_MODELS D:\ollama\models setx OLLAMA_HOST 0.0.0.0:11434OLLAMA_MODELS指向的是模型权重的根目录搬完之后ollama list还能列出原来那些模型说明迁移成功如果列表变空了八成是搬到了子目录里多套了一层models。OLLAMA_HOST设成0.0.0.0:11434而不是默认的127.0.0.1:11434是为了让 Docker 容器能通过宿主机地址访问到它——只监听回环地址的话容器那一侧是打不通的这个点在第四章会再撞一次。除了这两个还有几个值得一并设掉的变量变量名建议值作用与取舍OLLAMA_MODELSD:\ollama\models权重落盘位置越大越该挪出系统盘OLLAMA_HOST0.0.0.0:11434监听地址容器访问必需OLLAMA_KEEP_ALIVE30m模型在显存里的驻留时长默认 5 分钟调大避免频繁冷加载OLLAMA_NUM_PARALLEL1并发请求数显存吃紧就保持 1OLLAMA_KEEP_ALIVE这个参数在知识库场景里很实用。RAG 的典型交互是“先检索、再生成”用户点一次发送模型可能被调用两次如果间隔超过默认的 5 分钟第二次又得重新加载权重体感上就是“第一次回答快、隔一会儿再问就卡住十几秒”。设成 30 分钟能明显改善这种抖动代价是显存占用不被释放。2.3 拉取 deepseek-r1 并跑通第一次推理模型选择上1.5B 适合先跑通链路不适合做正式的知识库问答。参数量决定了它对长上下文和中文语义的把握能力1.5B 在“根据资料回答问题”这种任务上很容易出现两种毛病要么无视检索到的内容自己编要么把资料里的原句原样抄一遍不回答问题。我的建议是先用 1.5B 把所有配置打通确认链路没问题再换成更大的版本压测效果。# 拉取 1.5B 版本第一次会下载权重耗时取决于带宽 ollama pull deepseek-r1:1.5b # 进交互模式做一次冒烟测试 ollama run deepseek-r1:1.5b # 不进交互直接用 API 发一条方便脚本化验证 curl http://127.0.0.1:11434/api/generate -d {\model\:\deepseek-r1:1.5b\,\prompt\:\用一句话解释什么是向量检索\,\stream\:false}ollama pull只下载不加载可以在不占显存的情况下把模型备好ollama run既下载又进交互适合人肉验证。第三条 curl 是我更推荐的方式因为它验证的是 HTTP 接口而不是命令行封装后面 Dify 走的就是这条路——命令行能通不代表接口能通尤其是改过OLLAMA_HOST之后。规格怎么挑给一张按经验值的对照表实际占用会随量化版本和上下文长度浮动模型规格大致内存/显存需求适用场景deepseek-r1:1.5b4GB 以内跑通链路、低配机器验证deepseek-r1:7b/8b812GB个人知识库日常问答的主力档deepseek-r1:14b16GB 以上对回答质量有要求、机器够硬deepseek-r1:32b24GB 以上多文档交叉推理普通办公机不建议拉完之后记得看一眼ollama ps它会告诉你模型是否已经加载、占了多少显存。这个命令在排查“为什么回答很慢”时比看任务管理器准因为模型可能被换出到内存里任务管理器上看不出区别。3. 用 Docker Desktop 把 Dify 拉起来compose 编排、镜像加速与端口自检Dify 在这套组合里的角色是“应用层”它管知识库的切分和索引、管对话应用的编排、管模型供应商的接入。它自己不跑模型所有推理都转发给 ollama。官方提供的是 Docker Compose 编排文件一条命令拉起一组容器api、worker、web、db、redis、nginx 等所以这一章的重点不是“怎么点下一步”而是“容器起来之后怎么确认每一层都活着”。3.1 Docker Desktop 安装与 WSL2 后端确认Windows 上跑 DifyDocker Desktop 的后端必须走 WSL2不能是旧的 Hyper-V 模式否则容器网络和文件挂载都会出各种奇怪问题。安装包下载完双击安装向导里那个“Use WSL 2 instead of Hyper-V”的选项要保持勾选。装完重启一次托盘出现鲸鱼图标右下角状态是 Running 才算法。# 确认 WSL 版本与已安装的发行版 wsl --status wsl --list --verbose # 确认 Docker 引擎可用能跑通说明后端没问题 docker version docker info --format {{.ServerVersion}} | {{.OSType}} | {{.Architecture}}wsl --status里如果显示默认版本是 1用wsl --set-default-version 2改掉再重启 Docker Desktop。docker info那条格式化输出能一次性看到服务端版本、系统类型和架构比docker version的一屏输出更好读。这三条都过了再往下走不然 compose 阶段报的错会把你带偏到镜像问题上实际是虚拟化层没通。还有一个容易被忽略的点Docker Desktop 默认会随开机启动如果你同时装了别的虚拟化软件某些安卓模拟器、虚拟机它们会抢 WSL2 的资源表现是 Docker 时好时坏。遇到这种间歇性抽风先关掉其它虚拟化软件再试。3.2 镜像加速与 .env 里的端口设置Dify 的 compose 文件要拉十几个镜像国内网络环境下不加加速基本卡在 pull 阶段。加速配置在 Docker Desktop 的 Settings → Docker Engine 里编辑那个 JSON往registry-mirrors数组里填你自己可用的加速地址保存后 Docker 会自动重启生效。{ registry-mirrors: [ https://你的加速地址一, https://你的加速地址二 ], features: { buildkit: true } }填多个地址是有讲究的Docker 会按顺序尝试第一个不通自动切下一个单个地址偶尔抽风不至于让整条 pull 挂死。改完一定要点 Apply Restart只在编辑器里保存是不生效的。验证方式是docker info输出里能看到Registry Mirrors那一段列出的地址。然后是端口。Dify 默认通过 nginx 容器把 Web 界面暴露在宿主机 80 端口配置文件在dify/docker/.env里键名是EXPOSE_NGINX_PORT。如果你机器上 80 已经被 IIS、Apache 或者别的服务占了compose 起的时候 nginx 容器会直接起不来报端口绑定失败。# 进到 Dify 源码解压后的 docker 目录 cd D:\dify\docker # 看一眼端口和关键配置不修改也能跑但心里要有数 grep -E EXPOSE_NGINX_PORT|EXPOSE_NGINX_SSL_PORT .env端口冲突的判断方法很简单netstat -ano | findstr :80看有没有别的进程占着。占了就改.env里的EXPOSE_NGINX_PORT比如改成 8080那访问地址就变成http://127.0.0.1:8080/signin。这里要提醒一句改完端口后如果之前已经起过容器需要docker compose down再up -d光restart不会重新读端口映射。3.3 compose 启动与容器状态自检启动命令有新旧两种写法docker-composev1带横杠和docker composev2空格。新版 Docker Desktop 自带的是 v2老的教程里写的是 v1两条都能用但别在一台机器上混着来容易因为 compose 文件版本差异出问题。# 在 dify/docker 目录下执行-d 表示后台运行 docker compose up -d # 看容器列表和健康状态重点关注 State 和 Health 两列 docker compose ps # 跟着 api 容器的日志走初始化数据库失败会在这里暴露 docker compose logs -f apiup -d第一次执行会拉镜像、建数据表、初始化管理员耗时可能十几分钟中途别 CtrlC。docker compose ps是判断“到底起没起来”的第一现场正常状态下 api、worker、web、db、redis、nginx 应该是 Up 或 Up (healthy)如果有容器反复重启State 那一列会显示 Restarting这时候去看它的日志八成是数据库连不上或者环境变量缺失。docker compose logs -f api里最值得关注的是数据库迁移那一段。如果看到连接 db 超时的报错先确认 db 容器是不是 healthy再确认.env里的数据库密码和 compose 文件里的一致。这两处对不上是最常见的初始化失败原因而且报错信息往往指向“认证失败”而不是“密码错了”容易误判。全部容器 Up 之后浏览器访问http://127.0.0.1/signin或你改过的端口第一次会要求设置管理员账号设完就进主界面了。这一步过了说明应用层已经就绪接下来才是真正把模型接进来。4. Dify 接上 ollama 与知识库模型供应商、分段索引与聊天应用这一章是整套方案的核心。前面两章装的是“零件”这一章把它们装成一台能用的机器。链路上有三个关键节点Dify 怎么找到 ollama网络地址、知识库怎么把文档变成可检索的向量切分与索引、聊天应用怎么把检索结果喂给模型上下文注入与参数。三个节点任何一个配错表现都是“能聊天但答不准”很难一眼看出问题在哪。4.1 配置 Ollama 供应商host.docker.internal 与 11434这是新手翻车率最高的一步。在 Dify 的模型供应商设置里选 Ollama填的 Base URL 如果照抄教程写成http://127.0.0.1:11434大概率连不上。原因不复杂Dify 的 api 容器跑在自己的网络命名空间里容器内的127.0.0.1指向容器自己不是你的 Windows 宿主机。ollama 装在宿主机上容器当然找不到。Docker Desktop 为此提供了一个特殊域名host.docker.internal容器内解析它会得到宿主机的地址。所以正确的填法是Base URL: http://host.docker.internal:11434 模型名称: deepseek-r1:1.5b 模型类型: LLM填完之后点“保存”Dify 会立刻发一次请求做连通性校验成功的话下方会出现模型列表失败会直接报错。这一步能过说明网络链路通了如果报连接超时按顺序排查三件事ollama 服务是否在跑、OLLAMA_HOST是否设成了0.0.0.0、宿主机防火墙有没有拦 11434。模型名称这一栏要和ollama list里的名字完全一致包括 tag。deepseek-r1:1.5b和deepseek-r1在 ollama 里是两个不同的引用写错了保存时会提示模型不存在。这一点在同时装了多个规格的机器上特别容易搞混。4.2 建知识库分段策略与 Embedding 模型知识库的本质是把文档切成小段、每段转成一个向量存起来提问时先算问题向量、再找最相近的几段。这里有两个决策点切多粗、用什么模型转向量。切分上Dify 提供通用分段和父子分段两种模式。通用分段就是按固定长度切配置项是分段长度和重叠长度父子分段会保留段落层级检索时命中子段、返回父段适合结构清晰的手册类文档。我的经验是技术文档、产品手册用父子分段问答对、FAQ 用通用分段分段长度 512 字符、重叠 50 字符起步文档里句子特别长的再往上调。# 拉一个中文效果稳定的向量模型Ollama 直接提供 ollama pull bge-m3 # 确认拉下来了记住名字等下在 Dify 里要原样填 ollama list | grep -i bgebge-m3是多语言向量模型中文语义检索表现稳体积也在可接受范围。拉下来之后回到 Dify 的 Ollama 供应商页面再添加一个模型类型选Text Embedding名称填bge-m3Base URL 和刚才一样。添加成功后知识库创建时就能在索引方式里选“高质量向量检索”。索引方式那两个选项值得说清楚选“高质量”会调用 embedding 模型把每段转成向量检索时走向量相似度语义匹配能力强代价是要额外跑一个模型、建索引慢“经济”模式只做关键词倒排不调模型快但只能命中字面相同的词问“怎么配置端口”可能检索不到写着“修改监听地址”的段落。做个人知识库没有理由省这一步选高质量。文档上传后点“下一步”确认分段预览没问题再保存然后等索引完成。索引时间取决于文档数量和机器性能几十页 PDF 通常几分钟内能跑完状态从“排队中”变成“可用”才算真正入库。中途刷新页面看到进度卡住不动先去看 worker 容器的日志索引任务是它跑的。4.3 聊天应用里挂知识库并调参数知识库建好只是“有货”还得让聊天应用去取货。在 Dify 里创建一个空白应用类型选聊天助手进编排界面后在“上下文”那一栏点添加选中刚建好的知识库。这一步做了之后每次提问都会先触发一次检索命中的片段作为上下文拼进 prompt 再发给模型。模型参数这块我一般在 RAG 场景下调成偏保守的一组参数建议值调整理由temperature0.30.5越低越贴近检索内容越高越发散知识库问答不需要发散top_p0.9与温度配合控制采样范围最大 token2048回答够用即可太长会拖慢首字延迟上下文长度4096 起要能装下检索回来的几个片段加问题本身检索侧还有一组参数在知识库的“召回设置”里Top K 控制返回几个片段score 阈值控制低于多少分直接丢弃。Top K 设 35 比较合适设太大反而会稀释重点模型面对一堆弱相关片段更容易跑偏阈值一开始可以设 0.5 左右跑几条真实问题看命中情况再微调。配好之后在预览窗口做两件事一是问一个知识库里明确写了答案的问题看回答有没有引用来源、引用的是不是正确的那一段二是问一个知识库里完全没有的问题看模型是老实说“资料中没有”还是硬编。第二个测试比第一个重要很多“RAG 效果不好”其实是模型在无检索结果时不肯认输。5. 避坑清单五个把新手卡在半路的真实现场这一章记录的是我在不同机器上重复遇到过的五类问题每一条都按“现象 → 原因 → 解决”写。它们的共同点是报错信息指向的地方往往不是真正出问题的地方照着报错去搜会绕很远。5.1 现象compose 卡在 pull 阶段进度条不动或反复重试原因基本是镜像拉取通道不畅跟 Dify 本身无关跟 compose 文件版本也无关。Docker Hub 的默认源在部分网络环境下会超时表现是某几个镜像拉了一半停住docker compose ps里对应容器一直是 Created 状态。解决分两步先在 Docker Engine 配置里加registry-mirrors并重启引擎再执行docker compose pull单独把镜像拉完最后才up -d。把拉镜像和起容器拆成两步的好处是卡住的时候能明确知道是网络问题还是配置问题。如果只有某一个镜像死活拉不下来可以单独docker pull 镜像名看具体报错比在一堆并行拉取里找线索快得多。5.2 现象Dify 里填127.0.0.1:11434报连接失败但浏览器能打开 ollama原因就是容器网络隔离。容器内的回环地址指向容器自身宿主机上的服务对它不可见。这不是配置错误是网络模型决定的。解决办法是把地址换成http://host.docker.internal:11434。这个域名在 Docker Desktop 的 Windows 和 macOS 后端下默认可用Linux 上需要在 compose 里给服务加extra_hosts: - host.docker.internal:host-gateway。另外别忘了宿主机侧的OLLAMA_HOST必须是0.0.0.0:11434只监听127.0.0.1的话即使域名解析对了也连不上因为服务根本没在那个网卡上等连接。5.3 现象设了OLLAMA_MODELS但 ollama 还在往 C 盘写原因是环境变量在服务启动时只读一次。你在托盘图标还亮着的时候改系统变量运行中的进程不会重读新拉的模型照样落到老路径。解决顺序是死的先退出托盘里的 Ollama、确认进程清空、再设变量、再重启。验证方法是拉一个小模型然后看新目录下有没有多出blobs和manifests两个子目录。还有个小概率情况是变量设到了系统级但当前终端是管理员权限开的用户级变量读不到重开一个普通终端再试。5.4 现象知识库建好了提问却完全不引用资料回复像是凭空生成原因可能是三个层面的分段切得太碎导致语义不完整、索引方式选成了关键词模式、或者检索阈值设得太高导致一条都没召回。排查从知识库的“召回测试”入口开始直接输入你的问题看它返回哪些片段、相似度分数是多少。如果一条都不返回把 score 阈值往下调如果返回的片段明显不相关说明分段有问题回去调小分段长度或者换成父子分段如果片段相关但回答还是不引用那就是应用侧没挂上知识库回去检查“上下文”那一栏是不是空的。这三层按顺序排比一上来就换模型有效得多。5.5 现象1.5B 模型在知识库问答里答非所问换了提示词也没用原因是模型容量不够。1.5B 参数量在“阅读多段检索内容并归纳回答”这个任务上能力有限典型表现是忽略检索内容自顾自答、或者把几个片段拼接起来答非所问。这不是参数没调好是模型本身撑不住。解决办法是换规格。同样的配置、同样的知识库换成 7B 或 8B 版本回答质量会有肉眼可见的提升。1.5B 的正确用法是当“链路验证器”——所有配置用它跑通确认网络、索引、上下文注入都没问题再换大模型压效果。这个顺序别反过来否则模型效果差和配置错会混在一起根本分不清是哪个的问题。6. 上线前的三条自检从 curl 探活到召回抽查配置全部跑通之后我一般不会直接开始用而是走一遍固定的自检流程。原因很简单这套链路有四五个进程任何一层半死不活的表现都是“能回答但答得怪”靠体感判断不出来。第一条是分层探活。宿主机侧和容器侧各发一次请求两边结果对比能立刻定位问题在网络层还是应用层。# 宿主机视角ollama 自己通不通 curl -s http://127.0.0.1:11434/api/tags | head -c 200 # 容器视角从 Dify 的 api 容器里访问宿主机模拟真实调用路径 docker compose exec api python -c import urllib.request; print(urllib.request.urlopen(http://host.docker.internal:11434/api/tags, timeout5).read().decode()[:200])第一条返回模型清单说明 ollama 服务本身没问题第二条如果在容器里也能返回同样的清单说明host.docker.internal解析和端口映射都通了。第二条失败而第一条成功问题一定在容器网络或OLLAMA_HOST的监听地址上不用再怀疑模型和配置。第二条是看模型驻留状态。ollama ps会显示当前加载了哪个模型、占用多少、还剩多久被卸载。知识库问答场景下如果你发现每次提问前模型都要重新加载把OLLAMA_KEEP_ALIVE调大如果显示同时加载了两个模型一个对话一个向量而显存又吃紧考虑把向量模型换小一号。第三条是召回抽查也是最能体现效果的一步。从知识库里挑 10 个问题覆盖三种类型答案明确的、需要跨段落拼的、知识库里根本没有的。前两类看召回片段是否正确、回答是否引用了来源第三类看模型会不会硬编。我习惯建一张简单的表记录结果问题类型抽查条数观察点不合格时的动作答案明确4引用片段是否命中原文调分段长度或降阈值跨段落3是否召回了多个相关片段提高 Top K无答案3是否承认资料中没有补提示词约束这张表跑一轮大概十几分钟但能提前发现八成以上的效果问题。血泪经验是不要用“随便问几句感觉还行”来代替这一步感觉这东西在 RAG 上极不可靠同一套配置换个问法结论就反过来了。从那以后我每次部署完这类本地知识库都会强制走一遍这三条自检哪怕只是换了个模型版本。因为链路的每一层都在动昨天通的今天未必通而排错的成本远高于自检的成本。希望帮到你。本文还有配套的精品资源点击获取