はじめに
こんにちは。10月も半ばを過ぎ、秋らしい空気が広がっていますね。
紅葉が見頃になるのが待ち遠しいです。
AWSエンジニアの小林です。
さて今回は、生成AIアプリの開発プラットフォームとして注目を集めている「 Dify」を扱っていきます。
Difyには、Dify自体が提供するSaaSとは別に、Dockerを利用してセルフホストできる Community Edition があります。
本記事では、Community EditionでDify構築を行っていきます。
docker-compose.yamlを使用してアプリケーションをデプロイする際、デフォルトでデータベースもコンテナとして構築し、管理しています。
これは試験的な開発にはとても便利ですが、アップデートの運用などを考えるとコンテナの停止や削除によるデータ損失リスクなど課題が出てきます。
そこで、安全にDifyをアップデートするためにデータベースを自前で用意してDifyに組み込んでみたいと思います。
Difyの概要
DifyはLLMを使用した生成AIアプリをノーコードで簡単に作成できるオープンソースのプラットフォームです。
dify.ai
Difyについては以下の記事で詳細が説明されているので、参考にしてもらえればと思います。
acro-engineer.hatenablog.com
自前で用意したDBをDifyに組み込む
Dify用データベースを構築する
DifyではデータベースとしてPostgreSQLを使用します。
そこで今回は、Amazon RDS for PostgreSQLでデータベースを用意していきます。
構築するアーキテクチャは次の通りです。

パブリックサブネットおよびプライベートサブネット、Difyサーバー用EC2インスタンスは既に構築済みとして進めていきます。
RDS > データベースの作成ページを開きます。
「エンジンのオプション」で「PostgreSQL」を選択します。

「設定」>認証情報の設定で指定する、「マスターユーザー名」、「パスワード」はDifyの設定ファイルに使用するので控えておきます。
また、「パスワードを自動生成」の場合、パスワードは「データベースの作成」を押下後のダイアログからしか確認できないため注意してください。

「接続」で、「コンピューティングリソース」としてDifyサーバー用のEC2インスタンスを選択します。
これによって、EC2インスタンスがRDSに接続するためのセキュリティグループ設定が自動で構築されます。

続いて、構築したRDS PostGreSQLに、Dify用のデータベースを作成します。
Difyサーバー用EC2インスタンスにSSH接続し、以下コマンドでPostgreSQLをインストールします。
$ sudo dnf install -y postgresql15-server
構築したRDSのPostgreSQLに接続します。
$ psql -h {RDSのエンドポイント} -p {RDSのport} -U postgresPostgreSQLにDifyアプリケーション用のデータベースをdifyという名前で作成します。
postgres=> CREATE DATABASE dify;
以上で、自前のPostgreSQLデータベースの構築は完了です。
Dify構築用ソースを修正する
Difyサーバー用EC2インスタンスにSSH接続し、以下コマンドでDify構築に必要なソフトウェアをインストールします。
$ sudo yum update -y
$ sudo yum install -y git
$ sudo yum install -y docker
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
$ mkdir -p $DOCKER_CONFIG/cli-plugins
$ curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
$ sudo chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
$ sudo systemctl start docker
$ sudo systemctl enable docker
$ sudo chmod 666 /var/run/docker.sock以下コマンドで、Difyの公式リポジトリからソースコードを取得します。
$ git clone https://github.com/langgenius/dify.git
今回は後々Difyのアップデートを実施するので、古い0.8.3バージョンを使用します。
$ git checkout -b main-0.8.3 refs/tags/0.8.3
既存のdify/docker/docker-compose.yamlファイルを修正し、データベースをコンテナで立ち上げないようにします。
次の2点を修正します。
# The postgres database. # db: # image: postgres:15-alpine # restart: always # environment: # PGUSER: ${PGUSER:-postgres} # POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456} # POSTGRES_DB: ${POSTGRES_DB:-dify} # PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata} # command: > # postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}' # -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}' # -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' # -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' # -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' # volumes: # - ./volumes/db/data:/var/lib/postgresql/data # healthcheck: # test: [ "CMD", "pg_isready" ] # interval: 1s # timeout: 3s # retries: 30
# API service api: image: langgenius/dify-api:0.8.3 restart: always environment: # Use the shared environment variables. <<: *shared-api-worker-env # Startup mode, 'api' starts the API server. MODE: api depends_on: # - db - redis volumes: # Mount the storage directory to the container, for storing user files. - ./volumes/app/storage:/app/api/storage networks: - ssrf_proxy_network - default
# worker service # The Celery worker for processing the queue. worker: image: langgenius/dify-api:0.8.3 restart: always environment: # Use the shared environment variables. <<: *shared-api-worker-env # Startup mode, 'worker' starts the Celery worker for processing the queue. MODE: worker depends_on: # - db - redis volumes: # Mount the storage directory to the container, for storing user files. - ./volumes/app/storage:/app/api/storage networks: - ssrf_proxy_network - default
次に、以下コマンドで環境変数用ファイル.envを用意し、.envで定義されているデータベースへの接続情報を修正します。
$ cp .env.example .env
# ------------------------------
# Database Configuration
# The database uses PostgreSQL. Please use the public schema.
# It is consistent with the configuration in the 'db' service below.
# ------------------------------
DB_USERNAME={RDSのマスターユーザー名}
DB_PASSWORD={RDSのパスワード}
DB_HOST={RDSのエンドポイント}
DB_PORT=5432
DB_DATABASE={RDSのPostgreSQLに作成したデータベース名}
Difyを構築する
それではDifyアプリケーションを構築します。
$ docker compose up -d
アプリケーションが起動することが確認できました。

アプリケーション用のPostgreSQLテーブル等のスキーマは、自前のデータベースであっても自分で定義する必要なくDify構築時に生成されます。
以下コマンドで作成されたテーブル一覧が確認できます。
$ psql -h {RDSのエンドポイント} -p {RDSのport} -U postgres
postgres=> /connect {RDSのPostgreSQLに作成したデータベース名}
{RDSのPostgreSQLに作成したデータベース名}=> \dt
簡単なチャットアプリケーションとして、「chat application」を作成しておきます。
また、Difyのバージョンが0.8.3であることも確認しておきます。

安全にDifyをアップデートする
次にDifyのバージョンをアップデートしていきます。
まずは、Docker コンテナを停止します。
$ docker compose down
アップデート用に0.9.1バージョンを使用します。
$ git checkout -b main-0.9.1 refs/tags/0.9.1
0.8.3を構築したとき同様の修正を、docker-compose.yaml,.envファイルに適用します。
その後、アプリケーションを起動します。
$ docker compose up -d
無事、Difyが0.9.1にアップデートできていることが確認できました!
0.8.3で作成した「chat application」もそのまま残っています。

まとめ
今回はDifyのデータベースを自前で用意して安全なアップデートを試してみました。
アップデートなどの運用面で、アプリケーションとデータベースを分けて管理するメリットは大きいと思います。
Dockerコンテナで立ち上げるデフォルト設定から、大きな変更なく自前のデータベースに繋げられるのは良いですね。
今回はDBスキーマ自体の変更はなかったので、Difyのアプリ本体のアップデートだけで簡単にアップデートできました。
DBスキーマ自体に変更があり、自前のデータベースへのスキーマ移行が必要となる場合はDifyのアップデート情報を確認してください。
Acroquest Technologyでは、キャリア採用を行っています。
- Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
- ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
- マイクロサービス、DevOps、最新のOSSやクラウドサービスを利用する開発プロジェクト
- 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。