Dify:自建AI工作流平台

如何使用 Pigsty 自建 AI Workflow LLMOps 平台 —— Dify,并使用外部 PostgreSQL,PGVector 作为存储?

Dify 是一个生成式 AI 应用创新引擎,开源的 LLM 应用开发平台。 提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力,帮助用户轻松构建和运营生成式 AI 原生应用。

Pigsty 提供对自建 Dify 的支持,您可以一键拉起 Dify ,并将关键状态保存于外部由 Pigsty 管理的 PostgreSQL, 并使用同一个 PG 中的 pgvector 作为向量数据库,进一步简化版部署。

当前 Pigsty v3.4 支持的 Dify 版本为:v1.1.3


快速上手

在安装 兼容发行版 的全新 Linux x86 / ARM 服务器上执行:

curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty 
./bootstrap                # 安装 Pigsty 依赖
./configure -c app/dify    # 使用 Dify 配置模板 
vi pigsty.yml              # 修改密码,域名,密钥等参数
./install.yml              # 安装 Pigsty
./docker.yml               # 安装 Docker 模块
./app.yml                  # 拉起 Dify

Dify 默认监听于 5001 端口,你可以通过浏览器访问 http://<ip>:5001,并设置初始用户与密码后登陆。

Dify 启动后,你可以安装各种扩展插件,配置好系统模型之后,就可以开始使用了!


为何自建

自建 Dify 的原因有很多,但主要是出于数据安全的考虑。 Dify 提供的 DockerCompose 模板使用的是简陋的默认数据库镜像,缺少企业级应用所需的高可用性,容灾能力,监控,IaC,PITR 等能力。

Pigsty 可以优雅地为 Dify 解决这些问题,根据配置文件一键拉起所有组件,并使用镜像解决国内翻墙难题。让 Dify 的部署与交付无比丝滑。 一次性解决 PostgreSQL 主数据库与 PGVector 向量数据库,MinIO 对象存储,Redis,Prometheus 监控与 Grafana 可视化,以及 Nginx 反向代理,免费 HTTPS 证书。

Pigsty 可以确保 Dify 所有的状态都存储在外部托管服务中,包括 PostgreSQL 中的元数据,与文件系统中的其他数据。 因此,使用 Docker Compose 拉起的 Dify 是无状态的简单应用,可以随时销毁与重建,极大简化了运维。


单机安装

让我们先从单节点 Dify 部署开始,我们会在后面进一步介绍生产环境高可用部署的方法。

首先,使用 Pigsty 标准安装流程 安装 Dify 所需的 PostgreSQL 实例;

curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty
./bootstrap               # 准备 Pigsty 依赖
./configure -c app/supa   # 使用 Supabase 应用模板
vi pigsty.yml             # 编辑配置文件,修改域名与密码
./install.yml             # 安装 Pigsty,以及各种数据库

当你使用 ./configure -c app/dify 命令时,Pigsty 会自动根据 conf/app/dify.yml 配置模板,以及您当前的环境生成 Pigsty 配置文件。 您应该根据自己的实际需求,在生成的 pigsty.yml 配置文件中,修改密码,域名等相关参数,然后使用 ./install.yml 执行标准安装流程即可。

接下来,运行 docker.yml 安装 Docker 与 Docker Compose, 然后使用 app.yml 剧本完成 Dify 的部署:

./docker.yml              # 安装 Docker 与 Docker Compose
./app.yml                 # 使用 Docker 拉起 Supabase 无状态部分

你可以可以在本地网络通过 http://<your_ip_address>:5001 访问到 Dify Web 管理界面。

默认的用户名,邮箱,密码会在首次登陆时提醒您设置。

你也可以使用本地解析的占位域名 dify.pigsty,或者参考下面的配置,使用真正的域名与 HTTPS 证书。

整个安装过程非常简单,几行命令,十分钟左右即可完成。真正的难点主要在于正确配置参数,下面会详细介绍。


配置详情

当你使用 ./configure -c app/dify 命令进行配置时,Pigsty 会自动根据 conf/app/dify.yml 配置模板,以及您当前的环境生成 Pigsty 配置文件。以下是默认配置文件的详细说明:

all:
  children:

    dify:
      hosts: { 10.10.10.10: {} }
      vars:
        app: dify   # 指定要安装的应用名称(在 apps 中)
        apps:       # 定义所有应用
          dify:     # 应用名称,应该有对应的 ~/pigsty/app/dify 文件夹
            
            file:   # 需要创建的数据目录,创建 /data/dify 用于存储各种插件
              - { path: /data/dify ,state: directory ,mode: 0755 }
            
            conf:   # 覆盖 /opt/dify/.env 配置文件

              # Dify 使用的域名,请替换为您的实际域名,如果使用这个默认域名,你要自己添加本地/内网解析记录
              NGINX_SERVER_NAME: dify.pigsty
              # 用于签名和加密的密钥,可通过 `openssl rand -base64 42` 生成(请修改这个密钥!)
              SECRET_KEY: sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
              # 默认使用端口 5001 暴露 DIFY nginx 服务
              DIFY_PORT: 5001
              # 存储 Dify 文件的位置?默认是 ./volume,我们将使用上面创建的另一个卷 /data/dify 存储数据
              DIFY_DATA: /data/dify

              # 代理和镜像设置,对于中国地区,可以使用清华大学 PIP 镜像加速下载
              #PIP_MIRROR_URL: https://pypi.tuna.tsinghua.edu.cn/simple
              #SANDBOX_HTTP_PROXY: http://10.10.10.10:12345
              #SANDBOX_HTTPS_PROXY: http://10.10.10.10:12345

              # 数据库凭据,这里 PGVECTOR 和 PostgreSQL 使用同一个数据库,使用 pg-meta 集群中的 Dify 用户即可
              DB_USERNAME: dify
              DB_PASSWORD: difyai123456
              DB_HOST: 10.10.10.10
              DB_PORT: 5432
              DB_DATABASE: dify
              VECTOR_STORE: pgvector
              PGVECTOR_HOST: 10.10.10.10
              PGVECTOR_PORT: 5432
              PGVECTOR_USER: dify
              PGVECTOR_PASSWORD: difyai123456
              PGVECTOR_DATABASE: dify
              PGVECTOR_MIN_CONNECTION: 2
              PGVECTOR_MAX_CONNECTION: 10

    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - { name: dify ,password: difyai123456 ,pgbouncer: true ,roles: [ dbrole_admin ] ,superuser: true ,comment: dify 超级用户 }
        pg_databases:
          - { name: dify    ,owner: dify ,revokeconn: true ,comment: dify 主数据库  }
          - { name: dify_fs ,owner: dify ,revokeconn: true ,comment: dify 文件系统数据库    }
        pg_hba_rules:
          - { user: dify ,db: all ,addr: 172.17.0.0/16  ,auth: pwd ,title: '允许 dify 从本地 docker 网络访问' }
        node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨1点进行一次完整备份

    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

  vars:                               # 全局变量
    version: v3.4.0                   # pigsty 版本字符串
    admin_ip: 10.10.10.10             # 管理节点 IP 地址
    region: default                   # 上游镜像区域:default|china|europe
    node_tune: oltp                   # 节点调优规格:oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # PostgreSQL 调优规格:{oltp,olap,tiny,crit}.yml

    docker_enabled: true              # 在 app 组上启用 docker
    #docker_registry_mirrors: ["https://docker.1ms.run"] # 在中国大陆使用镜像站,否则需要你配置 proxy_env 进行科学上网

    proxy_env:                        # 下载软件包和拉取 docker 镜像时的全局代理环境
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.tsinghua.edu.cn"
      #http_proxy:  127.0.0.1:12345 # 在此添加您的代理环境用于下载软件包或拉取镜像
      #https_proxy: 127.0.0.1:12345 # 通常代理格式为 http://user:[email protected]
      #all_proxy:   127.0.0.1:12345

    infra_portal: # 域名和上游服务器
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }
      #minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      
      dify:                            # dify 的 nginx 服务器配置
        domain: dify.pigsty            # 替换为您自己的域名!
        endpoint: "10.10.10.10:5001"   # dify 服务端点:IP:PORT
        websocket: true                # 添加 websocket 支持
        certbot: dify.pigsty           # certbot 证书名称,使用 `make cert` 申请

    #----------------------------------#
    # 修改这里的默认密码!!!!!
    #----------------------------------#
    #grafana_admin_username: admin
    grafana_admin_password: pigsty
    #pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    #pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor
    #pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    #patroni_username: postgres
    patroni_password: Patroni.API
    #haproxy_admin_username: admin
    haproxy_admin_password: pigsty
    #minio_access_key: minioadmin
    minio_secret_key: minioadmin      # minio root secret key, `minioadmin` by default

    repo_extra_packages: [ pg17-main ]
    pg_version: 17

检查清单

以下是您需要关注的配置项检查清单:

  • 硬件/软件:准备所需的机器资源:Linux x86_64/arm64 服务器一台,全新安装主流 Linux 操作系统
  • 网络/权限:有 ssh 免密登陆权限,所用用户有免密 sudo 权限
  • 确保机器有内网静态IPv4网络地址,并可以访问互联网。
  • 如果你通过公网访问,请确保您拥有一个可用域名并将其指向当前节点的 公网IP地址
  • 确保使用 app/dify 配置模板,并按需修改参数
    • configure -c app/dify,并输入节点的内网首要 IP 地址,或通过 -i <primary_ip> 命令行参数指定
    • 您是否修改了所有与密码有关的配置参数?【可选】
    • 您是否修改了 PostgreSQL 集群业务用户的密码,以及使用此密码的 App 配置?
      • 默认的用户名 dify 与密码 difyai123456 是 Pigsty 为 Dify 生成的默认用户名与密码,请根据实际情况修改
      • Dify 的配置块中,请相应修改 DB_USERNAMEDB_PASSWORDPGVECTOR_USERPGVECTOR_PASSWORD 等参数
    • 您是否修改了 Dify 默认使用的加密密钥?
      • 你可以使用 openssl rand -base64 42 随机生成一个密码字符串,填入 SECRET_KEY 参数中
    • 您是否修改了 Dify 使用的域名?
      • 将占位符域名 dify.pigsty 替换为您的实际域名,例如 dify.pigsty.cc
      • 您可以使用 sed -ie 's/dify.pigsty/dify.pigsty.cc/g' pigsty.yml 修改 Dify 使用的域名

域名证书

如果你希望使用真实的域名与 HTTPS 证书,你需要在 pigsty.yml 配置文件中,修改:

  • infra_portal 参数中的 dify 域名
  • 最好指定一个用于接受证书过期通知的邮箱地址 certbot_email
  • 配置 dify 的 NGINX_SERVER_NAME 参数,指定为你的实际域名
all:
  children:                            # 集群定义
    dify:                              # Dify 分组
      vars:                            # Dify 分组变量
        apps:                          # 应用配置
          dify:                        # Dify 应用定义
            conf:                      # Dify 应用配置
              NGINX_SERVER_NAME: dify.pigsty

  vars:                                # 全局参数
    #certbot_sign: true                # 使用 Certbot 申请免费 HTTPS 证书
    certbot_email: [email protected]      # 申请证书使用的邮箱,用于接受过期通知,可选
    infra_portal:                      # 配置 Nginx 服务器
      dify:                            # Dify 服务器定义
        domain: dify.pigsty            # 请在这里替换为你自己的域名!
        endpoint: "10.10.10.10:5001"   # 请在这里指定 Dify 的 IP 与端口(默认自动配置)
        websocket: true                # Dify 需要启用 websocket 
        certbot: dify.pigsty           # 指定 Certbot 证书名称

使用以下命令申请 Nginx 证书:

# 申请证书,也可以手动执行 /etc/nginx/sign-cert 脚本
make cert

# 以上 Makefile 快捷命令实际上是执行以下剧本任务:
./infra.yml -t nginx_certbot,nginx_reload -e certbot_sign=true

执行 app.yml 剧本,重新拉起 Dify 服务即可让 NGINX_SERVER_NAME 配置生效。

./app.yml

文件备份

你可以使用 restic 对 Dify 文件系统进行备份,Dify 的数据文件在 /data/dify 目录下,你可以使用以下命令对其进行备份:

export RESTIC_REPOSITORY=/data/backups/dify   # 指定 dify 备份目录
export RESTIC_PASSWORD=some-strong-password   # 指定备份加密密码
mkdir -p ${RESTIC_REPOSITORY}                 # 创建 dify 备份目录
restic init

创建 Restic 备份库后,你可以使用以下命令对 Dify 进行备份:

export RESTIC_REPOSITORY=/data/backups/dify   # 指定 dify 备份目录
export RESTIC_PASSWORD=some-strong-password   # 指定备份加密密码

restic backup /data/dify                      # 将 /dify 数据目录备份到仓库
restic snapshots                              # 查看备份快照列表
restic restore -t /data/dify 0b11f778         # 将快照 xxxxxx 恢复到 /data/dify
restic check                                  # 定期检查仓库完整性

另一种更可靠的方式是使用 JuiceFS 将 MinIO 对象存储挂载到 /data/dify 目录下,这样你就可以使用 MinIO/S3 盛放文件状态了。

如果你希望将所有的数据都保存在 PostgreSQL 中,可以考虑 使用 JuiceFS 将文件系统数据保存到 PostgreSQL 中

例如,你可以创建另一个 dify_fs 数据库,并使用它作为 JuiceFS 的元数据存储:

METAURL=postgres://dify:difyai123456@:5432/dify_fs
OPTIONS=(
  --storage postgres
  --bucket :5432/dify_fs
  --access-key dify
  --secret-key difyai123456
  ${METAURL}
  jfs
)
juicefs format "${OPTIONS[@]}"         # 创建一个 PG 文件系统
juicefs mount ${METAURL} /data/dify -d # 后台挂载到 /data/dify 目录
juicefs bench /data/dify               # 测试性能
juicefs umount /data/dify              # 停止挂载

参考阅读





最后修改 2025-04-04: add openhalo (053a5b8)