🏊‍♂️

【Dify Deep Dive #1】Difyのシステムアーキテクチャを理解する

に公開

はじめに

Difyはノーコード/ローコード開発プラットフォームとして、非エンジニアでもアプリケーションを作成できる非常に便利なツールです。
しかし、Difyをセルフホスト(自社の管理するインフラ上)で運用していく際には、Difyのシステムを正確に理解し、不具合対応やバージョン管理を行う必要があります。

「Difyのシステムをより深く理解し、より安定した運用を目指したり、今後のアップデートに柔軟に対応できるようになりたい」

そんな想いを持つ方々のために、Dify Deep Diveと称してDifyのシステム面に関する解説を連載形式でお届けしたいと思います。


なお、
「Difyって何ができるかいまいちわからない」
「使ってみたいけど使い方がよく分からない」
という悩みをお持ちの方々には、先日発刊しましたZenn Bookがお勧めです。
https://zenn.dev/kentaichimura/books/e48a042e40c657

Difyの基礎から具体的なノウハウまで詰め込んでおり、実践的な内容となっています。
また、学習用途だけでなく辞書として傍に添えていただけるような教材にもなっております。
ぜひご覧ください。


さて、記念すべき第1回はDifyのシステムアーキテクチャの概要について説明したいと思います。

システムアーキテクチャ概要

Difyは、Quick Startに従って以下のように簡単にデプロイすることができます。

cd dify
cd docker
cp .env.example .env
docker compose up -d

その裏側では、概ねこのようなコンポーネント群で構成されています。また、利用されている技術スタックは以下のように多様なことがわかります。
(ホストする環境や要件により多少異なる場合があります)


それぞれのコンポーネントについて、利用技術や基本的な役割を確認していきましょう。

nginx

https://github.com/langgenius/dify/tree/main/docker/nginx

システム全体への入り口となるリバースプロキシです。ユーザーからのリクエストを受け付け、パスに応じてトラフィックを振り分けます。
例えば、以下のように https://~~~/ならwebコンテナに、 https://~~~/console/apiならAPIコンテナに、というように振り分けています。

(Optional) Certbot

CertbotはSSL証明書の取得・更新を行う自動化ツールです。Let's Encryptを利用してHTTPS化するためのSSL証明書を自動発行・更新しnginxに提供します。
デフォルトでは無効であり、 docker compose --profile certbot up -d とプロファイルを指定することで有効化できます。

Web

https://github.com/langgenius/dify/tree/main/web
利用技術: TypeScript, Next.js

Difyの管理画面およびエンドユーザー向けWebアプリのUIを提供するWebアプリケーションサーバーです。ブラウザ側からのAPIリクエストは、nginxを経由してAPIコンテナへプロキシされます。

API

https://github.com/langgenius/dify/tree/main/api
利用技術: Python, Flask, SQLAlchemy

Difyのビジネスロジックを持つAPIサーバーです。ユーザーからのリクエストを処理しデータベース操作、LLMとの通信などを行っています。
また、プラグインの実行やノード内でのコード実行はPlugin DaemonSandboxといった他のコンポーネントに処理を委譲することで、実行環境を分離しセキュリティを確保しています。

Worker

※リポジトリはAPIと同様
利用技術: Python, Celery

バックグラウンドタスクを処理する非同期ワーカーです。
APIサーバーは時間のかかるLLMの推論やドキュメントのインデックス化など、重たい処理をRedisキューに投げることでSLOを維持しています。
Celeryというライブラリを利用し、Redisに入ってくるタスクキューの購読を行い非同期に処理します。

Worker Beat

Embeddingキャッシュのクリアや未使用データセットの削除、一部メール送信など定期的なタスクをスケジューリングするコンポーネントです。
定義されたスケジュールに従って、定期タスクキューを投入します。

Sandbox

https://github.com/langgenius/dify-sandbox
利用技術: Go, Python

信頼できないコードを安全に実行するための隔離環境です。 ワークフロー内の「コード実行ノード」において、ユーザーが記述したPythonやJavaScriptコードを実行します。
システム本体(API/Worker)とは別のコンテナで動作しシステムコールやリソースの制限をすることで、セキュリティを確保します。
なお、デフォルトで全てのアウトバウンド通信がSSRF proxyを経由する設定となっています。

SSRF Proxy

https://github.com/langgenius/dify/tree/main/docker/ssrf_proxy
利用技術: Squid

SSRF (Server-Side Request Forgery) 攻撃を防ぐためのHTTPプロキシです。
ユーザーが入力したURL(例: Webスクレイピング機能など)へのアクセス時に、このプロキシを経由させることで、内部ネットワークへの不正なアクセスを遮断します。

なお、OpenAIなどのLLMプロバイダーやS3などのクラウドサービスへの通信は、通常このプロキシを経由せず、コンテナから直接社内ネットワークまたはインターネットを経由して接続します。

Plugin Daemon

https://github.com/langgenius/dify-plugin-daemon
利用技術: Go, Python

プラグイン(拡張機能)の管理と実行を行うコンテナです。インストールされたプラグインのライフサイクルを管理し、プラグインを隔離された環境で実行してAPIサーバーと連携します。
環境変数を設定することにより、リモートデバッグやインストール制御が可能です。
SSRF Proxyを経由せずに直接外部のLLMやツールへ接続します。

Database

Difyでは複数のデータベースを役割に応じて使い分けています。

PostgreSQL

https://www.postgresql.org/
アプリケーションの永続データを管理するメインのデータベースです。RDBMSとして、ユーザー情報、アプリ設定、ワークフロー定義、実行ログ、構造化データセットなどを保存します。
pgvector拡張を利用する場合、ベクトルデータもここに保存されることがあります。

Redis (Broker)

https://redis.io/
Workerのタスクキューとして機能し、APIからWorkerへのタスク受け渡しを仲介します。
また、頻繁にアクセスされるデータやAPIレスポンスをキャッシュし、DB負荷を軽減します。

VectorDB

RAG(検索拡張生成)の要となるベクトル検索エンジンです。
ドキュメントのテキストをベクトル化して保存し、ユーザーの質問(クエリ)と意味的に近いドキュメントを高速に検索します。
以下のようなサービスと互換性があります。

https://weaviate.io/ja
https://qdrant.tech/
https://milvus.io/ja
https://www.trychroma.com/
https://www.sraoss.co.jp/tech-blog/pgsql/pgvector-intro/
https://jp.oceanbase.com/
https://www.oracle.com/jp/
https://www.elastic.co/jp/elasticsearch

Storage

アップロードされたファイル(PDF, 画像等)、構造化データセット、ツールの実行ログなどを保存するストレージです。
通常はS3またはS3互換のパブリッククラウドサービスを利用します。
https://aws.amazon.com/jp/s3/
コンテナのボリュームにマウントすることも可能ですが、コンテナのライフサイクルに依存してしまうため注意が必要です。

おわりに

今回はDifyのシステムアーキテクチャの全体像を掴むために、各コンテナがどういった役割かを解説していきました。
UI上ではシームレスに使われている機能も、裏側では明確に責務分離されていることがわかったと思います。

次回以降で、各コンポーネントで詳細に何が行われているかを深掘りしていこうと思います。

UPGRADE tech blog

Discussion