広告

AIのアシストで、どうにかUbuntu上の Docker EngineでDifyをサーバー化できた。

AI

前回までで、「Docker Engine」の設定は完了しています。
今回は、「Docker」で「Dify」を起動させサーバー化が目的です。
実現するにあたって、かなりAIに助けてもらったので、そのやり取りも紹介しています。

Difyをクローン化

gitの確認

difyをクローン化するのに、「git」を利用するので、「git」のインストール状況を確認します。
windows ターミナルを開き、wsl を起動し、「git -v」で状況を確認します。

Gitでdifyをクローン化する

「git clone ・・」でクローン化を実行すると、カレントディレクト下「dify」ディレクトリへソースコードがクローン化されます。
windowsターミナルで、「wsl」を実行し、ubuntu環境へ入ると、デフォルトでは、winndowsユーザーのディレクトリへセットされた状態で起動します。
好みの問題だと思いますが、この場所へ「dify」環境を作成してもいいと思いますが、筆者はubuntuのユーザーホームディレクトリ下に作成しようと思います。
wsl、ubuntuプロンプトで、「cd」を実行すると、ユーザーのホームディレクトリへ移動します。
その場所で「git clone・・」すると、そのディレクトリ直下に「dify」さらにその下に「docker」ディレクトリが作成されています。
「ls」コマンドで確認できます。
「dify/docker」ディレクトリへ「cd」コマンドで移動しておきます。
「pwd」コマンドで、現在のディレクトリが確認できます。

Difyコンテナ起動

「git clone」を実行したディレクトリに、「dify/docker」ディレクトリが作成されています。
その中に「.env.example」のサンプル環境変数ファイルが作成されています。
通常ファイルは「ls」コマンドで確認できますが。「.」で始まるファイルは表示されません。
その場合「ls -la」コマンドを実行すると、表示されます。
コピーは「cp <オリジナルファイル名> <複写ファイル名>」で複写できます。
「.env.example」ファイルを、正式な環境変数「.env」としてコピーし、「docker compose」コマンドで、コンテナを起動させます。

docker compose upでエラー発生!AIに聞いてみる。

上記は正常な例ですが、古いPCをテストマシンとして利用した時、「docker compose up」で下記エラーがでた事がありました。

この時もgeminiに聞いてみたところ、「docker logs docker-db-1」でログを確認してくれとの事なので、ログを直接貼り付けると、

Ai
Ai

ログを見る限り、データベースの初期化自体は正常に完了しています (PostgreSQL init process complete; ready for start up.)。 その後の起動プロセスも進んでいますが、2025-04-29 00:02:07.998 UTC [557] FATAL: the database system is starting up という致命的なエラーが出力されています。

このエラーは、PostgreSQLサーバーが起動してリカバリなどの内部処理を行っている最中に、外部からの接続要求(この場合はおそらくDockerのヘルスチェックや、依存するDifyコンテナからの初期接続試行)があった場合に発生することがあります。

つまり、データベースサーバー自体は最終的に database system is ready to accept connections の状態になりますが、Dockerのヘルスチェックがサーバーの準備が完全に整う前に接続を試み、上記の FATAL エラーを受け取ってしまい、それが原因でコンテナが unhealthy と判定されている可能性が高いです。

解決策:

Dockerのヘルスチェック設定を調整し、データベースが完全に起動して接続可能になるまで、チェックを待つように設定を変更するのが最も有効な対策です。

データベースサービス (db または postgresql) の healthcheck 設定を見つける:
services のセクションにある、データベースコンテナに対応するサービス定義(通常は db という名前)を探します。その中に healthcheck というブロックがあるはずです。

YAML
services:

db: # ... その他の設定 ...
healthcheck: # ここに設定があります
  ・
test: ["CMD-EXEC", "pg_isready -U <db_user> -d <db_name>"] # 例
interval: 10s
timeout: 5s
retries: 5
start_period: 30s # <-- この値を調整します

docker-compose.yml を開く: Difyを起動するために使用している docker-compose.yml ファイルをテキストエディタで開きます。

じじぃ
じじぃ

docker-compose.yamlを確認した所、「start_period:」の設定がありません。

Ai
Ai

start_period が指定されていない場合、コンテナが起動を開始すると同時にヘルスチェックが始まります。今回のデータベースのログで見たように、起動直後の一時的な準備期間中に接続を試みると FATAL: the database system is starting up のようなエラーが発生することがあります。

interval: 1s と非常に短い間隔でチェックが実行されるため、データベースが完全に準備できる前に多くのチェックが走ってしまい、すぐにリトライ回数(retries: 60)を使い果たして unhealthy と判定されてしまう可能性が高いです。

解決策:

start_period を追加し、必要に応じて interval も調整しましょう。

  1. healthcheck 設定に start_period を追加する: データベースが起動して準備ができるまでの猶予期間として、start_period を設定します。
    例えば 30s または 60s (30秒または60秒) を指定します。
    YAML
    services:
    db: # ... その他の設定 ...

    healthcheck:
    test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ]
    interval: 5s # 例: 毎秒ではなく5秒ごとにチェックに緩和
    timeout: 3s
    retries: 10 # 例: リトライ回数を調整 (intervalを長くすればretriesは少なくても良い)
    start_period: 60s # <- この行を追加 (例: 60秒待つ)

    ポイント: start_period の間は、ヘルスチェックが失敗してもコンテナは starting 状態のままとなり、unhealthy とは判定されません。start_period が経過した後に初めて、ヘルスチェックの失敗が unhealthy の判定に使われます。
  2. interval も少し長めにすることをお勧めします: interval: 1s は開発時などに素早く確認したい場合には便利ですが、本番に近い環境や安定性を重視する場合は 5s10s に設定することが一般的です。これにより、データベースへの不要な負荷も軽減されます。
  3. docker-compose.yml を保存する。
  4. Docker Compose を再起動する: 変更を反映させるために、コンテナを再作成して起動します。

アドバイス通りに、編集して再度「docker compose up -d」を実行すると、正常になりました。
いやぁ~、AIさまさま、ですね~
おそらく、ネット検索では、解決できなかったと思います。
ただし、古いPCだったのが、一番の原因かもしれません。
5年ほど前のPCでは、このエラーはでなかったので、レアなケースかもしれませんが、AIの利用例として紹介しました。

Dify起動

初期画面

「docker compose up」が正常に終了すると、Webブラウザで「http://localhost/install」へアクセスすると「dify」の初期設定が開きます

Difyの動作と試用

とりあえず、起動しました。
以前このサイトでも説明していますが、簡単なチャットボットを作成し試してみます。
LLMモデルはオンラインの「gemini」を登録し、動作を確認できました。
オンラインであれば、「LM Studio」や「Ollama」など、ローカルLLMを利用するアプリは必要ないので、すぐに確認できます。

Difyを自動起動

Difyを動作させるには、Dockerが起動していなくてはいけません。
それには、WSL上で、ubuntuも起動している必要があります。
手動でやる場合、

・windowsターミナル起動
・wslコマンドで、ubuntuターミナル起動
・ubuntuターミナルでカレントディレクトリを、Difyのクローンディレクトリに移動
・「docker compose up -d」 コマンド実行

このような手順が必要ですが、問題なのは、ターミナルを閉じるとdockerも終了してしまうことです
Difyを使うには、dockerが起動していなくてはいけません。
windowsアプリの「docker desktop」であれば、標準で自動起動設定だったと思いますし、起動後もシステムトレイのアイコンで起動が確認できます。右ボタンで状態確認や終了も簡単です。
ubuntu経由の場合には、GUIでの確認ができないので、ここが面倒なところですね~。
自動起動方法をいろいろ調べると、windowsバッチファイルを作成し、スタートアップフォルダに登録する事で、windows起動時に、自動起動できそうです。
ただ、
「コマンドプロンプト ⇒ ubuntuターミナル ⇒ docker」
のタスクが必要で、ターミナルは開いた状態にしておく必要があります。
このようなバッチファイルを作りたいですが、どんなコードにすればいいのか・・?
うまいコードを考え付かなかったので、difyの試しもかねて起動しているチャットボットで設定しているgeminiに考えてもらいました。

すごいです。
ほとんど実際の起動には影響がない「REM」や「echo」文がほとんどですが、
「REM」文を使っての説明文や、「echo」での実行中のメッセージにも手抜きがないですね!
このコードをコピーしてエディターで、「start_dify.bat」というファイルで保存しました。
バッチファイルの単独実行では問題ありませんでした。
後はこのファイルのショートカットを、スタートアップフォルダへコピーするだけです。

・上記の作成したバッチファイルを、適当は場所へ保存します
 私は、ユーザーフォルダ「C:\Users\「ユーザー」」へ保存しました。
・次に、このファイルのショートカットを作成します。
・このショートカットを「スタートアップフォルダ」へ保存します。
 スタートアップフォルダは、エクスプローラーのアドレスバーへ「shell:startup」と入力すると開くことができます。

特に必須ではないですが、ターミナルは起動状態にさせるので邪魔になる場合、作成したショートカットファイルを、マウス右ボタンで「プロパティ」を開きます。
「プロパティ」の「ショートカット」タブの「実行時の大きさ」を「最小化」に設定すると、起動時にタスクバーに最小化状態で起動できます。

これで、再起動すると、自動起動したターミナルはタスクバーへ最小化状態ですが、環境によっては起動途中の場合があるので、すぐに使用したい場合には、一度開いてDockerの状態を確認したほうがいいと思います。
正常に起動できると、Webブラウザのアドレスバーに「http://localhost/install」でdifyが起動できます。
場合によっては、「http://localhost/signin」にリダイレクトされる場合もあります

この画面が開くと、ローカルPCでは、Difyを利用する事ができますが、今回はサーバーとして利用したいので、LAN上の別のPCからのアクセスも必要です。

Difyをサーバー化して、他のPCからもアクセスさせる

同じLAN上であっても、「localhost」では、他のPCではアクセスできません。
前回後半で少し話題にしましたが、「windowsホスト」「WSL(ubuntu)」「Docker」と複雑な通信環境なので面倒です。

DifyPCのIPアドレス調査

IPアドレスは、windowsターミナルでは「ipconfig」コマンド
WSLターミナルでは、「ip addr」で確認できます。
この情報を、Aiに添付して聞いてみました。

Ai
Ai

詳細な情報ありがとうございます!ipconfig と ip a の結果から状況がより明確になりました。
原因の特定
・Windows ホスト:
 あなたの Windows PC の Wi-Fi アダプターには 192.168.0.94 という IP アドレスが割り当てられています。
 これはご自宅などの LAN 内の IP アドレスです。
・WSL (Ubuntu):
 Windows Subsystem for Linux (WSL) 環境内の Ubuntu には、eth0 インターフェースに 172.31.226.6 という IP アドレスが割り当てられています。
 これは WSL が使用する仮想ネットワーク内の IP アドレスです。

Ai
Ai

WSL2 環境で Docker コンテナを動かしている場合、Windows ホストからそのコンテナ内のサービスにアクセスするには、通常以下のいずれかのアドレスを使用します。
1.localhost:
 Windows ホストのブラウザで http://localhost/chat/…と入力する。
 WSL2 は localhost 経由でのポートフォワーディングをサポートしています。
 (これが最も一般的な方法です)
2.WSL の IP アドレス: http://172.31.226.6/chat/…
 (今回アクセスできている方法)

・http://192.168.0.94/chat/… でアクセスできないのは、WSL2 と Docker のネットワークアーキテクチャ上、自然なことです。
サービスが Windows ホストの物理的な IP アドレスに直接公開されているわけではないためです。
・もし、LAN 内の他の PC (例: 192.168.0.100) からもこの Dify 環境にアクセスしたい場合は、追加の設定が必要になる可能性があります:

1.Windows ファイアウォールの設定: Windows のファイアウォールで、外部からのポート 80 (または Dify が使用しているポート) への着信接続を許可する必要があります。
2.ポートフォワーディング (状況による): WSL2 のネットワーク設定によっては、Windows ホストの 192.168.0.94 のポート 80 へのアクセスを、WSL の 172.31.226.6 のポート 80 へ転送する設定が必要になる場合があります。
これは 「netsh interface portproxy」 コマンドなどで設定できますが、まずは localhost や WSL の IP でアクセスできることを確認するのが先決です。

要約:
・Windows ホストからアクセスする場合: http://localhost/chat/… または http://172.31.226.6/chat/… を使用してください。
・http://192.168.0.94/chat/… でアクセスできないのは仕様であり、問題ではありません。

Windowsのアドレスからは、アクセスできない。

じじぃ
じじぃ

http://localhost や http://172.31.226.6 からはアクセスできています。
今回は、LAN上の別のPCからhttp://192.168.0.94 にアクセスしたいため、自分PCで試したら、アクセスできませんでした

Ai
Ai

なるほど、LAN上の他のPCからアクセスできるようにしたい、ということですね。承知いたしました。

ご自身のPC (192.168.0.94) から http://192.168.0.94/chat/... にアクセスできなかったのは、まさにその設定がまだされていないためです。Windowsホストのネットワーク(192.168.0.x) と WSL内部のネットワーク (172.31.x.x) は分離されており、外部(LANを含む)から直接WSL内のサービスにアクセスするには、「ポートフォワーディング(ポート転送)」という設定が必要になります。

設定手順

以下の手順を管理者権限で実行してください。

  1. Difyが使用しているポートを確認 (重要):
    • まず、DifyがWSL内でどのポート番号で待ち受けているか確認します。HTTPなので通常は 80番 ですが、Dockerの設定によっては異なるポート(例: 3000番など)がホスト(WSL)に公開されている場合があります。
    • Docker Composeを使っている場合は docker-compose.yml ファイルの ports: セクションを確認してください。例えば ports: - "80:80"ports: - "3000:80" のようになっています。左側の数字がWSL側で公開されているポート番号です。
    • docker ps コマンドを実行しても確認できます。PORTS 列に 0.0.0.0:80->80/tcp0.0.0.0:3000->80/tcp のように表示されます。0.0.0.0: の後の数字がWSL側で公開されているポート番号です。
    • 以降の説明では、Difyがポート 80 を使用していると仮定します。もし異なるポート(例: 3000)だった場合は、コマンド内の 80 をその番号に読み替えてください。
  2. Windows ファイアウォールでポートを開放:
    • LAN内の他のPCからのアクセスを許可するために、WindowsのファイアウォールでDifyが使用するポート(ここでは80番)を開ける必要があります。
    • 管理者としてPowerShellを開き、以下のコマンドを実行します。
      powershell New-NetFirewallRule -DisplayName "Allow Dify Access from LAN" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
      (もしコマンドプロンプトを使いたい場合は、管理者として開き netsh advfirewall firewall add rule name="Allow Dify Access from LAN" dir=in action=allow protocol=TCP localport=80 を実行)
  3. ポートフォワーディングの設定:
    • Windowsホスト (192.168.0.94) のポート80に来た通信を、WSL (172.31.226.6) のポート80に転送するように設定します。
    • 管理者としてPowerShell(またはコマンドプロンプト)を開き、以下のコマンドを実行します。 powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6
      • listenport=80: Windows側で外部からの接続を待ち受けるポート番号。
      • listenaddress=0.0.0.0: Windowsの全てのIPアドレス(192.168.0.94 を含む)で待ち受ける設定。特定のIP (192.168.0.94) だけを指定することも可能です。
      • connectport=80: 転送先のWSL内でDifyが待ち受けているポート番号。
      • connectaddress=172.31.226.6: 転送先のWSLのIPアドレス。
  4. 動作確認:
    • 設定後、まずご自身のPCのブラウザから http://192.168.0.94/chat/84aj9r6azPSYjXt8 にアクセスできるか試してください。 (ポートが80以外の場合は http://192.168.0.94:ポート番号/chat/... のように指定)
    • アクセスできれば、LAN内の他のPCからも同じアドレス (http://192.168.0.94/chat/...) でアクセスできるはずです。

注意点:

  • WSLのIPアドレスの変動: WSLを再起動すると、WSLのIPアドレス (172.31.226.6) が変わる可能性があります。もしアクセスできなくなった場合は、ip a コマンドでWSLの新しいIPアドレスを確認し、手順3のポートフォワーディング設定を一度削除して再作成する必要があります。
    • 削除コマンド: netsh interface portproxy delete v4tov4 listenport=80 listenaddress=0.0.0.0
    • 再作成コマンド: (新しい connectaddress を指定して再度実行)
  • 管理者権限: ファイアウォールとポートフォワーディングの設定には管理者権限が必要です。
  • ポート番号: Difyが使用しているポート番号を正確に確認し、コマンド内の 80 を適宜修正してください。

この手順で、LAN内の他のPCからアクセスできるようになるはずです。試してみてください。

docker ps コマンドで実行中のコンテナーを提出

じじぃ
じじぃ

docker ps では下記になっています。
$ docker ps
・・

Ai
Ai

docker ps の出力結果、ありがとうございます。

コンテナ docker-nginx-1PORTS 列にご注目ください。

PORTS
0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp

これは、以下のことを意味しています。

  • 0.0.0.0:80->80/tcp: WSLホスト(172.31.226.6 など)の ポート 80 (HTTP) へのTCP接続を、docker-nginx-1 コンテナ内部のポート 80 に転送する。
  • [::]:80->80/tcp: 上記のIPv6版。
  • 0.0.0.0:443->443/tcp: WSLホストの ポート 443 (HTTPS) へのTCP接続を、docker-nginx-1 コンテナ内部のポート 443 に転送する。
  • [::]:443->443/tcp: 上記のIPv6版。

docker-web-1 コンテナ自体は内部的にポート 3000 を使っていますが、外部(WSLホスト)からのアクセスは docker-nginx-1 コンテナがポート 80 (HTTP) と 443 (HTTPS) で受け付けています。Nginx がリバースプロキシとして動作し、リクエストを docker-web-1docker-api-1 などに振り分けている構成です。

結論

あなたが LAN 上の他の PC からアクセスしたい HTTP のポート番号は 80 です。

したがって、先ほどのポートフォワーディング設定のコマンドは、ポート番号 80 を使って実行してください。

  1. ファイアウォール開放 (ポート 80): New-NetFirewallRule -DisplayName "Allow Dify Access from LAN (HTTP)" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
  2. ポートフォワーディング設定 (ポート 80):
    powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6

これで、 http://192.168.0.94 (ポート80は省略可能) でアクセスできるはずです。

もし将来的にHTTPS (https://192.168.0.94) でアクセスしたい場合は、同様にポート 443 用のファイアウォールルールとポートフォワーディング設定を追加する必要があります。

ファイヤーウォールとポートフォワーディング設定

ファイアウォールを開放し、ポートフォワーディング設定をしろ、のアドバイスです。
教わったコードを実行してみます。

1.ファイアウォール開放 (ポート 80):

コントロールパネル→システムとセキュリティ→windows Defender ファイアウォール→詳細設定
受信の規則で
コマンドで指定したAllow Dify Access from LAN(HTTP)が設定されているのが、確認できます。
コマンドではなく、この画面で、GUI設定する事もできます。

2.ポートフォワーディング設定 (ポート 80):

管理者権限のPowerShell の、「netsh」コマンドで設定します。

「netsh interface portproxy show v4tov4」で確認できます。

アクセスできた~

これで無事に「http://192.168.0.94/instal」でアクセスできました。
LAN上の別のPCからも、アクセス確認できました。
おそらく、ネット検索では、ここまで的確なアドバイスを見つけるのは至難の業だと思います。
ちょっと前までは、言語生成AIをうまく使うには、プロンプトが重要だと言われていましたが、最近の言語生成AIはかなり言語の理解力が向上していると感じます。
上記のじじぃの質問でもわかりますが、ほとんど「プロンプト」など意識していません。
とにかくわからない事やPCからの出力を、自分の言葉で質問しているだけです。
それでもかなり的確な回答をくれます。
たまには、間違った回答もありますが、それでエラーが発生した場合、そのエラーやログをそのまま突っ込めば、新たな回答をくれます。
すごい時代になりました。

DifyにLLMを設定して、カスタムチャット環境を構築

やっとDifyサーバーが起動できました。

次に、このDifyにLLMモデルを設定することで、チャットボットをはじめカスタムLLMアプリを開発する事ができるようになります。
左図の例では、
一番上の「Gemini」はオンラインで公開されているLLMです。
二番目は、「LM Studio」でダウンロードしたローカルLLMです。
三番目は、「Ollama」で読み込んでいるローカルLLMです。
このように、「Dify」ではオンライン、ローカルあまり意識せず、使用するLLMを自由にカスタマイズできます。

DifyにLLMの設定方法

ネット上でも、多くの情報があると思いますが、このサイトでも以前の記事で紹介しています。

オンラインLLMの登録

LM Studio モデルの登録

Ollama モデルの登録

あとがき

Windowsアプリ「Docker Desktop」を使わず、「Ubuntu」にインストールした「Docker Engine」で「Dify」をサーバー化する方法を紹介しました。
「Docker Desktop」はWindows環境向けのツールであり、構築の手間は比較的少ないですが、Ubuntuサーバー上で動作させる際は、仮想化環境の設定やネットワーク通信の複雑さが生じるため、トラブルシューティングがやや難しくなります。
今回は、AIのアシストにより、Difyサーバーを構築することができました。
設定プロセスだけでなく、AIを活用した実践例として、このやり取りもご参考にしていただければ幸いです。

コメント

タイトルとURLをコピーしました