WSL2+Docker+Dify+QQBot(更新中)
安装WSL2
- Windows搜索
程序与功能,打开启用或关闭 Windows 功能,勾选虚拟机平台和适用于 Linux 的 Windows子系统 - 安装Linux内核更新包。如果是Win10/11 2022.3 之后,直接跳过这一步,这一步是将wsl1 更新到 wsl2。下载适用于 x64 计算机的 WSL2 Linux 内核更新包,然后双击运行。
- 将WSL默认版本设置为 WSL2:
wsl --set-default-version 2 - 重启电脑
- 手动下载Ubuntu镜像文件(以wsl.rootfs.tar.gz结尾,注意区分amd64和arm64)到自己指定的路径中。镜像文件仓库地址打不开的话可以去清华的镜像站
- 将镜像文件导入WSL中:
wsl --import <DistributionName> <InstallLocation> <FileName>- DistributionName:分发(实例)名称,按自己需要命名
- InstallLocation:安装位置,按自己需要选择
- FileName:刚刚下载的rootfs系统包路径,
- 设置默认子系统:
wsl --set-default <DistributionName> - 查看WSL版本和分发版本:
wsl -l -v - 进入WSL设置root的密码:
wsl -d <DistributionName>:进入指定的实例(分发版本),也可以使用wsl直接进入默认的实例passwd root:重置密码,第一次进去时是root且没有密码,可以直接设置,以后要设置时需要sudo同时先输入当前密码
- 添加用户:
adduser <UserName>:新建指定名字的用户,新建后系统要求输入密码,输入即可,后面还会有个人信息,可以全部回车不填,最后直接Y确定。usermod -aG sudo <UserName>:赋予指定用户sudo权限groups <UserName>:查看指定用户是否有sudo权限(如果输出中包含sudo,则该用户有 sudo 权限)
- 设置默认用户(可选):用wsl指令启动时默认使用该用户
nano /etc/wsl.conf:编辑wsl.conf文件(注意改你需要的用户名)Ctrl+X、Y、回车Enter:保存配置- 关闭WSL,重新启动以生效
编辑wsl.conf文件添加以下内容:
[user]
default=<UserName>
- 换源:修改Ubuntu系统内的源地址配置文件,这里以Ubuntu24.04为例参考博文。
- 编辑源地址配置文件:
sudo vim /etc/apt/sources.list.d/ubuntu.sources - 注释掉原有的源地址配置(就
archive.ubuntu.com和security.ubuntu.com这两段) - 添加以下清华园配置:
Types: deb
URIs: http://mirrors.tuna.tsinghua.edu.cn/ubuntu/
Suites: noble noble-updates noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
其他常用指令:
wsl --shutdown:关闭所有实例wsl --terminate <DistributionName>:关闭指定实例wsl -l -v: 查看已安装的实例wsl -d <DistributionName>:进入指定的实例wsl --unregister <DistributionName>:卸载/注销指定的实例Ctrl+d:退出当前用户/退出实例su:切换到rootsu - <UserName>:切换到指定用户wsl -u <UserName>:启动wsl并切换到指定用户passwd <UserName>:为指定用户设置/重置密码cat /etc/passwd:查看系统中的所有用户
在WSL2中安装Docker
- 更新Openssl:
sudo apt-get install --only-upgrade openssl - 更新 CA 证书,按顺序执行以下指令:
sudo apt-get updatesudo apt-get install --reinstall ca-certificatessudo update-ca-certificates
- 使用阿里云镜像安装Docker(这里如果遇到curl报错,可以多试几次):
sudo curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun - 为docker配置镜像源,复制以下指令:
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.imgdb.de",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com",
"https://docker.1ms.run",
"https://func.ink",
"https://lispy.org",
"https://docker.xiaogenban1993.com"
]
}
EOF
- 验证docker成功安装:
sudo docker run hello-world或sudo docker pull hello-world,查看是否成功执行。
如果不能成功运行,显示类似于守护进程未运行,并且尝试重启docker服务后查看docker运行状态发现根本没在运行,可以尝试以下方案(参考博文)的处理方式:
- 执行
sudo update-alternatives --config iptables - 选择
iptables-legacy - 重启docker服务,查看运行状态,应该能发现docker成功运行
Docker相关使用
注意:WSL2 默认并不使用 systemd 作为初始化系统(init system)。WSL2 使用自己的轻量级初始化进程,因此不支持原生的 systemctl 命令。
docker version:查看docker版本sudo service docker start:启动docker服务sudo service docker stop:关闭docker服务sudo service docker restart:重启docker服务sudo service docker status:查看docker服务的运行状态
使用Docker安装Dify
前排提示:也可以根据官方文档进行安装
- 选一个路径放置项目(我在
/home/<UserName>/projects作为存放项目的路径) - 克隆dify项目:
git clone https://github.com/langgenius/dify.git - 进入dify项目的docker配置:
cd dify/docker - 配置docker的环境:
cp .env.example .env - 启动项目:
sudo docker compose up -d - 验证部署状态:
sudo docker compose ps
预计输出(在这之前改过端口,EXPOSE_NGINX_PORT从80改为5080):
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-api-1 langgenius/dify-api:1.5.1 "/bin/bash /entrypoi…" api 58 seconds ago Up 40 seconds 5001/tcp
docker-db-1 postgres:15-alpine "docker-entrypoint.s…" db About a minute ago Up 53 seconds (healthy) 5432/tcp
docker-nginx-1 nginx:latest "sh -c 'cp /docker-e…" nginx 56 seconds ago Up 37 seconds 0.0.0.0:443->443/tcp, [::]:443->443/tcp, 0.0.0.0:5080->80/tcp, [::]:5080->80/tcp
docker-plugin_daemon-1 langgenius/dify-plugin-daemon:0.1.3-local "/bin/bash -c /app/e…" plugin_daemon 58 seconds ago Up 40 seconds 0.0.0.0:5003->5003/tcp, [::]:5003->5003/tcp
docker-redis-1 redis:6-alpine "docker-entrypoint.s…" redis About a minute ago Up 54 seconds (healthy) 6379/tcp
docker-sandbox-1 langgenius/dify-sandbox:0.2.12 "/main" sandbox About a minute ago Up 53 seconds (healthy)
docker-ssrf_proxy-1 ubuntu/squid:latest "sh -c 'cp /docker-e…" ssrf_proxy About a minute ago Up 53 seconds 3128/tcp
docker-weaviate-1 semitechnologies/weaviate:1.19.0 "/bin/weaviate --hos…" weaviate About a minute ago Up 53 seconds
docker-web-1 langgenius/dify-web:1.5.1 "/bin/sh ./entrypoin…" web About a minute ago Up 54 seconds 3000/tcp
docker-worker-1 langgenius/dify-api:1.5.1 "/bin/bash /entrypoi…" worker 58 seconds ago Up 40 seconds 5001/tcp
...
- 本机访问:浏览器输入http://localhost
如果改过端口,则登入链接为http://localhost:<EXPOSE_NGINX_PORT> - 关闭项目:
sudo docker compose stop:仅停止容器,但不删除容器、网络、卷或镜像。
sudo docker compose down:停止正在运行的容器,并删除容器、默认网络和为服务创建的镜像(如果有)。默认不会删除数据卷,因此卷中保存的数据不会丢失。
对于端口修改,可以参考官方文档的做法
改完端口后就可以用localhost:<EXPOSE_NGINX_PORT>访问Dify
备份与更新可以参考该博文Dify 升级保姆级教程:手把手教你更新不丢数据,小白也能轻松搞定!
挂载本地卷可以参考该博文docker run使用卷(volume)挂载的两种方式
打包命令:tar -czf /目标路径/压缩文件名.tgz /源文件夹路径
复制命令:cp 源路径 目标路径
个人用更新流程:
cd dify/docker,sudo docker compose down,cd ../..:关闭difysudo cp dify/docker/.env baks/dify/docker/:备份.env文件(改了端口)。sudo cp dify/docker/docker-compose.yaml baks/dify/docker/:备份docker-compose.yaml文件sudo tar -czf baks/dify/docker/volumes-<备份版本号>.tgz dify/docker/volumes:备份数据卷cd dify,sudo git checkout main:确保main分支sudo git pull origin main,cd ..:拉取最新代码(多试几次,实在不行手动下载到路径解压)sudo cp baks/dify/docker/.env dify/docker/:还原.env文件sudo tar -xzf baks/dify/docker/volumes-<备份版本号>.tgz -C .:还原数据卷cd dify/docker,sudo docker compose up -d:启动difysudo docker compose ps:检查容器状态
使用VSCode连接WSL2中的项目进行开发
其实也可以用Remote - SSH插件完成,但方便起见这里仍以使用WSL插件为例
- 搜索
WSL插件并安装 - 按
Ctrl+Shift+p,输入WSL,点击Connet to WSL选项 - 等待连接然后再选择项目路径,完成与项目的连接
QQBot
这里使用官方的机器人平台开发,不然容易被风控
流式输出:只有私聊方式支持
async def on_c2c_message_create(self, message: C2CMessage):
stream = {
"state": 1,
"id": None,
"index": 0,
"reset": False
}
_log.info(f"收到用户{message.author.user_openid}的私信")
print(message.author)
conversation_id = None
async for status, chunk, conv_id in dify.chatflow(message.content, conversation_id):
if status < 1:
break
# 在这里处理每个数据块
_log.info(chunk)
conversation_id = conv_id
response = await self.api._http.request(
Route("POST", "/v2/users/{openid}/messages", openid=message.author.user_openid),
json={
"openid": message.author.user_openid,
"msg_type": 0,
"msg_id": message.id,
"content": chunk,
"stream": stream,
}
)
stream["index"] += 1
stream["id"] = response["id"]
参考资料
https://developer.aliyun.com/article/1582169
https://blog.jojo.host/posts/dxdhlMjMt/#1-环境检测
https://zhuanlan.zhihu.com/p/32004414428
https://www.runoob.com/docker/ubuntu-docker-install.html
https://blog.csdn.net/qq_40603125/article/details/148678056
https://blog.csdn.net/yanbober/article/details/138245581

浙公网安备 33010602011771号