本文收录于专栏 AI Agent系列 ------ 专栏系统覆盖 AI Agent 的框架选型、工具链搭建、本地部署与工程落地,点击订阅可跟踪后续更新。
你想在自己电脑上跑一套 Dify:提示词编排、知识库、Agent 流程都放本地,数据不出内网,也不用买云主机。真动手时会卡在四个地方:Windows 的 80 端口被系统占着、默认向量库镜像拉不动、容器起来又反复重启、重启电脑后打不开。
本文按动手顺序给一条跑通的路线:WSL2 装 Ubuntu(不需要管理员权限)、Docker 换能用的镜像源、.env 只改 4 项、15 个容器全绿、管理员建好,最后附 7 个实测报错和一套开机自启方案。装完你就有了一个能自己建应用、接国产模型、把网页发给同事用的本地平台,命令照抄即可复现。
关键字 :Dify、本地部署、WSL2、Docker Compose、镜像加速、qdrant、容器自启、大模型应用平台

#mermaid-svg-VIkNXcsoqBxaI3bk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VIkNXcsoqBxaI3bk .error-icon{fill:#552222;}#mermaid-svg-VIkNXcsoqBxaI3bk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VIkNXcsoqBxaI3bk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VIkNXcsoqBxaI3bk .marker.cross{stroke:#333333;}#mermaid-svg-VIkNXcsoqBxaI3bk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VIkNXcsoqBxaI3bk p{margin:0;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge{stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 text{fill:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth--1{stroke-width:17;}#mermaid-svg-VIkNXcsoqBxaI3bk .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-0{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-0{stroke-width:14;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-1{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-1{stroke-width:11;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 text{fill:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-2{stroke-width:8;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-3{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-3{stroke-width:5;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-4{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-4{stroke-width:2;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-5{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-5{stroke-width:-1;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-6{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-6{stroke-width:-4;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-7{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-7{stroke-width:-7;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-8{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-8{stroke-width:-10;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-9{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-9{stroke-width:-13;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 polygon,#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 text{fill:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .node-icon-10{font-size:40px;color:black;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .edge-depth-10{stroke-width:-16;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled circle,#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:lightgray;}#mermaid-svg-VIkNXcsoqBxaI3bk .disabled text{fill:#efefef;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-root rect,#mermaid-svg-VIkNXcsoqBxaI3bk .section-root path,#mermaid-svg-VIkNXcsoqBxaI3bk .section-root circle,#mermaid-svg-VIkNXcsoqBxaI3bk .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-VIkNXcsoqBxaI3bk .section-root text{fill:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-root span{color:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .section-2 span{color:#ffffff;}#mermaid-svg-VIkNXcsoqBxaI3bk .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-VIkNXcsoqBxaI3bk .edge{fill:none;}#mermaid-svg-VIkNXcsoqBxaI3bk .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-VIkNXcsoqBxaI3bk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Dify 本地部署
准备
WSL2 装 Ubuntu
Docker 换镜像源
起服务
改 .env 四项
15 个容器全绿
建管理员
七个坑
端口被占
向量库源断
大层拉挂
沙箱 token
WSL 回收
网络模式
自启失败
长期可用
开机自启
备份 volumes
目录
- [§0. 相关教程与核心文献](#§0. 相关教程与核心文献)
- [§1. 先弄清三件事:Dify 是什么、为什么装本地、几个词什么意思](#§1. 先弄清三件事:Dify 是什么、为什么装本地、几个词什么意思)
- [§2. 架构:16 个服务,你要操心的只有 4 类](#§2. 架构:16 个服务,你要操心的只有 4 类)
- [§3. 第一步:WSL2 + Ubuntu,不需要管理员权限](#§3. 第一步:WSL2 + Ubuntu,不需要管理员权限)
- [§4. 第二步:Docker 引擎与能用的镜像源](#§4. 第二步:Docker 引擎与能用的镜像源)
- [§5. 第三步:拉源码,改 .env 的 4 项](#§5. 第三步:拉源码,改 .env 的 4 项)
- [§6. 第四步:起服务、验证、建管理员](#§6. 第四步:起服务、验证、建管理员)
- [§7. 七个实测报错(含报错原文)](#§7. 七个实测报错(含报错原文))
- [§8. 开机自启:三种方案只活了一种](#§8. 开机自启:三种方案只活了一种)
- [§9. 日常运维与备份](#§9. 日常运维与备份)
- [§10. 边界与代价](#§10. 边界与代价)
- [§11. 参考来源](#§11. 参考来源)
§0. 相关教程与核心文献
| 资源 | 链接 | 与本文关系 |
|---|---|---|
| Dify 主仓库 langgenius/dify | --- | 源码、docker 目录与部署说明 |
| Dify v1.18.0 Release | --- | 本文部署的版本与变更记录 |
| docker/docker-compose.yaml(1.18.0) | --- | 服务清单、镜像 tag、profiles 来源 |
| docker/README.md(1.18.0) | --- | 官方三步部署流程 |
| WSL 官方安装文档 | --- | wsl --install 与发行版管理 |
| Dify Marketplace | --- | 模型供应商插件来源 |
§1. 先弄清三件事:Dify 是什么、为什么装本地、几个词什么意思
Dify 是什么。 它是一个把大模型应用"拼"出来的平台:提示词、知识库、工作流、Agent 都在网页上拖拽配置,不用写后端代码。
为什么装本地。 两条:内部文档不能出内网;想接局域网里的模型服务、或者直接看源码改代码。代价也很直白------Dify 不是"一个 pip 包",而是一套由 16 个服务搭起来的系统,真正要折腾的是你机器上的 Docker。
先认识四个词,后面全靠它们:
| 词 | 一句话解释 | 在本机对应什么 |
|---|---|---|
| WSL2 | Windows 里跑的轻量 Linux 子系统 | 我们装 Ubuntu 24.04,Dify 装在里面 |
| 镜像 / 容器 | 镜像=装好的软件包;容器=把它跑起来的实例 | Dify 一共 15 个容器 |
| 端口 | 一台机器上区分不同服务的"门牌号" | Dify 对外用 8080 |
卷(volumes/) |
容器删了数据还在的目录 | 备份抓这个目录就够了 |
本文实测的环境:
| 层 | 版本 |
|---|---|
| 宿主系统 | Windows 11 |
| WSL | 2.7.8.0(内核 6.18.33.1) |
| 发行版 | Ubuntu 24.04.5 LTS |
| 容器引擎 | Docker 29.1.3(Ubuntu 仓库 docker.io) |
| 编排 | Docker Compose 2.40.3 |
| Dify | 1.18.0(社区版 COMMUNITY) |
| 占用 | 虚拟磁盘 15 GB,/var/lib/docker 18 GB |
§2. 架构:16 个服务,你要操心的只有 4 类
docker-compose.yaml 里写了 47 个服务定义,实际启动哪些由 profiles 决定:默认 13 个,加上 PostgreSQL 与 qdrant,共 16 个服务、15 个常驻容器(init_permissions 是一次性任务,跑完就退出)。

按职责分四类,排错时按这四类去找:
| 类别 | 服务 | 干什么 |
|---|---|---|
| 入口 | nginx |
唯一对外端口,控制台和 API 都走它 |
| 应用 | api、worker、worker_beat、api_websocket、web |
网页前端 + 后端 API + 后台任务 |
| 执行 | sandbox、local_sandbox、plugin_daemon、agent_backend、两个 ssrf_proxy |
代码沙箱、插件、Agent 运行时、出站代理 |
| 数据 | db_postgres、redis、qdrant |
业务库、缓存队列、向量库 |
profiles 不是写死的,而是从 .env 里读出来的(.env.example 第 299 行):COMPOSE_PROFILES=${VECTOR_STORE:-weaviate},...。所以你把 VECTOR_STORE 改成 qdrant,docker compose up -d 会自动带上 qdrant,不需要 额外加 --profile。
拉镜像前先知道自己在等什么(实测体积,前五个是大头):
| 镜像 | 体积 |
|---|---|
dify-plugin-daemon:0.6.10-local |
2.28 GB |
dify-agent-backend:1.18.0 |
1.54 GB |
dify-web:1.18.0 |
911 MB |
dify-sandbox:0.2.15 |
848 MB |
dify-api:1.18.0 |
含一个 622 MB 单层(见坑 3) |
§3. 第一步:WSL2 + Ubuntu,不需要管理员权限
先用两条命令看本机状态(wsl -l -v 报"没有已安装的分发"=WSL 在、发行版没装;wsl --version 有版本号=组件就绪):
bash
wsl -l -v
wsl --version
装发行版一条命令,全程不需要管理员:
bash
wsl --install -d Ubuntu-24.04 --no-launch
--no-launch 的作用:装完不弹终端让你设用户名密码,方便后面写脚本。
装好后以 root 直接进去看:
bash
wsl -d Ubuntu-24.04 -u root -- bash -lc "cat /etc/os-release | head -3"
接着把发行版挪到空间大的盘(先导出再导入,同样不需要管理员):
bash
wsl --export Ubuntu-24.04 D:\wsl\base.tar
wsl --import dify D:\wsl\dify D:\wsl\base.tar --version 2
wsl -d dify -u root -- bash -lc "hostname; df -h / | tail -1"
到这里你就有了一个 systemd 已就绪的 Ubuntu(ps -p 1 -o comm= 输出 systemd 即正常),后面所有东西都装在它里面。
§4. 第二步:Docker 引擎与能用的镜像源
Ubuntu 仓库里的 docker.io + docker-compose-v2 够跑 Dify,不用加 Docker 官方 apt 源(少一个海外依赖):
bash
apt-get update
apt-get install -y docker.io docker-compose-v2 git curl ca-certificates jq openssl
systemctl enable --now docker
docker --version && docker compose version
国内必须配镜像加速,否则 docker pull 会一直卡在 Pulling fs layer。写 /etc/docker/daemon.json:
json
{
"registry-mirrors": [
"https://docker.1panel.top",
"https://docker.1panel.live",
"https://docker.xuanyuan.me",
"https://docker.1ms.run",
"https://docker.m.daocloud.io"
],
"log-driver": "json-file",
"log-opts": { "max-size": "50m", "max-file": "3" },
"max-concurrent-downloads": 8
}
改完重启,再拿一个 25 MB 的小镜像探路(十几秒拉完=加速器生效):
bash
systemctl restart docker
docker pull hello-world
五个加速器实测差异(这是坑 3 的依据):
| 加速器 | 实测 |
|---|---|
docker.1panel.top |
可用,约 1.4 MB/s,最终靠它拉全 |
docker.1panel.live |
多数可用,偶发 429 限流 |
docker.xuanyuan.me |
前 10 个正常,第 11 个 622 MB 层 403 |
docker.1ms.run |
报 magic number mismatch(返回的不是镜像) |
docker.m.daocloud.io |
卡在 Pulling fs layer 无进度 |
§5. 第三步:拉源码,改 .env 的 4 项
这台机器上 git clone 会被 TLS 掐断(GnuTLS recv error (-110)),但 tarball 通道是通的,直接下指定版本更省事:
bash
cd /opt
curl -L -o /tmp/dify.tgz https://codeload.github.com/langgenius/dify/tar.gz/refs/tags/1.18.0
tar -xzf /tmp/dify.tgz -C /opt && mv /opt/dify-1.18.0 /opt/dify
ls /opt/dify/docker | head
复制配置,然后改 4 项(每一项对应后面的一个坑):
| 改什么 | 改成 | 不改会怎样 |
|---|---|---|
EXPOSE_NGINX_PORT |
8080 |
Windows 的 80 被系统占着(坑 1) |
EXPOSE_NGINX_SSL_PORT |
8443 |
同上,顺带占位 |
VECTOR_STORE |
qdrant |
默认 weaviate 镜像国内拉不动(坑 2) |
DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN |
随机串 | 两个容器无限重启(坑 4) |
顺带把两个地址一起改成新端口,否则页面能开、对话不出字:
bash
cd /opt/dify/docker
cp .env.example .env
# 用 python 改比 sed 稳(值里可能有特殊字符)
python3 - <<'PY'
import re, pathlib, secrets
p = pathlib.Path("/opt/dify/docker/.env"); t = p.read_text()
upd = {
"EXPOSE_NGINX_PORT": "8080",
"EXPOSE_NGINX_SSL_PORT": "8443",
"VECTOR_STORE": "qdrant",
"NEXT_PUBLIC_SOCKET_URL": "ws://localhost:8080",
"ENDPOINT_URL_TEMPLATE": "http://localhost:8080/e/{hook_id}",
"DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN": secrets.token_hex(24),
}
for k, v in upd.items():
t = re.sub(rf"^{k}=.*$", f"{k}={v}", t, flags=re.M) if re.search(rf"^{k}=", t, re.M) else t + f"\n{k}={v}\n"
p.write_text(t)
PY
改完先校验,再做后面的事------这一步别跳,配置错一处,后面就是一堆容器反复重启:
bash
docker compose config --quiet && echo CONFIG_OK
docker compose config --services # 应该是 16 个服务名
§6. 第四步:起服务、验证、建管理员
bash
cd /opt/dify/docker
docker compose up -d # 命令 10 秒左右返回,容器随 db 健康检查陆续起
sleep 60
docker compose ps --format "table {{.Name}}\t{{.Status}}"
判断成功的标准:15 个容器都 Up,其中 db_postgres、redis、sandbox、local_sandbox、api 显示 (healthy)。
再从 Windows 侧验证入口(WSL 的端口会转发到本机 localhost):
bash
curl -s -o NUL -w "%{http_code}\n" http://localhost:8080/signin # 期望 200
curl -s http://localhost:8080/console/api/system-features | head -c 120 # 期望返回 JSON
JSON 里能看到 "deployment_edition":"COMMUNITY" 和 "enable_marketplace":true,说明 nginx 与 API 都活了。
首次打开 http://localhost:8080 会跳 /install 让你建管理员。想省掉手填,直接调接口:
bash
curl -s -X POST -H "Content-Type: application/json" \
-d '{"email":"admin@dify.local","name":"admin","password":"你的密码"}' \
http://localhost:8080/console/api/setup
# 返回 {"result":"success"}(HTTP 201)
curl -s http://localhost:8080/console/api/setup
# 返回 {"step":"finished", ...} 说明建好了
登录请用浏览器。
/console/api/login走前端加密,直接 curl 会报Invalid encrypted data,这是正常现象。
§7. 七个实测报错(含报错原文)

按遇到的顺序,每条给"现象 → 原因 → 怎么办"。
坑 1:80 端口起不来。 netstat -ano | findstr :80 看到 0.0.0.0:80 LISTENING 4------PID 4 是 Windows 的 System 进程(http.sys)占着端口。改 EXPOSE_NGINX_PORT=8080,并把 NEXT_PUBLIC_SOCKET_URL、ENDPOINT_URL_TEMPLATE 一起改成新端口,否则页面能打开、对话不出字(WebSocket 和回调还指着 80)。
坑 2:默认向量库拉不动。 weaviate 的镜像在 cr.weaviate.io,不走 Docker Hub,加速器帮不上忙。改 VECTOR_STORE=qdrant(在 Docker Hub 上),COMPOSE_PROFILES 会自动跟着换。首次部署时决定最省事------已有数据再换库要重新嵌入。
坑 3:622 MB 那一层永远拉不完。 现象是卡在某一层不动,换加速器后变成 invalid input: magic number mismatch 或 429。最坑的是:强杀过一次 pull 之后,再拉会一直停在 Pulling fs layer 一个字节不动------Docker 29 的下载缓存被强杀后会留下锁文件,后续拉取一直等这把锁。分两步修:
bash
# 1) 清掉被杀断的 pull 留下的锁
systemctl stop docker docker.socket
rm -rf /var/lib/containerd/io.containerd.content.v1.content/ingest/*
systemctl start docker
# 2) 换一个真能出数据的加速器,单独拉这个镜像再打回标准 tag
docker pull docker.1panel.top/langgenius/dify-api:1.18.0
docker tag docker.1panel.top/langgenius/dify-api:1.18.0 langgenius/dify-api:1.18.0
判断加速器到底有没有在传数据,别看进度条,看磁盘增速:df --output=used -B1 / 前后取差,一分钟涨几十 MB 才算真在下载。
坑 4:local_sandbox 与 agent_backend 无限重启。 docker compose ps 里显示 Restarting (1),日志反复打:
shellctl: auth token is required: set SHELLCTL_AUTH_TOKEN or --token
Value error, local_sandbox_auth_token is required for the local runtime backend
1.18 把 Agent 执行层拆成这两个服务,本地运行时模式强制要一个共享 token,而 .env.example 里默认为空。填一个随机值并重建这两个服务:
bash
sed -i "s|^DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN=.*|DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN=$(openssl rand -hex 24)|" .env
docker compose up -d --force-recreate local_sandbox agent_backend
坑 5:容器每几分钟集体重启一次。 迷惑点在于 docker compose ps 老显示 Up 6 秒、Up 13 秒,但 RestartCount 不涨。查 journalctl --list-boots 才发现不是 Docker 的问题------WSL 实例被回收了:
WSL (2 - init-systemd(dify)) ERROR: InitTerminateInstanceInternal:2763:
systemctl poweroff did not terminate the instance in 10000 ms, calling reboot(RB_POWER_OFF)
最后一个 wsl.exe 会话结束后,WSL 会把整个发行版关掉,容器随之停止;下次任何 wsl 命令又把它拉起来,restart: always 的容器再起一遍。修复见 §8:必须挂一个常驻会话。
坑 6:networkingMode=mirrored + autoProxy=true 把网络搞崩。 打开镜像网络和自动代理后,WSL 里除国内站点外全部超时:baidu 200,api.github.com 和 marketplace.dify.ai 都是 000。原因是 autoProxy 会把 Windows 的系统代理写进 WSL 的 https_proxy,而那个代理当时失效了。改回默认 NAT、关掉 autoProxy:
ini
# %USERPROFILE%\.wslconfig
[wsl2]
memory=12GB
processors=8
swap=4GB
dnsTunneling=true
autoProxy=false
wsl --shutdown 让配置生效后,marketplace.dify.ai 从 WSL 内返回 200------这点很关键,否则后面装模型插件会全失败。
坑 7:开机自启三连失败。 见下一节,单独展开。
§8. 开机自启:三种方案只活了一种
Dify 装在 WSL 里,自启多一层:不光要把容器拉起来,还得保证 WSL 发行版不被回收(坑 5)。
| 方案 | 结果 | 为什么 |
|---|---|---|
计划任务 schtasks /SC ONLOGON |
拒绝访问 | 本机策略不允许非管理员注册登录任务 |
启动文件夹放 .vbs → .cmd → Start-Process wsl.exe |
脚本跑了,wsl 立刻退出 | wsl.exe 没有有效的输出目标就会直接退出,"常驻"没挂住 |
注册表 HKCU\...\Run + PowerShell |
可用 | 带输出重定向的 Start-Process 会一直阻塞等子进程,进程因此常驻 |
脚本干三件事:挂常驻会话、等 docker 就绪、拉起容器。
powershell
$log = 'D:\wsl\keepalive.log'
$wsl = 'C:\Windows\System32\wsl.exe'
# 1) 常驻会话:带重定向的 Start-Process 会一直阻塞,wsl.exe 因此不会退出
$ka = Start-Process -FilePath $wsl `
-ArgumentList '-d','dify','-u','root','--','sleep','infinity' `
-RedirectStandardOutput $log -RedirectStandardError 'D:\wsl\keepalive.err' `
-WindowStyle Hidden -PassThru
# 2) 等 docker 就绪(最多 120 秒)
for ($i = 0; $i -lt 60; $i++) {
& $wsl -d dify -u root -- bash -lc "systemctl is-active --quiet docker" 2>$null | Out-Null
if ($LASTEXITCODE -eq 0) { break }
Start-Sleep -Seconds 2
}
# 3) 拉起容器,然后挂住不退($ka 一退,WSL 会话就没了)
& $wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose up -d" *>> 'D:\wsl\dify-autostart.log'
$ka.WaitForExit()
注册到当前用户的 Run 键(不需要管理员):
powershell
New-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' `
-Name 'DifyLocalAutostart' -PropertyType String -Force `
-Value 'powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File D:\wsl\dify-autostart.ps1'
验证方式就是模拟一次关机再开机:wsl --shutdown → 手动执行同一条命令 → 等 90 秒后检查三件事。实测结果:日志末尾 compose done rc=0、发行版内 sleep infinity 常驻、15 个容器全 Up、/signin 返回 200,4 分钟后 boot id 未变、容器无重启。
§9. 日常运维与备份
bash
# 状态
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose ps"
# 停 / 起(保留数据)
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose stop"
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose up -d"
# 看日志
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose logs -f api"
# 改完 .env 后重建受影响的服务
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && docker compose up -d --force-recreate api worker"
备份只抓 volumes/------Dify 1.18 把持久化数据放在 compose 目录下(直接挂在宿主机目录上,不是 docker volume):
bash
wsl -d dify -u root -- bash -lc "cd /opt/dify/docker && tar czf /mnt/d/dify-backup-$(date +%F).tar.gz volumes/"
数据库目录实测 79 MB(空库 + 初始化数据),知识库用起来后会明显变大。整个发行版要搬家,用 wsl --export dify 打快照。
§10. 边界与代价
只能本机访问。 WSL 默认 NAT 模式只把端口转发到 Windows 的 127.0.0.1,局域网其他机器打不开。要从别的设备用,需要管理员权限做端口转发(重启后失效,得做成开机脚本):
cmd
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8080 connectaddress=127.0.0.1 connectport=8080
netsh advfirewall firewall add rule name="Dify 8080" dir=in action=allow protocol=TCP localport=8080
模型要装插件才能用。 Dify 1.x 把模型供应商做成了插件,第一次用要去"设置 → 模型供应商"装一个(如 OpenAI-API-compatible)。marketplace.dify.ai 本机能直连,但 OpenAI / Anthropic 这类境外端点要自备代理;代理失效时插件装得上、调用会超时。
资源占用不高,但要注意内存上限。 15 个容器稳定运行约 2.3 GB 内存,给 WSL 配 12 GB 很宽裕;磁盘增长主要在镜像层。
升级要重新拉镜像。 路径是拿新版本 tarball、沿用旧 .env、docker compose pull && up -d,最后跑一次数据库迁移 flask db upgrade。跨大版本升级前先备份 volumes/。
§11. 参考来源
- Dify 主仓库与版本:langgenius/dify、v1.18.0
- 部署配置基线:docker-compose.yaml、docker/README.md
- WSL 安装与管理:learn.microsoft.com/windows/wsl/install
- 插件来源:Dify Marketplace
说明:
docs.dify.ai与docs.docker.com在本文实测网络下不可直连,因此正文只引用 GitHub 上的源码与 README;你的网络能访问官方文档的话,那里有更完整的 Compose 参数说明。
系列导航 :专栏全集 AI Agent系列
更多专栏:
| 蛋白 / 抗体 / 多肽 / 核酸 | 分子模拟 / 动力学 / 对接 | 药物 / 设计 / 案例 | AI / Agent / 大模型 |
|---|---|---|---|
| 开源蛋白结构预测 | 分子模拟基础 | 小分子药物设计案例 | AI Agent系列 |
| 开源蛋白生成方法实践 | 分子动力学模拟-Amber | 蛋白药物设计案例 | 化学大模型 |
| 开源多肽设计模型 | 分子动力学模拟-Gromacs | 多肽药物设计案例 | 《AI Agent原理与实战》 |
| 开源多肽性质预测 | 分子动力学模拟-OpenMM | 开源小分子生成设计 | CADD中的机器学习模型 |
| DNA/RNA药物设计 | 結合自由能 | 高效计算配置 | 《MCP 入门实战》 |
| siRNA药物设计模型 | UCSF DOCK系列 | 我胡师兄说药 | 《AI入门实战2026》 |
| ASO药物设计模型 | rDock系列 LeDock系列 gnina系列 | 《经典机器学习实战》 |