はじめに
- データの同期: Difyのコンテナは、データをフォルダに同期します。このため、フォルダごとコピーすればデータを移行できます。
- データのコピー手順: 保存されたデータは新しい環境のフォルダにコピーします。具体的には、旧DifyのVolumesフォルダ内容を新しいDifyフォルダに上書きします。
- コンテナの設定: 環境変数の書き換えが必要です。.envファイルを作成し、設定を調整します。このことで、移行後も設定が保持されます。
- バックアップ: データ移行前にバックアップを取ることが推奨されます。DockerのボリュームをGzip形式で圧縮して保存します。
- 復元手順: SSHで新環境にログインし、バックアップファイルを展開してDockerを起動します。
バックアップの方法 [1]
-
-
- バックアップ作成手順: Docker Composeを停止し、Difyディレクトリ全体をtarコマンドで圧縮します。
Dockerディレクトリに移動 sudo docker compose down
- 保存場所: バックアップファイルは安全な場所に確保することが重要です。
Difyを格納しているフォルダーのルートに移動し、「cd ..」にて一つ上の階層に移動 tar -czvf dify_backup.tar.gz dify ※difyディレクトリをdify_backup.tar.gzに圧縮して格納
- バックアップ作成手順: Docker Composeを停止し、Difyディレクトリ全体をtarコマンドで圧縮します。
-
- 復元準備: バックアップファイルを適切に管理し、復元時のアクセスを容易にする必要があります。
移行手順の具体例 [2]
- 旧環境の停止: 前回起動したディレクトリに移動後停止させます。
- 新フォルダ作成: 新しいDifyのコンテナを作るため、フォルダを作成しリポジトリをクローンします。
- 環境変数の設定: .envファイルを作成し、必要な設定を調整。
scpを使用してサーバ間でファイルのコピーを行う
SSHの認証公開キーを作成する
移行元サーバでSSH鍵を生成する: まだ鍵がない場合、以下のコマンドで鍵を生成します。パスフレーズは空でも構いませんが、設定しておくとより安全です。
「ssh-keygen」コマンドを使用してコピー元のサーバへSSHの公開鍵と秘密鍵のペアを生成します。
$ sudo ssh-keygen
<実行結果>
$ sudo ssh-keygen
Generating public/private rsa key pair.・
Enter file in which to save the key (/root/.ssh/id_rsa):←格納先のフォルダーを指定(Enterでデフォルトの/root/.ssh/id_rsaへ格納されます。)
Enter passphrase (empty for no passphrase): ←公開キー利用の為のパスフレーズ
Enter same passphrase again: ←パスフレーズの再入力
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:o57j6tqpJ+cLrvkn1hZxTDpheHVSq6sh6D2Nx+aJYiw root@dify.com
The key's randomart image is:
+---[RSA 3072]----+
| . .o.o |
| . + .o . |
| o = . |
| + o. |
| +. S |
| . . o . |
|o o.=.o |
|E*=*BXo. |
|==*#&*+. |
+----[SHA256]-----+
移行元サーバーの公開鍵を移行先サーバーにコピーする
以下のコマンドを実行すると、パスワード認証を一度だけ使って公開鍵を移行先サーバーに登録できます。
$ sudo ssh-copy-id dify@192.168.1.1 ←移行先のユーザ名(dify)とIPアドレス(192.168.1.1)
<実行結果>
$ sudo ssh-copy-id dify@192.168.1.1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed Enter passphrase for key '/root/.ssh/id_rsa': ←先に設定したパスコード
※尚、sshが上手く接続できない場合には、先に移行元サーバで作成した「id_rsa.pub
」の内容をターゲット先の~/etc/.ssh/authorized_keysの内容にvi等で追加することで、移行先サーバーに登録できます。
移行元サーバーの圧縮ファイルを移行先サーバーにコピーする
$ sudo scp /home/dify/dify_backup.tar.gz
dify@192.168.1.1:/home/mirrormaster/
パスワード入力が求められずに、コピーが完了するはずです。
<実行結果>
$ sudo scp /home/kagami-dify/dify_backup.tar.gz
dify@192.168.1.1
:/home/mirrormaster/ Enter passphrase for key '/root/.ssh/id_rsa':←先に設定したパスコード dify_backup.tar.gz
復元手順 [1]
-
- SSHログイン: 新しいサーバーにSSHでログインします。
- バックアップファイルの確認: バックアップファイルが目的の場所にあることを確認します。
-
-
- バックアップ展開: tarコマンドを使ってバックアップファイルを解凍します。
$ tar -xzvf dify_backup.tar.gz -C dify -x:ファイルを解凍するオプションです。 -z:
gzip
で圧縮されたファイルを扱います(.gz
に対応)。 -v:解凍中にファイルリストを詳細に表示します(verbose)。 -f:アーカイブファイルの名前を指定します(file)。 -C:解凍先のディレクトリを指定します(change directory) ※dify_backup.tar.gzは解凍元のファイル difyは解凍先のディレクトリ名(このディレクトリの下に解凍元のディレクトリが作成される)
- Docker Compose起動: コンテナをバックグラウンドで立ち上げます。
- バックアップ展開: tarコマンドを使ってバックアップファイルを解凍します。
-
データの同期と保存場所 [2]
- フォルダの役割: Difyのコンテナはデータをフォルダに同期します。
- 保存場所の確認: データはdify/docker/volumesフォルダに格納されています。
- データのコピー方法: 新しい環境のvolumesフォルダにデータをコピーします。
データベースの移行
1. pg_dumpとpsqlを使った方法(推奨)
この方法は、データベースの内容をSQLファイルとしてエクスポートし、それを新しいサーバーにインポートします。データ量が多い場合や、データベースのバージョンが異なる場合に適しています。
ステップ1: サーバーAでデータをバックアップする (ダンプ)
- Difyコンテナを停止する: データベースの整合性を保つため、まずDifyのコンテナをすべて停止します。
cd /path/to/dify_directory docker-compose down
pg_dump
コマンドを実行する: Docker Composeを使用して、db
コンテナ内でpg_dump
を実行し、データをSQLファイルとして出力します。docker-compose exec -T db pg_dump -U postgres -d dify > dify_backup.sql
exec -T
: コンテナ内でコマンドを実行します。-U postgres
: PostgreSQLのユーザー名を指定します。-d dify
:dify
データベースを指定します。
ステップ2: サーバーBへSQLファイルを転送する
SCPコマンドを使って、作成したdify_backup.sql
ファイルをサーバーBに転送します。
scp dify_backup.sql mirrormaster@163.44.113.144:/path/to/difyai_directory/
ステップ3: サーバーBでデータを復元する (リストア)
- 新しいDify環境を起動する: 新しいサーバー(
difyai
)で、空のデータベースを持つDifyコンテナを起動します。cd /path/to/difyai_directory docker-compose up -d
psql
コマンドを実行する: Docker Composeを使用して、db
コンテナ内でpsql
を実行し、SQLファイルをインポートします。cat dify_backup.sql | docker-compose exec -T db psql -U postgres -d dify
- コンテナを再起動する: データのインポート後、コンテナを再起動して設定を反映させます。
docker-compose restart
2. ボリュームを直接コピーする方法
この方法は、データベースのデータそのものを物理的にコピーします。データベースのバージョンが同じ場合に適しています。
ステップ1: サーバーAでボリュームの場所を特定する
- コンテナを停止する:
docker-compose down
を実行してコンテナを停止します。 - ボリュームのパスを調べる:
docker inspect
コマンドで、db
コンテナがマウントしているボリュームのホスト上の場所を特定します。docker inspect [コンテナIDまたはコンテナ名]
出力されるJSONの
Mounts
セクションにあるSource
が物理パスです。通常は/var/lib/docker/volumes/[ボリューム名]/_data
のようなパスになります。
ステップ2: データをサーバーBにコピーする
- ボリュームを圧縮する:
tar -czvf db_volume_backup.tar.gz /var/lib/docker/volumes
- 圧縮ファイルを転送する:
scp db_volume_backup.tar.gz mirrormaster@163.44.113.144:/path/to/destination/
ステップ3: サーバーBでデータを復元する
- 新しいDify環境のボリュームを準備する: サーバーBの
difyai
ディレクトリで、まずdocker-compose up -d
を実行して、空のデータベースボリュームを作成します。 - 新しいコンテナを停止する:
docker-compose down
を実行します。 - ボリュームのパスを特定する:
docker inspect
で、サーバーB上の新しいデータベースボリュームの物理パスを調べます。 - バックアップデータを展開する: サーバーBの
root
ユーザーで、新しいボリュームの物理パスに直接バックアップファイルを展開します。tar -xzvf db_volume_backup.tar.gz -C /path/to/new/db/volume/on/server_B
- バックアップファイルを展開する: 新しいサーバーの
/var/lib/
ディレクトリに移動し、バックアップファイルを展開します。sudo tar -xzvf docker_volumes_backup.tar.gz -C /
※但し、既存環境が存在する場合には、/var/lib/volumesではなく、/var/lib/volumes2等異なるディレクトリへ展開する必要必要があります。
異なるディレクトリへの解凍は一旦/var/lib/tmpなどの名前のディレクトリ上に解凍して、mv dify/* .やmv dify/{.,}* .、mv dify/.??* .などのコマンドを使用してファイルの保管ディレクトリを変更します。
最後に不要なディレクトリをrmdir difyにて削除します。
ステップ4: ボリュームの認識とdocker-compose.ymlの変更
volumes2
というディレクトリにデータを解凍した場合、Difyコンテナにそれを認識させるには、docker-compose.yml
のボリュームマッピングを変更する必要があります。
変更前の設定
これは、名前付きボリュームを使用している場合です。
services:
db:
volumes:
- 'dify_db_data:/var/lib/postgresql/data'
volumes:
dify_db_data:
※Dockerはデータを独自のボリュームに格納しており、コンテナは、ホスト上の特定のディレクトリ(この場合は/var/lib/postgresql/
)にデータを直接書き込むのではなく、Dockerが管理する抽象化されたボリュームを使用します。このボリュームの実体は、ホスト上の/var/lib/docker/volumes/
以下に存在します。
PostgreSQLのデータが実際にどこに保存されているかを確認するには、docker inspect
コマンドを使用します。
docker inspect [コンテナ名またはコンテナID]
このコマンドの出力にあるMounts
セクションのSource
が、データが実際に保存されているホスト上の物理パスです。
変更後の設定
解凍したホスト上の物理パスを直接指定するように変更します。
services:
db:
volumes:
- '/var/lib/docker/volumes2/dify_db_data/_data:/var/lib/postgresql/data'
この変更により、Dockerはdify_db_data
という名前付きボリュームを探す代わりに、指定された物理ディレクトリのデータを使用します。
ステップ5: コンテナを起動する
docker-compose up -d
でDifyを再起動すると、元のデータが読み込まれます。
ディレクトリをそっくり移行する手順
- 元のサーバー(A)でDockerコンテナを停止する: データの不整合を防ぐため、移行するDifyコンテナをすべて停止します。
docker-compose down
- ボリュームディレクトリを圧縮する: Dockerのボリュームデータが格納されている
/var/lib/docker/volumes/
ディレクトリを、tar
コマンドなどで圧縮します。これにより、すべてのボリュームを一つのファイルとして扱えます。sudo tar -czvf docker_volumes_backup.tar.gz /var/lib/docker/volumes
- 新しいサーバー(B)にファイルを転送する:
scp
やrsync
などのツールを使って、圧縮したファイルを新しいサーバーに転送します。 - 新しいサーバーでDockerを停止する: もしDockerが動いていれば停止します。
sudo systemctl stop docker
- バックアップファイルを展開する: 新しいサーバーの
/var/lib/
ディレクトリに移動し、バックアップファイルを展開します。sudo tar -xzvf docker_volumes_backup.tar.gz -C /
3.pg_dumpとpsqlを使った方法とボリュームを直接コピーする方法の比較
2つのバックアップ方法の違い
データベースをバックアップする最初の方法(pg_dump
/psql
)と、2番目の方法(ボリュームを直接コピー)の主な違いは、システムの負荷ではなく、安全性と互換性です。
「pg_dump
とpsql」
を使った方法は、同一のデータベースでの管理となり、「ボリュームを直接コピーする方法」はDifyコンテナ毎にデータベースを分離するため、より独立性の高い環境を構築できます。このため、今回は「ボリュームを直接コピーする方法」を使用します。
結論: pg_dump
/psql
を使った方法は、少し複雑ですが、データの安全性が非常に高く、最も推奨される方法です。ボリュームを直接コピーする方法は、簡単ですが、両サーバーの環境が完全に一致していないと動作しないリスクがあります。
どちらの方法も、元の環境と新しい環境のDifyのバージョンが一致していることを確認してください。 バージョンが異なると、データベースのスキーマが合わず、正常に動作しない可能性があります。
4.pg_dumpとpsqlを使った方法とボリュームを直接コピーする方法の比較
コンテナの設定変更 [2]
- 環境変数の書き換え: .envファイル作成で環境設定が簡易化されます。
- ポート番号の変更: ポート番号を.envファイルで設定できます。
- 設定の重要性: デフォルト設定ではセキュリティが懸念されるため、カスタマイズが推奨されます。
.envファイルの書き換えポイント
解決方法
以下のいずれかの方法で、このポート競合の問題を解決できます。
競合Portが発生した場合
1. ポートを使用しているプロセスを特定して停止する
最も直接的な解決策です。5003
番ポートを使用しているプロセスを特定し、そのプロセスを停止します。
- プロセスを特定するコマンド:
Bash
sudo lsof -i :5003
または
Bash
sudo netstat -tulpn | grep 5003
- プロセスの停止:
- 上記のコマンドで表示されたプロセスID(PID)を確認し、
sudo kill <PID>
コマンドでプロセスを停止します。
- 上記のコマンドで表示されたプロセスID(PID)を確認し、
2. Difyコンテナのポートマッピングを変更する
もし、ポートを使用しているプロセスを停止できない場合や、恒久的な解決策が必要な場合は、difyai-plugin_daemon-1
コンテナのポートマッピングを変更します。
docker-compose.yml
ファイルで、plugin_daemon
サービスのポート設定を編集します。YAML
plugin_daemon: ... ports: # 例: 5003ポートを別のポートにマッピングする - "5004:5003"
この例では、ホストマシンの
5004
番ポートがコンテナの5003
番ポートにバインドされるようになります。
推奨される手順
新しい環境へのアクセス [2]
- ローカルアクセス試行: 新しいDify環境にローカルIPアドレスでアクセスして接続を確認します。
- ポート番号の確認: 設定したポート番号を使用して新しい環境にアクセス。
- 設定保持の確認: 全てのチャットボットなどの設定がアップデート後も保持されていることを確認します。
はい、可能です。お考えの手順は、Dockerコンテナ環境を柔軟に管理し、複製するために非常に有効な方法です。
手順の整理と補足
提供された手順は概ね正しいですが、いくつかの点を整理・補足します。
1. Difyディレクトリのコピー
- 最初に、元の
dify
ディレクトリをdify2
としてコピーします。これにより、コードと設定ファイルが複製されます。
2. volumesディレクトリのリネーム
dify2/docker
ディレクトリ内のvolumes
ディレクトリをvolumes2
にリネームします。このステップが重要です。 ホストマシン上のボリュームのパスを新しいものに変更することで、既存のコンテナのデータと干渉せずに、新しいコンテナのデータを独立して永続化できます。
3. .envファイルの修正
- 新しく作成した
dify2/docker
ディレクトリ内に.env
ファイルを作成し、VOLUME=volumes2
と記述します。これにより、dify2
ディレクトリ内でdocker-compose up
を実行した際に、docker-compose.yml
が新しいvolumes2
ディレクトリを参照するようになります。
4. ボリュームデータのコピー
- このステップは、既存のデータを引き継ぎたい場合にのみ必要です。
dify
コンテナで作成された既存のデータ(/var/lib/docker/volumes/dify_docker_volumes_db_data/_data
など)を、新しいコンテナのディレクトリにコピーします。- 注意点: Dockerのデータ管理方法から、単純なファイルシステムのコピーでは不十分な場合があります。Dockerが管理するボリュームは、ホストの特定のパスに格納されています。正確なパスは、
docker volume inspect <volume_name>
で確認できます。
推奨される手順:
docker-compose down
で元のコンテナを停止します。docker volume inspect <volume_name>
で、元のボリュームのパス(Source
フィールド)を確認します。- そのパスから、新しいディレクトリ
dify2/docker/volumes2/db/data
などにデータをコピーします。
まとめ
この手順によって、複数のDifyインスタンスをホストマシン上で共存させることが可能になります。
docker-compose.yml
: 環境変数を使用することで、設定ファイルを汎用化します。.env
ファイル: 各インスタンス固有の設定(ボリューム名など)を管理します。
この構成により、将来的に3番目、4番目のコンテナを追加する際も、同じ手順で効率的に環境を複製できます。
サーバのレスポンス確認と対処方法
サーバーの負荷状況の確認
サーバーの負荷状況を確認するには、以下のコマンドが役立ちます。これにより、CPU、メモリ、ディスクI/O、ネットワークなどの使用状況を把握できます。
1. docker stats
最も重要なコマンドです。稼働中の各Dockerコンテナがどれだけのリソースを消費しているかをリアルタイムで表示します。
Bash
sudo docker stats
このコマンドの出力で、CPU %
、MEM %
、NET I/O
、BLOCK I/O
の列に注目してください。特にCPU %
とMEM %
が継続的に高い状態(例: 80%以上)であれば、リソースが不足している可能性があります。
2. htop (または top)
ホストサーバー全体のプロセスとリソース使用状況をリアルタイムで表示します。
Bash
sudo htop
htop
はtop
よりも見やすく、CPUコアごとの使用状況やメモリの全体像を把握するのに適しています。サーバー全体の負荷が高い場合、どのプロセス(Docker、システムプロセスなど)が原因かを特定できます。
3. df -h
ディスクの空き容量を確認します。ディスク容量が不足すると、多くのアプリケーションのパフォーマンスが低下します。
Bash
df -h
Difyのナレッジベースやデータベースが大量のデータを保存している場合、ディスク容量を圧迫している可能性があります。
考えられる原因と対策
上記のコマンドでリソース不足が確認された場合、以下の対策を検討してください。
1. メモリ不足
Difyの複数のインスタンスがそれぞれデータベースやRedisを動かしている場合、メモリを大量に消費します。
- 対策:
docker-compose.yml
で各サービスにdeploy: resources: limits:
を設定し、メモリ使用量を制限します。または、サーバーのメモリを増設します。
2. CPUの過負荷
LLMの推論処理やファイル処理は、CPUを大量に使用します。
- 対策: サーバーのCPUコア数を増やす、または
docker-compose
でCPUリソースを制限します。
3. 複数のコンテナ
Dockerは軽量ですが、複数のDifyインスタンスを同時に動かすと、それぞれが独立したPostgreSQL、Redis、Nginxなどを起動するため、単一のサーバーではリソースが急速に枯渇する可能性があります。
docker stats
コマンドで、どのコンテナが最も多くのリソースを消費しているかを確認することが、問題解決の第一歩となります。
レスポンス対策
原因の可能性
plugin_daemon
が干渉する主な原因として、以下の点が考えられます。
- 共有リソースの競合: 両方の
plugin_daemon
コンテナが、ホストマシンの共有リソース(CPUやメモリ)を奪い合っている可能性があります。Dockerコンテナはホストのリソースを共有するため、一方のコンテナが処理を行うと、もう一方のコンテナのパフォーマンスに影響を与えることがあります。 - 通信の干渉: もし
plugin_daemon
が内部ネットワークで特定のポートやサービス(例:Redisやデータベース)にアクセスしている場合、2つのインスタンスが同じサービスに過剰なリクエストを送信することで、リソースのボトルネックが発生し、CPU使用率が上昇する可能性があります。 - ファイルシステムの干渉: 稀なケースですが、もし
plugin_daemon
が同じホストディレクトリを共有している場合、ファイルのロックやI/O競合が発生し、パフォーマンスが低下することがあります。
解決策
個々のインスタンスのplugin_daemon
が独立して動作するように、以下の対策を検討してください。
- リソース制限の設定:
docker-compose.yml
ファイルで、各plugin_daemon
コンテナのCPUとメモリの使用量を制限します。これにより、一方のコンテナが過剰にリソースを消費するのを防ぎ、他のコンテナに影響を与えないようにできます。YAML
services: plugin_daemon: ... deploy: resources: limits: cpus: '0.5' # CPUコアを0.5に制限 memory: 1024M # メモリを1GBに制限
- ネットワークの分離: 各
docker-compose.yml
ファイルに個別のネットワークを定義し、コンテナ同士が互いに通信できないようにします。これにより、不要な干渉を防ぎます。YAML
# docker-compose.yml (aidify環境) services: ... networks: default: name: aidify_network
difyai
環境のdocker-compose.yml
でも同様に、異なるネットワーク名を指定してください。 - 個別のデータボリュームの使用: すでに
volumes
のパスを分けていると思いますが、各コンテナが完全に独立したデータにアクセスしていることを再確認してください。
これらの対策により、各インスタンスが互いに干渉することなく、安定して動作するようになります。
コメント