Difyでデータベースに接続し、データを自動的にMySQLにインポートしたいのですが、接続パラメータには問題ないにもかかわらず、常にエラーが発生します:
データインポート結果
データベースのインポートに失敗しました: (pymysql.err.OperationalError) (2003, “Can’t connect to MySQL server on ‘111.8.160.135’ (\[Errno 101\] Network is unreachable)”)
(Background on this error at: https://sqlalche.me/e/20/e3q8)
DifyはDockerにデプロイされており、ローカルでPythonコードを実行してMySQLに接続し、データインポートをテストすると成功するのですが、このエラーを解決できません。解決策を教えてください。
エラーメッセージ自体を見ると:
(pymysql.err.OperationalError) (2003, “Can’t connect to MySQL server on ‘111.8.160.135’ ([Errno 101] Network is unreachable)”)
これはアカウントやパスワードのようなパラメータエラーではなく、ネットワークにまったく接続できないというエラーです。Difyが動作しているDockerコンテナ内でのみ発生し、ホストマシンで直接Pythonを実行すると接続できることから、コンテナネットワークが111.8.160.135:3306に到達できないと判断できます。
以下のいくつかの方向で一つずつ確認してください(特に1、2番に注目してください):
1. ホストマシンはこのMySQLにアクセスできますか?
まずホストマシンで確認してください:
# ホストマシンで実行
telnet 111.8.160.135 3306
# または
nc -vz 111.8.160.135 3306
- ここで接続できない場合:データベースが配置されているネットワーク/ファイアウォールの問題であり、DifyやDockerとは関係ありません。
- ホストマシンが接続できる場合:ステップ2に進んでください(Dockerコンテナのネットワーク問題です)。
2. Difyのコンテナ内でネットワークをテストする
Dify APIを実行しているコンテナを見つけます。通常、名前は dify-api または dify-server のようになっています。コンテナに入ってテストします:
docker ps # apiが配置されているコンテナIDまたは名前を見つける
docker exec -it <api_container_name_or_id> bash # または sh
# コンテナ内部で実行:
apt-get update && apt-get install -y telnet netcat-openbsd || apk add --no-cache busybox-extras
telnet 111.8.160.135 3306
# または
nc -vz 111.8.160.135 3306
- コンテナ内でも同様に接続できない場合(タイムアウト/Network is unreachable)、それはDockerコンテナから外部MySQLへのルーティング/ファイアウォールの問題であると断定できます。
- よくある原因:
- 会社/サーバールームのファイアウォールがホストマシンのIPアドレスからのアクセスのみを許可し、Dockerブリッジネットワークからのアクセスを許可していない。
- クラウドプロバイダーのセキュリティグループが特定の送信元IPのみを許可しており、DockerのNAT後の出口IPがホワイトリストに含まれていない。
- ホストマシンで
firewalld / iptables ルールが有効になっており、Dockerネットワークインターフェースの外部アクセスを制限している。
解決策(例):
- MySQLサーバー側/ファイアウォール/セキュリティグループで、ホストマシンの出口IPが属するネットワークセグメントまたはDockerブリッジネットワークセグメントからのアクセスを許可する。
- または、DockerがNAT出口を使用しており、実際にはホストマシンのIPが出力されていることを確認し(ほとんどの場合がこれです)、MySQL側でこのIPがホワイトリストに登録されていることを確認する。
- 内部ネットワークの特殊な環境(例えば、1台の踏み台サーバーからのアクセスのみを許可している場合)であれば、DifyをDBに直接接続できる同じマシンで実行するか、ネットワークプロキシ/内部ネットワークトンネリングを設定することを検討してください。
3. コードノードで使用しているMySQLアドレスを確認する
現在のエラーは次のとおりです:
Can't connect to MySQL server on '111.8.160.135'
さらにいくつか確認してください:
- ポートは3306ですか:
- MySQLがデフォルトの3306ではない場合、コードで
port=xxxx を明示的に指定する必要があります。
- MySQLが同じホストマシン上にある場合、
localhost または 127.0.0.1 を使用しないでください:
- コンテナにとって
127.0.0.1 はコンテナ自身であり、ホストマシンではありません。
- MySQLがホストマシン上にある場合、
127.0.0.1 ではなく、Dockerブリッジから見えるホストマシンのIP(例:ホストマシンの内部IP、または同じローカルネットワーク内のホストマシンのIP)を使用する必要があります。
- MySQLが別のDockerコンテナで実行されており、Difyと同じ
docker-compose.yml にある場合、推奨される設定は次のとおりです:services:
dify-api:
# ...
depends_on:
- mysql
networks:
- dify_net
mysql:
image: mysql:8
# ...
networks:
- dify_net
networks:
dify_net:
driver: bridge
その場合、コードノードの hostには mysql(サービス名) を記述し、ポートは3306とします。
4. Dockerコンテナのネットワークモードを確認する
docker-compose.yml でDify APIコンテナに特別な設定があるか確認してください:
network_mode: host
その場合、コンテナはホストマシンネットワークを直接使用します。このとき:
5. こちらでさらに判断するために補足していただきたい情報
上記の手順でも解決しない場合は、以下の重要な情報を貼り付けてください:
docker-compose.yml 内のDify関連サービス(特にapi)の設定。
- MySQLのデプロイ場所:
- 公開ネットワークのマシンですか?クラウドRDSですか?それとも同じホストマシン上のDockerコンテナですか?
- ホストマシン上とDifyコンテナ内でそれぞれ
nc -vz 111.8.160.135 3306 を実行した結果のスクリーンショットまたは出力。
まとめ
- エラーはネットワークに到達できないことを示しており、アカウント、データベース名、パスワードの問題ではありません。
- ホストマシンのPythonからは接続できるのに、Docker内のコードからはできない場合、根本原因はほぼ間違いなくDockerコンテナからMySQLへのネットワーク/ファイアウォール/ルーティングの制限です。
- まずコンテナ内で直接
telnet / nc を使って接続をテストし、到達可能かどうかに応じてセキュリティグループ、ファイアウォール、またはdocker-composeのネットワーク設定を調整してください。
まずステップ1と2をテストし、その結果と一部の設定を貼り付けていただければ、具体的な変更方法を一緒に確認できます。
1\. ホストマシンはこのMySQLにアクセスできますか?
ホストマシンで接続に成功しました。
2\. Difyのコンテナでネットワークをテストする
dify-apiコンテナへの接続も成功しました
私のMySQLは、同じホストマシン上のDockerコンテナにデプロイされています。
サンドボックスには追加の制限があります。詳細はサンドボックスのFAQをご覧ください。