Dify 1.18 本地部署实战:Windows + WSL2 + Docker,从零跑到本地可用

本文收录于专栏 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. 参考来源

说明: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系列 《经典机器学习实战》
相关推荐
shangjian0072 小时前
K8S学习-基础组件
学习·容器·kubernetes
徐小黑ACG3 小时前
docker 基础教程
运维·docker·容器
cc_yy_zh3 小时前
笔记本关机自动重启解决办法
windows
wzg20164 小时前
ubuntu 离线安装 docker-compose
linux·ubuntu·docker
时间售卖铺4 小时前
Docker镜像构建全解析:从原理到实战优化
运维·docker·云原生·容器
wzq11_6665 小时前
Kubernetes集群——工作负载
云原生·容器·kubernetes
AlanAshley6 小时前
Windows 错误代码 0x80284018:可能原因与解决办法
windows
2501_915909067 小时前
Windows 打开 Xcode 工程,编译调试 Xcode 项目并和 Mac 同事协作
ide·windows·vscode·macos·ios·个人开发·xcode
jianjinwssy7 小时前
从零设计一个 Agent 安全沙箱:Docker 隔离、三级风控与 Kafka 审计
人工智能·docker·kafka