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

0 阅读10分钟

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

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

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


目录

  1. 前置要求
  2. 安装 Docker 环境
  3. 目录规划
  4. 编写 docker-compose.yaml
  5. 编写 nginx 配置
  6. 启动全部容器
  7. 数据库迁移
  8. 首次访问与初始化
  9. 外网访问(NPS 内网穿透)
  10. 常见问题与踩坑记录
  11. 日常运维命令

1. 前置要求

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

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

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

2. 安装 Docker 环境

# ----- 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. 目录规划

# 创建部署目录
sudo mkdir -p /data/dify
cd /data/dify

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

# 假设 /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

最终目录结构:

/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

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_PASSWORDPostgreSQL 密码
REDIS_PASSWORDRedis 密码
PLUGIN_DAEMON_KEY / SERVER_KEY插件 daemon 密钥,两处保持一致
DIFY_INNER_API_KEYAPI 与插件 daemon 内部通信密钥,两处保持一致
PLUGIN_REMOTE_INSTALLING_HOST外网可访问的域名或 IP
PLUGIN_REMOTE_INSTALLING_PORT外网端口

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

# 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

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. 启动全部容器

cd /data/dify

# 启动
docker compose up -d

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

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

正常输出应该长这样:

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 容器启动后,需要执行数据库迁移来创建表结构:

# 执行数据库迁移
docker compose exec api flask db upgrade

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

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

docker compose exec db psql -U postgres -d dify -c "\dt"

8. 首次访问与初始化

本地访问:

http://你的服务器IP:3199

初始化步骤:

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

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


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

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

NPS 隧道配置示例

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

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

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

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

http://你的域名:33099/v1

10. 常见问题与踩坑记录

10.1 前端白屏 / API 404

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

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

解决: web 容器 environment 中加:

CONSOLE_API_URL: ""
APP_API_URL: ""

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

10.2 插件报 500 / PluginDaemonInnerError

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

Failed to resolve 'plugin_daemon' - Name or service not known

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

排查:

docker compose ps plugin_daemon
# 如果是 Restarting,看日志
docker logs dify-plugin_daemon-1

10.3 plugin_daemon 启动崩溃

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

[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 一次。必须补全以下环境变量:

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 映射到大分区,上面的配置已经做了这件事。

检查磁盘空间:

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 容器日志:

docker compose logs api --tail=20

11. 日常运维命令

# 进入部署目录
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

附:整体架构图

用户
  │
  ▼
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 节,基本覆盖了所有常见坑。

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