Dify RAG知识库-自部署完整指南

Dify 1.1.3 自部署完整指南 --- 从空白 Linux 到上线

✅ 本帖是基于实际部署经验整理的一站式教程,全部踩坑记录都在,照着走一定能跑起来。

环境:Linux + Docker Compose,单机部署,nginx 统一入口 + 可选 NPS 内网穿透。


目录

  1. 前置要求
  2. [安装 Docker 环境](#安装 Docker 环境 "#2-%E5%AE%89%E8%A3%85-docker-%E7%8E%AF%E5%A2%83")
  3. 目录规划
  4. [编写 docker-compose.yaml](#编写 docker-compose.yaml "#4-%E7%BC%96%E5%86%99-docker-composeyaml")
  5. [编写 nginx 配置](#编写 nginx 配置 "#5-%E7%BC%96%E5%86%99-nginx-%E9%85%8D%E7%BD%AE")
  6. 启动全部容器
  7. 数据库迁移
  8. 首次访问与初始化
  9. [外网访问(NPS 内网穿透)](#外网访问(NPS 内网穿透) "#9-%E5%A4%96%E7%BD%91%E8%AE%BF%E9%97%AEnps-%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F")
  10. 常见问题与踩坑记录
  11. 日常运维命令

1. 前置要求

项目 最低配置 推荐配置
CPU 2 核 4 核
内存 4 GB 8 GB
磁盘 20 GB 50 GB+(向量数据和文件存储比较吃空间)
系统 Ubuntu 20.04+ / Debian 11+ / CentOS 7+ 同左
Docker 24+ 最新版

需要开放的端口(按需):

端口 用途
3199 Dify 主入口(nginx 统一代理)
33099 仅 NPS 隧道使用时映射到外网
80 / 443 如果有独立公网 IP 直接反代

2. 安装 Docker 环境

bash 复制代码
# ----- Docker -----
curl -fsSL https://get.docker.com | bash
sudo systemctl enable --now docker

# ----- Docker Compose 插件 -----
# Docker 24+ 自带 compose 插件,验证:
docker compose version

# 如果是旧版 Docker,单独安装:
# sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# sudo chmod +x /usr/local/bin/docker-compose

3. 目录规划

bash 复制代码
# 创建部署目录
sudo mkdir -p /data/dify
cd /data/dify

数据存储目录(建议放到大分区):

bash 复制代码
# 假设 /data 是大数据盘
sudo mkdir -p /data/dify/storage
sudo mkdir -p /data/dify/db/data
sudo mkdir -p /data/dify/redis/data
sudo mkdir -p /data/dify/weaviate/data
sudo mkdir -p /data/dify/plugin_daemon

# 或者直接用 docker-compose 同级目录:
# sudo mkdir -p ./storage ./db/data ./redis/data ./weaviate/data ./plugin_daemon

最终目录结构:

bash 复制代码
/data/dify/
├── docker-compose.yaml    # 主配置
├── nginx.conf              # nginx 反向代理配置
├── storage/               # 上传文件
├── db/data/               # PostgreSQL 数据
├── redis/data/            # Redis 数据
├── weaviate/data/         # Weaviate 向量数据
└── plugin_daemon/         # 插件存储

4. 编写 docker-compose.yaml

⚠️ 这是全教程最关键的部分。 Dify 官方文档给的 docker-compose 用了大量 .env 文件拆分,新手容易漏配。下面这份是整合好的单文件版本,包含所有 8 个容器,直接复制就能用。

文件:/data/dify/docker-compose.yaml

yaml 复制代码
name: dify

x-shared-env: &shared-api-worker-env
  LOG_LEVEL: INFO
  DEBUG: "false"
  EDITION: SELF_HOSTED
  DEPLOY_ENV: PRODUCTION
  SECRET_KEY: your-secret-key-change-in-prod      # ← 改掉!
  INIT_PASSWORD: your-admin-password               # ← 改掉!初始化管理员用
  DB_USERNAME: postgres
  DB_PASSWORD: dify123456                          # ← 建议改掉
  DB_HOST: db
  DB_PORT: 5432
  DB_DATABASE: dify
  REDIS_HOST: redis
  REDIS_PORT: 6379
  REDIS_PASSWORD: dify123456                       # ← 建议改掉
  CELERY_BROKER_URL: redis://:dify123456@redis:6379/1
  STORAGE_TYPE: local
  STORAGE_LOCAL_PATH: storage
  VECTOR_STORE: weaviate
  WEAVIATE_HOST: weaviate
  WEAVIATE_PORT: 8080
  WEAVIATE_SCHEME: http
  WEAVIATE_BATCH_SIZE: 100
  WEAVIATE_TEXT_KEY: text
  PLUGIN_DAEMON_URL: http://plugin_daemon:5002
  PLUGIN_DAEMON_KEY: your-plugin-daemon-key        # ← 改掉!插件 daemon 密钥
  DIFY_INNER_API_KEY: your-inner-api-key           # ← 改掉!内部通信密钥

services:
  api:
    image: langgenius/dify-api:1.1.3
    restart: always
    environment:
      <<: *shared-api-worker-env
      MODE: normal
    volumes:
      - /data/dify/storage:/app/api/storage
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - dify-network

  worker:
    image: langgenius/dify-api:1.1.3
    restart: always
    environment:
      <<: *shared-api-worker-env
      MODE: worker
    command: celery -A app.celery worker --pool=gevent --concurrency=10 -n worker@%h
    volumes:
      - /data/dify/storage:/app/api/storage
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - dify-network

  web:
    image: langgenius/dify-web:1.1.3
    restart: always
    environment:
      NEXT_TELEMETRY_DISABLED: "1"
      # 这俩设空,让前端走同源相对路径,靠 nginx 代理
      CONSOLE_API_URL: ""
      APP_API_URL: ""
    depends_on:
      - api
    networks:
      - dify-network

  db:
    image: postgres:15-alpine
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: dify123456
      POSTGRES_DB: dify
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - /data/dify/db/data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - dify-network

  redis:
    image: redis:7-alpine
    restart: always
    command: redis-server --requirepass dify123456 --appendonly yes
    volumes:
      - /data/dify/redis/data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "dify123456", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - dify-network

  weaviate:
    image: semitechnologies/weaviate:1.19.0
    restart: always
    volumes:
      - /data/dify/weaviate/data:/var/lib/weaviate
    environment:
      AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true"
      PERSISTENCE_DATA_PATH: /var/lib/weaviate
      DEFAULT_VECTORIZER_MODULE: "none"
      CLUSTER_HOSTNAME: node1
    networks:
      - dify-network

  nginx:
    image: nginx:alpine
    restart: always
    ports:
      - "3199:80"
    volumes:
      - /data/dify/storage:/app/api/storage
      - /data/dify/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api
      - web
    networks:
      - dify-network

  plugin_daemon:
    image: langgenius/dify-plugin-daemon:0.0.6-local
    restart: always
    environment:
      <<: *shared-api-worker-env
      SERVER_PORT: 5002
      SERVER_KEY: your-plugin-daemon-key           # ← 和上面 PLUGIN_DAEMON_KEY 保持一致
      DIFY_INNER_API_URL: http://api:5001
      DIFY_INNER_API_KEY: your-inner-api-key       # ← 和上面保持一致
      MAX_PLUGIN_PACKAGE_SIZE: 52428800
      PLUGIN_REMOTE_INSTALLING_HOST: your-domain-or-ip   # ← 外网域名或 IP
      PLUGIN_REMOTE_INSTALLING_PORT: 3199                 # ← 外网端口
      PLUGIN_WORKING_PATH: /app/storage/cwd
      DB_DATABASE: dify
      DB_SSL_MODE: disable
      FORCE_VERIFYING_SIGNATURE: "true"
    volumes:
      - /data/dify/plugin_daemon:/app/storage
    depends_on:
      - db
    networks:
      - dify-network

networks:
  dify-network:
    driver: bridge

需要改的配置项

配置项 说明
SECRET_KEY 应用加密密钥,生成随机字符串
INIT_PASSWORD 首次初始化管理员密码
DB_PASSWORD PostgreSQL 密码
REDIS_PASSWORD Redis 密码
PLUGIN_DAEMON_KEY / SERVER_KEY 插件 daemon 密钥,两处保持一致
DIFY_INNER_API_KEY API 与插件 daemon 内部通信密钥,两处保持一致
PLUGIN_REMOTE_INSTALLING_HOST 外网可访问的域名或 IP
PLUGIN_REMOTE_INSTALLING_PORT 外网端口

生成随机密钥的快捷命令:

bash 复制代码
# Linux
openssl rand -base64 32

# 或者直接用
date +%s | md5sum | head -c 32

5. 编写 nginx 配置

为什么要用 nginx?因为 Dify 的 API 和 Web 前端是分开的容器(api:5001 和 web:3000),直接暴露哪个都不对。nginx 做统一入口,按路径分流。

文件:/data/dify/nginx.conf

nginx 复制代码
user  nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;

    # API upstream
    upstream api {
        server api:5001;
    }

    # Web upstream
    upstream web {
        server web:3000;
    }

    server {
        listen 80 default_server;
        server_name _;

        # API 路由(后台管理 API)
        location /console/api/ {
            proxy_pass http://api/console/api/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 600s;
        }

        # API 路由(应用 API)
        location /api/ {
            proxy_pass http://api/api/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 600s;
        }

        # 文件服务
        location /files/ {
            proxy_pass http://api/files/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 600s;
        }

        # Web 前端(兜底路由,所有其他请求走前端)
        location / {
            proxy_pass http://web/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

6. 启动全部容器

bash 复制代码
cd /data/dify

# 启动
docker compose up -d

# 查看状态(所有 8 个容器都应该是 Up)
docker compose ps

# 看看日志有没有报错
docker compose logs --tail=30

正常输出应该长这样:

scss 复制代码
NAME                   STATUS                   PORTS
dify-api-1             Up                       ~
dify-worker-1          Up                       ~
dify-web-1             Up                       ~
dify-db-1              Up (healthy)             ~
dify-redis-1           Up (healthy)             ~
dify-weaviate-1        Up                       ~
dify-nginx-1           Up                       0.0.0.0:3199->80/tcp
dify-plugin_daemon-1   Up                       ~

⚠️ 如果某个容器状态是 Restarting,用 docker logs <容器名> 查看具体报错。常见问题见第 10 节。


7. 数据库迁移

API 容器启动后,需要执行数据库迁移来创建表结构:

bash 复制代码
# 执行数据库迁移
docker compose exec api flask db upgrade

# 成功输出示例:
# INFO  [alembic.runtime.migration] Running migrate...
# INFO  [alembic.runtime.migration] Running upgrade -> xxxx, init

如果没有报错就说明迁移完成。可以进数据库验证:

bash 复制代码
docker compose exec db psql -U postgres -d dify -c "\dt"

8. 首次访问与初始化

本地访问:

arduino 复制代码
http://你的服务器IP:3199

初始化步骤:

  1. 打开页面 → 看到 Dify 初始化设置页
  2. 输入管理员邮箱和密码(对应 INIT_PASSWORD 环境变量里设置的值)
  3. 点击确认 → 设置完成
  4. 用刚刚设置的邮箱+密码登录

登录成功后,可以看到 Dify 的工作台首页,就可以开始创建应用了 🎉


9. 外网访问(NPS 内网穿透)

如果你没有公网 IP,需要用 frp / NPS / ngrok 这类工具做内网穿透。

NPS 隧道配置示例

以 NPS 为例,隧道映射关系:

NPS 端口 目标
33099 127.0.0.1:3199(nginx 统一入口)

⚠️ 不要映射到 web:3000 或 api:5001 的独立端口,一定要走 nginx 的入口。

在 Dify 后台的「设置 → 模型供应商」中配置 LLM 时,注意回调地址也要用外网域名:

arduino 复制代码
http://你的域名:33099/v1

10. 常见问题与踩坑记录

10.1 前端白屏 / API 404

症状: 页面打开了但全是白色,控制台 JS 报 404。

原因: CONSOLE_API_URLAPP_API_URL 没设空,前端 JS 尝试请求 http://127.0.0.1:5001

解决: web 容器 environment 中加:

yaml 复制代码
CONSOLE_API_URL: ""
APP_API_URL: ""

这样前端走同源相对路径,由 nginx 代理到正确后端。

10.2 插件报 500 / PluginDaemonInnerError

症状: 打开模型设置或插件页面时 API 返回 500,日志报:

vbnet 复制代码
Failed to resolve 'plugin_daemon' - Name or service not known

原因: plugin_daemon 容器启动失败或未启动。

排查:

bash 复制代码
docker compose ps plugin_daemon
# 如果是 Restarting,看日志
docker logs dify-plugin_daemon-1

10.3 plugin_daemon 启动崩溃

症状: plugin_daemon 不断重启,日志依次报:

csharp 复制代码
[PANIC] DifyInnerApiKey... required tag
[PANIC] plugin remote installing host is empty
[PANIC] plugin remote installing port is empty
[PANIC] plugin working path is empty

原因: 0.0.6-local 版本的 plugin_daemon 对配置检查非常严格,按顺序检查,缺一个就 panic 一次。必须补全以下环境变量:

yaml 复制代码
DIFY_INNER_API_KEY: xxx                      # api 和 plugin_daemon 都要有
DIFY_INNER_API_URL: http://api:5001
PLUGIN_REMOTE_INSTALLING_HOST: your-domain
PLUGIN_REMOTE_INSTALLING_PORT: 3199
PLUGIN_WORKING_PATH: /app/storage/cwd
DB_DATABASE: dify
DB_SSL_MODE: disable

10.4 存储空间不足

症状: 用了一段时间后磁盘满了,容器写不进数据。

原因: 默认配置下数据都写在 docker-compose 同级目录,如果系统盘小(比如 32GB),很容易撑爆。

解决: 所有 volumes 映射到大分区,上面的配置已经做了这件事。

检查磁盘空间:

bash 复制代码
df -h
du -sh /data/dify/*

10.5 跨域问题

症状: 浏览器控制台报 CORS 错误。

原因: 前端域名和后端 API 域名不一致,或者 nginx 没配好。

解决: 确保 nginx 配置了正确的 proxy_set_header,并且前端 CONSOLE_API_URL / APP_API_URL 设为空字符串走同源。

10.6 API 返回 502 Bad Gateway

原因: api 容器还没启动好,nginx 代理不到。

解决: 等几秒重试,或者检查 api 容器日志:

bash 复制代码
docker compose logs api --tail=20

11. 日常运维命令

bash 复制代码
# 进入部署目录
cd /data/dify

# 启动/停止全部
docker compose up -d
docker compose down

# 重启单个服务
docker compose restart api
docker compose restart web
docker compose restart nginx
docker compose restart plugin_daemon

# 查看日志
docker compose logs api --tail=50
docker compose logs web --tail=50
docker compose logs plugin_daemon --tail=50

# 查看所有容器状态
docker compose ps

# 更新容器(先拉新镜像)
docker compose pull api web
docker compose up -d

# 升级前备份数据库
docker compose exec db pg_dump -U postgres dify > dify_backup_$(date +%Y%m%d).sql

# 进入数据库
docker compose exec db psql -U postgres -d dify

# 查看资源占用
docker stats

附:整体架构图

bash 复制代码
用户
  │
  ▼
http://域名:3199(或外网穿透端口)
  │
  ├── nginx (监听 3199)
  │     │
  │     ├── /console/api/* ──→ api:5001
  │     ├── /api/*         ──→ api:5001
  │     ├── /files/*       ──→ api:5001
  │     └── /*             ──→ web:3000
  │
  ├── api:5001       ← Dify API 服务
  ├── worker         ← Celery 异步任务
  ├── web:3000       ← Next.js 前端
  ├── plugin_daemon:5002  ← 插件后台
  │
  ├── db:5432        ← PostgreSQL 15
  ├── redis:6379     ← 缓存 / Celery Broker
  └── weaviate:8080  ← 向量数据库

总结

Dify 自部署核心就三点:

  1. nginx 统一入口 --- 解决跨域和端口暴露问题
  2. plugin_daemon 环境变量补全 --- 这版 daemon 配置检查很严格,缺一个就崩
  3. 数据挂载到大分区 --- 避免系统盘撑爆

照着上面一步步走,半小时内应该能跑起来。遇到问题先看第 10 节,基本覆盖了所有常见坑。

如果对你有帮助,点个 👍~

相关推荐
Moment3 小时前
长上下文会最终杀死 Rag 吗?
前端·javascript·后端
蝎子莱莱爱打怪4 小时前
🚀 🚀🚀2026年5月GitHub月榜精选:17个项目中挑出10个推荐,实操4个!
人工智能·后端·ai编程
砍材农夫5 小时前
物联网实战:Spring Boot MQTT | MQTT 设备模拟器演示(附源码)
java·spring boot·后端·物联网·spring·netty
我叫黑大帅5 小时前
解决聊天页内部滚轮改为页面滚动问题
javascript·后端·面试
IT_陈寒6 小时前
Python的线程池居然把我坑在了垃圾回收这块
前端·人工智能·后端
zhangxingchao7 小时前
AI应用开发八:RAG相关技术总结
前端·人工智能·后端
吴佳浩7 小时前
Go史上最大“打脸”现场来了:泛型方法终于实现了
后端·go
Huyuejia7 小时前
runtime-ask
后端
Rust研习社7 小时前
90% 的 Rust 新手都不知道的 3 个实用开发技巧
后端·rust·编程语言
ZengLiangYi7 小时前
sql.js WASM 深度解析
javascript·数据库·后端