目录
一、环境介绍
PowerShell版本:
wsl版本:
虚拟机版本:
本机IP:
虚拟机IP:
容器宿主机IP(host.docker.internal):
Docker版本:
Docker Compose版本:
其他:
二、Dify部署
1、克隆Dify代码仓库
2、启动Dify
①在本地打包镜像
问题1:
②进入Dify 源代码的docker目录
③复制环境配置文件
④启动docker容器
⑤检查容器是否都正常
问题1:docker-db-1起不来,报错如下:
问题2:docker-ssrf_proxy起不来,报错如下:
问题3:dify-web起不来,报错如下:
⑥进入Dify
三、SearXNG部署
1、修改Dify配置文件
2、启动SearXNG服务
问题1:SearXNG起来了但是报错,报错如下:
3、使用SearXNG服务
问题1:输入http://host.docker.internal:8081后,点击保存,页面没反应或者报错,报错如下:
四、DeepSeek R1模型部署
1、ollama安装
2、修改ollama模型部署的路径
3、模型部署 DeepSeek R1
五、Embedding模型部署
六、在Dify中添加deepseek模型
问题1:
七、在Dify中添加Embeding模型添加
八、上传私有知识库
九、智能体搭建
问题1:在“工作室“建立好的应用,在点击进去时报错:
DeepSeek这么火,网络上关于本地部署大模型,然后什么搭建私有知识库的文章层出不穷,看着也不难,我就想着,找篇文章docker部署的文章,集成到Dify中,部署一个,看着简单,但是实际,好多好多坑,一个一个解决,还是决定这里结合参考的文章,再重新出一篇。
一、环境介绍
先介绍下环境,如果跟我环境差不多的应该更有参考意义:
本机:Windows 11系统,细版本是22000.1936,这个操作系统细版本应该没啥影响。
PowerShell版本:
执行命令获取:Get-Host | Select-Object Version
wsl版本:
WSL 2
虚拟机版本:
执行命令获取:wsl --list –verbose
进入虚拟机后再看下版本:
本机IP:
虚拟机IP:
容器宿主机IP(host.docker.internal):
Docker版本:
Docker Compose版本:
其他:
你要准备一个能连接外网的梯子。
二、Dify部署
1、克隆Dify代码仓库
如果不知道Dify是什么的,可以百度下,解释的文章很多。
Dify直接Docker安装。
我在我的X盘,建了一个目录,cd进去执行git操作,即克隆 Dify 源代码至本地环境:
git clone https://github.com/langgenius/dify.git
这一步出现了问题,网络没得问题,就是git的慢,我直接访问其主页,以zip的方式下载了下来,解压放到了我的x盘中,我下载好的文件也上传上去了,链接是:
https://download.csdn.net/download/qq_30168227/90369269https://download.csdn.net/download/qq_30168227/90369269
至此,我的目录结构是:
2、启动Dify
①在本地打包镜像
接下来的操作就是都要到Linux中了,像我windows上的这个路径X:\LLM\dify-main,在我WSL的Linux上默认路径就是:
接下来直接cd到/mnt/x/LLM/dify-main下:
cd /mnt/x/LLM/dify-main
然后修改Makefile中的版本号:
从原来的latest改为这种,可以不用思考,改成和我一样的。
然后cd /mnt/x/LLM/dify-main,在dify-main根目录下,执行打包镜像,请注意,这里要用到你的梯子了,不连接外网这块有些过不去,我当时是docker镜像源也加上了好几个,可以百度以下,把国内的一些都加上,遇到的问题就行,有些得连外网,有些不能连外网,连外网访问不了,反正两个网络切换,多试试就能下载好了。
make build-all
打包完成后,执行docker images命令,能看到打好的镜像:
上图中先不用看版本,我是因为某些坑,重新打了些镜像,你可以主要看下langgenius/dify-api:0.15.2和langgenius/dify-web:0.15.2有没有。
问题1:
这个时候,我遇到了一个问题,我WSL的镜像默认安装在了C盘,C盘空间不够了,所以我要进行,WSL的虚拟机迁移,也比较简单:
(1)查询虚拟机信息,关闭虚拟机
在cmd中,我的虚拟机名字什么的文章开头已经查询了,命令是wsl -l -v,出来名字、状态、版本等信息,我这里直接先关闭WSL:wsl --shutdown
(2)导出虚拟机
我新建了一个非C盘的目录,X:\WSL,将虚拟机导出过去:wsl --export Ubuntu_2204 X:\WSL\ubuntu.tar
看你虚拟机的大小,导出的时间一般都得几分钟,这个没有导出进度条,耐心等待就行。
(3)注销老虚拟机
进行了这一步才会释放原磁盘的空间。
wsl --unregister Ubuntu_2204
(4)重新导入虚拟机
wsl --import Ubuntu_2204 X:\WSL X:\WSL\ubuntu.tar --version 2
(5)再测试
刚刚第四步好后迁移就算完成,直接cmd或者powerShell中执行wsl进入虚拟机的命令,能进去就是没啥问题。
②进入Dify 源代码的docker目录
我这里就是:cd /mnt/x/LLM/dify-main/docker
③复制环境配置文件
我这里是:cp /mnt/x/LLM/dify-main/docker/.env.example /mnt/x/LLM/dify-main/docker/.env
④启动docker容器
我的Docker Compose是V2版本,如文章开头的环境信息中展示的,所以在/mnt/x/LLM/dify-main/docker使用这个命令启动:
docker compose up -d
如果你的是V1版本的,就是这个命令:
docker-compose up -d
这里附一个停止的命令:docker compose down
运行完成之后可以看到类似这种输出,显示所有容器的状态等信息:
⑤检查容器是否都正常
命令是:docker compose ps,结果如下
可以看到,我现在的都是正常的,但是实际上,我遇到了几个问题,导致有几个容器一直不断重启,一个一个排,遇到的值得记录有如下几个。
问题1:docker-db-1起不来,报错如下:
看容器报错日志的命令是:
docker logs [OPTIONS] CONTAINER,可以跟-f(持续跟踪日志输出,类似于 tail -f 命令)、-t(在日志中显示时间戳,方便定位日志产生的时间)等参数,我下面日志,执行的命令是:
docker logs docker-db-1
initdb: error: could not change permissions of directory "/var/lib/postgresql/data/pgdata": Operation not permitted fixing permissions on existing directory /var/lib/postgresql/data/pgdata ... mkdir: can't create directory '/var/lib/postgresql/data/pgdata': Permission denied mkdir: can't create directory '/var/lib/postgresql/data/pgdata': Permission denied mkdir: can't create directory '/var/lib/postgresql/data/pgdata': Permission denied
我的解决是这样的:
(1)我使用 docker inspect 命令查看容器的数据卷挂载信息,看看挂载到了哪个目录
docker inspect docker-db-1 | grep Mounts -A 10
我需要直接修改这个目录的路径,但是有个问题,就是我是WSL的虚拟机,实际磁盘用的还是windows上的X盘,在Linux上直接使用chown等命令,不得行,所以我先改下挂载的方式:
(1.1)检查 SELinux 或 AppArmor 限制
Ubuntu 系统默认启用了 AppArmor,某些情况下它可能会限制容器对文件系统的操作。
# 禁用 AppArmor:
sudo systemctl stop apparmor
sudo systemctl disable apparmor
# 临时禁用 SELinux
sudo setenforce 0
(2.2)修改下WSL的配置文件
文件路劲在Linux的/etc下:
我改好的如下:
主要是最后一条,改好保存后,重启wsl(cmd中wsl –shutdown,然后重新进入wsl)。
(2.3)检查文件系统挂载选项
查看挂载信息:使用 mount 命令查看 /mnt/x/LLM/dify-main/docker/volumes/db/data 所在文件系统的挂载选项(X盘)。
mount | grep /mnt/x
检查是否有写保护:如果挂载选项中包含 ro(只读),则需要重新挂载文件系统为可写模式。首先,卸载该文件系统:
sudo umount /mnt/x
然后,重新挂载为可写模式(假设挂载点是 /dev/sdX):
sudo mount -t drvfs X: /mnt/x -o metadata
(2)修改权限
sudo chown -R postgres:postgres /mnt/x/LLM/dify-main/docker/volumes/db/data
chmod -R 777 /mnt/x/LLM/dify-main/docker/volumes/db/data
(3)重启容器
直接docker compose重启即可,或者重启单个容器docker restart [容器 ID 或容器名称]。
问题2:docker-ssrf_proxy起不来,报错如下:
ERROR: Cannot open cache_log (/var/log/squid/cache.log) for writing;
fopen(3) error: (13) Permission denied
ERROR: logfileHandleWrite: daemon:/var/log/squid/access.log: error writing ((32) Broken pipe)
我的解决是这样的,直接基于原来的镜像,重新打一个镜像:
(1)新建目录
mkdir /mnt/x/LLM/dify-main/docker-ssrf_proxy_lyg
(2)在新目录中新建DockerFIle
FROM ubuntu/squidRUN touch /var/log/squid/cache.logRUN chmod -R 777 /var
(3)重新打包镜像
cd /mnt/x/LLM/dify-main/docker-ssrf_proxy_lyg
docker build -t ubuntu/squid:0.15.4 .
打包好的镜像可以通过docker images看到:
(4)更新 docker-compose.yml 文件
如果容器是通过docker compose启动的,要修改这个文件,在 docker-compose.yml 文件中,确保已将镜像的版本(标签)更新为新的版本号:
我的docker-compose.yml在/mnt/x/LLM/dify-main/docker/docker-compose.yaml路径下。
(5)重启
在启动新版本的镜像之前,需要停止并移除当前基于旧版本镜像运行的容器。在包含/mnt/x/LLM/dify-main/docker/目录下,执行以下命令:
docker-compose down
docker-compose up -d
问题3:dify-web起不来,报错如下:
pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)
[PM2][ERROR] Permission denied, to give access to current user:
$ sudo chown undefined:undefined /.pm2/rpc.sock /.pm2/pub.sock
pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)
$ sudo chown undefined:undefined /.pm2/rpc.sock /.pm2/pub.sock
[PM2][ERROR] Permission denied, to give access to current user:
pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)
[PM2][ERROR] Permission denied, to give access to current user:
$ sudo chown undefined:undefined /.pm2/rpc.sock /.pm2/pub.sock
pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages
我的解决也是重新打一个镜像:
(1)修改Dockerfile
这个镜像的Dockerfile不用新建,直接在老的上面做修改,位置在/mnt/x/LLM/dify-main/web,修改如下:
旧的:
新的:
对比可以看出来,我注释了原来的chown和chmod命令,新增了一条chmod命令:&& chmod -R 777 /.pm2 /app/web
(2)重新打包镜像
cd /mnt/x/LLM/dify-main/web
docker build -t langgenius/dify-web:0.15.4 .
(3)更新 docker-compose.yml 文件并重启
文件位置和修改方式,重启方式都是一样的,这里不再赘述。
⑥进入Dify
刚刚问题都已经完成处理,所以容器都运行正常,也就是说我们已经成功在本地安装好了Dify,可以在浏览器上输入网址,直接进入,我中间重启了次wsl,没有设置静态IP,所以IP变成了172.26.106.243,进入的URL也就是:http://172.26.106.243,如下图:
三、SearXNG部署
SearXNG 是一个免费的互联网元搜索引擎,整合了各种搜索服务的检索结果。用户不会被跟踪,搜索行为也不会被分析。现在可以直接在 Dify 中使用此工具,下面介绍具体docker部署步骤。
1、修改Dify配置文件
SearXNG 的配置文件位于 /mnt/x/LLM/dify-main/api/core/tools/provider/builtin/searxng/docker/settings.yml, 配置文档可参考SearXNG官网文档。
可以按需修改配置,也可直接使用默认配置,我是直接使用的默认的,就中间因为问题改了次日志级别,后来错误解决后又改了回来,其他的都是用的默认的:
-
2、启动SearXNG服务
cd /mnt/x/LLM/dify-main
这个启动命令是原来版本的,但是我出现了问题,经过了修改,就没用这个来启动,你如果用着哥启动没得问题,那就可以使用:docker run --rm -d -p 8081:8080 -v "${PWD}/api/core/tools/provider/builtin/searxng/docker:/etc/searxng" searxng/searxng
我的端口时8080,成功后直接访问:http://172.26.106.243:8080/
尝试搜索:
问题1:SearXNG起来了但是报错,报错如下:
FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/usr/local/searxng/searx']
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
Traceback (most recent call last):
File "/usr/local/searxng/searx/webapp.py", line 87, in <module>
from searx.webadapter import (
File "/usr/local/searxng/searx/webadapter.py", line 11, in <module>
from searx.preferences import Preferences, is_locked
File "/usr/local/searxng/searx/preferences.py", line 19, in <module>
from searx import settings, autocomplete, favicons
File "/usr/local/searxng/searx/favicons/__init__.py", line 11, in <module>
from .proxy import favicon_url, favicon_proxy
File "/usr/local/searxng/searx/favicons/proxy.py", line 24, in <module>
from . import cache
File "/usr/local/searxng/searx/favicons/cache.py", line 93, in <module>
class FaviconCacheConfig(msgspec.Struct): # pylint: disable=too-few-public-methods
File "/usr/local/searxng/searx/favicons/cache.py", line 106, in FaviconCacheConfig
db_url: str = tempfile.gettempdir() + os.sep + "faviconcache.db"
^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/tempfile.py", line 315, in gettempdir
return _os.fsdecode(_gettempdir())
^^^^^^^^^^^^^
File "/usr/lib/python3.12/tempfile.py", line 308, in _gettempdir
tempdir = _get_default_tempdir()
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/tempfile.py", line 223, in _get_default_tempdir
raise FileNotFoundError(_errno.ENOENT,
我的解决是这样的,直接基于原来的镜像,重新打一个镜像:
(1)新建目录
mkdir /mnt/x/LLM/dify-main/searxng_lyg
(2)在新目录中新建DockerFIle
# 基于现有的 searxng/searxng 镜像FROM searxng/searxng# 创建 /usr/tmp 目录并设置权限RUN mkdir -p /usr/tmp && chmod 777 /usr/tmp
(3)重新打包镜像
cd /mnt/x/LLM/dify-main/searxng_lyg
docker build -t searxng_lyg:0.0.1 .
打包好的镜像可以通过docker images看到
(5)重启
这个镜像是直接启动的,没有通过compose,而且我为了避免网络问题,使用host网络,端口改为使用8080(使用—network host后,没法指定端口了,我的环境默认就会使用8080,根据你的具体环境来,可以使用netstat或者ss看看虚拟机监听的端口,看看你的环境用的哪个),所以直接运行命令:
docker ps,找到原来运行的镜像;
docker stop xxxx,然后stop掉原来的镜像;
再重新启动:
docker run --rm -d --add-host=host.docker.internal:host-gateway --network host -v "/mnt/x/LLM/dify-main/api/core/tools/provider/builtin/searxng/docker:/etc/searxng" searxng_lyg:0.0.1
3、使用SearXNG服务
在Dify中,以上图的路径访问过去,我的已授权那儿在你的页面应该是进入授权页面的按钮:
点击授权,输入http://host.docker.internal:8081之后,点击保存即可,如果成功的话,会出现「已授权」的字样。
问题1:输入http://host.docker.internal:8081后,点击保存,页面没反应或者报错,报错如下:
{code: "invalid_param",…}
code: "invalid_param"
message: "HTTPConnectionPool(host='172.26.111.225', port=8081): Max retries exceeded with url: /?q=SearXNG&format=json&categories=general (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x7f6e4a939460>, 'Connection to 172.26.111.225 timed out. (connect timeout=None)'))"
status: 400
或者报错干脆就是无法建立连接类的报错。
我的解决方法是:
我排查了下,发现我的容器内无法解析host.docker.internal,可能是因为docker版本问题,一步一步排查,解决。
(1)处理无法解析host.docker.internal的问题
docker compose启动的容器直接在上文提到的docker-compose.yaml中改,每个image下都加入以下内容:
我这里图没有截全,要每个image下的都加。
然后上文提到的方式,重启这些容器。
其他的我不是用docker compose启动的就只有SearXNG,刚刚部署的时候我给了两个命令,我自己改后的命令如下:
docker run --rm -d --add-host=host.docker.internal:host-gateway --network host -v "/mnt/x/LLM/dify-main/api/core/tools/provider/builtin/searxng/docker:/etc/searxng" searxng_lyg:0.0.1
其中“--add-host=host.docker.internal:host-gateway”就是起到这个作用,如果你是用的官方给出的启动命令,可以加上,重新启动下。
四、DeepSeek R1模型部署
1、ollama安装
需要启动梯子,进入到ollama官网https://ollama.com/,选择对应的操作系统,下载ollama应用程序:
因为我前文提到了,我C盘容量不够了,所以这个我直接安装到其他盘了,我是见了一个新目录X:\Ollama,将上一步下载好的ollama安装包放到这个目录。
然后打开CMD,进入X:\Ollama目录下,使用命令安装:OllamaSetup.exe /DIR=X:\Ollama,在跳出来的安装页面上,正常用下一步就行了。
安装成功之后,在cmd输入ollama,如果出现下面的内容,则说明安装成功:
2、修改ollama模型部署的路径
Ollama模型下载部署也是默认到C盘,我这里也改到我制定好的目录,还是放到X:\Ollama目录下。
下面增加系统环境变量,即“我的电脑”-》属性-》“高级系统设置”-》“环境变量”
新建一个用户环境变量:
接下来将默认的Ollama的大模型目录挪到我指定的里面,即将
红框中的这个路径下的models目录,整个剪切到X:\Ollama下。
重新打开Ollama即可。
3、模型部署 DeepSeek R1
在ollama官网的顶部,点击「Models」,然后选择「DeepSeek R1」:
然后在模型界面根据自己电脑情况,选择对应版本,我选择了1.5B的来尝试。
然后将右边红框中的命令(ollama run deepseek-r1:1.5b)复制到CMD中执行即可。
有下载进度条,耐心等待即可。
下载完后会自动部署,就可以直接用来对话了。
五、Embedding模型部署
为了使用私有的向量数据库,并使用混合检索来提升检索精度,还需要通过ollama下载一个文本Embedding模型,上面那个没问题的话,这个也非常简单。
ollama pull shaw/dmeta-embedding-zh
六、在Dify中添加deepseek模型
登录到已经部署好的Dify中,点击右上角的头像,然后点击设置:
找到Ollama,添加我们刚刚那两步下载部署好的模型。
上面填写的,主要是“基础URL”的内容,11434是ollama默认的端口,在“基础URL”中,如果ollama和Dify是同机部署,并且Dify是通过Docker部署,那么填http://host.docker.internal:11434,其他情况填http://ollama的地址:11434,填完之后点击保存即可,如果你的保存成功,没啥问题正好,我的出现了写问题,我添加进去后,保存没有反应,下面问题我具体写下。
问题1:
我的ollama是在我本机,也就是我的windows上直接安装的,就不能使用,即无法解析host.docker.internal,这个时候,肯定用本机的WSL IP:172.26.96.1:11434,但是这个有点问题,我在本机ping我的虚拟机IP没问题,但是在虚拟机上ping我的本机IP不同,这个大概率是windows防火墙的问题,我是这样做的:
(1)配置windows防火墙
我的是Windows Defender 防火墙。
(1.1)按下 Win + R 组合键,输入 wf.msc 并回车,打开 “高级安全 Windows Defender 防火墙”。
(1.2)在左侧导航栏中选择 “入站规则”。
(1.3)点击右侧的 “新建规则”,在弹出的 “新建入站规则向导” 中:
(1.4)规则类型选择 “自定义”,然后点击 “下一步”。
(1.5)程序选择 “所有程序”,点击 “下一步”。
(1.6)协议和端口:协议类型选择 全部,点击 “下一步”。
(1.7)作用域:在 “远程 IP 地址” 中选择 “这些 IP 地址”,点击 “添加”,输入 172.26.96.0/20(这是 WSL 子网的 CIDR 表示法),然后点击 “下一步”。
(1.8)操作选择 “允许连接”,点击 “下一步”。
(1.9)配置文件根据你的实际情况选择,一般全选,然后点击 “下一步”。
(1.10)给规则命名(例如 “Allow WSL ICMP”),点击 “完成”。
(2)手动设置ollama的监听IP与端口
即cmd启动OLLAMA Server,在CMD下直接执行:
set OLLAMA_HOST=0.0.0.0
set OLLAMA_PORT=11434
ollama serve
七、在Dify中添加Embeding模型添加
基本与上面的一样。在添加模型那里,点击“Text Embedding”,模型名称填:shaw/dmeta-embedding-zh,在“基础URL中”,如果ollama和Dify是同机部署,并且Dify是通过Docker部署,那么填http://host.docker.internal:11434,其他情况填http://ollama的地址:11434,填完之后点击保存即可。
我的是:
八、上传私有知识库
在Dify的首页,点击“知识库“,进入到知识库界面,点击创建知识库:
上传已有文档,直接下一步,基本都是默认选项,然后在“索引方式“一栏中,选择”高质量“,Embedding模型选择刚才添加的ollama embedding模型。
在“检索设置“一栏,选择”混合检索“,即同时执行全文检索和向量检索,并应用重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,用户可以选择设置权重或配置重新排序模型。然后点击”保存并处理 “:
待处理完成即可,处理完成后,再看,会是“可用“状态。
可以点击进去,试一下“召回测试“:
九、智能体搭建
点击“工作室 “,选择“创建空白应用 “,选择”Agent“,然后填写”应用名称“,点击”创建“:
创建完成后,进去,按照你的需要填写一些信息,就可以探索了,具体使用就不细讲了,我这里还是遇到了一个问题。
问题1:在“工作室“建立好的应用,在点击进去时报错:
Application error: a client-side exception has occurred (see the browser console for more information).
Console中报错:
content.js:1 TypeError: Cannot read properties of undefined (reading 'tabId')
at 634.js:2
at Generator.next (<anonymous>)
at t (147.js:2)
at u (147.js:2)
我的解决就是,换个浏览器就好了,报错的浏览器时chrom,也就是谷歌浏览器,我换成Edge,没有问题。