<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AIとのやり取り | じじぃの引出し</title>
	<atom:link href="https://www.kazuban.com/blog/tag/ai%E3%81%A8%E3%81%AE%E3%82%84%E3%82%8A%E5%8F%96%E3%82%8A/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.kazuban.com/blog</link>
	<description>なにかしら、皆さんの参考になれば幸いです！</description>
	<lastBuildDate>Wed, 28 Jan 2026 07:15:54 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.kazuban.com/blog/wp-content/uploads/2020/05/cropped-ICON-1-32x32.png</url>
	<title>AIとのやり取り | じじぃの引出し</title>
	<link>https://www.kazuban.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。</title>
		<link>https://www.kazuban.com/blog/fusion-python-api/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 20:01:00 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Fusion360]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[AIとのやり取り]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11250</guid>

					<description><![CDATA[数年前、Fusion360のPython APIに少しだけ触れたことがあります。当時はPython自体が初めてで、構文の違いに戸惑いました。C言語に慣れていた私には、インデントでブロックを作る点や、変数・関数に型の宣言が [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>数年前、Fusion360のPython APIに少しだけ触れたことがあります。<br>当時はPython自体が初めてで、構文の違いに戸惑いました。<br>C言語に慣れていた私には、インデントでブロックを作る点や、変数・関数に型の宣言が不要な点など、なかなか馴染めませんでした。<br>さらに、Fusion独自のオブジェクトや関数の使い方を調べる必要があり、作業のハードルは思った以上でした。<br><a href="https://qiita.com/reisyu/items/84aa97117439e4962bbf">こちらのブログ記事</a>や<a href="https://kantoku.hatenablog.com/archive/category/Fusion360API?page=20">「Kantoku」さんのサイト</a>を参考にしながら少しだけ進めてみたのですが、残念ながら長続きせず中断してしまいました。</p>



<p>ところが昨年、AI（生成AI）が大きく注目されるようになり、「これを使ってみるか？」と再び興味がわきました。<br>試しにFusion向けのコードをAIに聞いてみると、実際に動作するスクリプトを提案してくれて、少しやる気が復活…<br>しかしそれも一時的で、またもや放置状態に。</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/" title="話題の『生成Ai』に、Fusion360のPythonスクリプトをきいてみた" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-160x90.jpg 160w, https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-120x68.jpg 120w, https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-320x180.jpg 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">話題の『生成Ai』に、Fusion360のPythonスクリプトをきいてみた</div><div class="blogcard-snippet internal-blogcard-snippet">最近『生成Ai』を触り始めました。今までの、検索に比べても、非常に便利です。できる事の幅が広すぎて、ついていけませんが、プログラムコードも出力してくれるようです。いままで手を付けていなかった、Fusion360のPythonスクリプトを質問してみました。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2024.01.27</div></div></div></div></a>
</div></figure>



<p>そして今回！<br>AIもさらに進化してきた今こそ、もう一度挑戦してみようと思い立ちました。<br>本記事では、Fusion360 Python API に再び取り組み始めた記録と、コーディングへのAIの活用事例をレポートしています。<br>例題として、Fusion APIの基本ライブラリを作成しましたので、利用できそうであれば、利用していただければ幸いです。</p>



<p>なお、より高度なスクリプトや実践的な例に興味がある方は、<a href="https://kantoku.hatenablog.com/archive/category/Fusion360API?page=20">「Kantoku」さんのサイト</a>に素晴らしい資料が公開されていますので、ぜひチェックしてみてください。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">今回の目標：スケッチ関連の基本ライブラリを作る</a></li><li><a href="#toc2" tabindex="0">Aiの実力を試してみる</a><ol><li><a href="#toc3" tabindex="0">fusionのpython API で直線を引くコード</a><ol><li><a href="#toc4" tabindex="0">ローカルLLM</a></li><li><a href="#toc5" tabindex="0">オンラインLLM</a></li></ol></li><li><a href="#toc6" tabindex="0">コンポネントやスケッチのアクティブな状態を把握</a><ol><li><a href="#toc7" tabindex="0">現状がスケッチモードかどうかの判定</a></li></ol></li></ol></li><li><a href="#toc8" tabindex="0">python特有な構文</a></li><li><a href="#toc9" tabindex="0">Fusion スクリプトをライブラリ化する</a><ol><li><a href="#toc10" tabindex="0">ライブラリの登録場所とpythonでの実装方法</a></li><li><a href="#toc11" tabindex="0">実行スクリプトと同じレベルのスクリプトをインポートするには？</a></li></ol></li><li><a href="#toc12" tabindex="0">ライブラリ利用方法</a></li><li><a href="#toc13" tabindex="0">ライブラリを利用して、X,Y,Zの座標軸にセンターラインを描く</a><ol><ol><li><a href="#toc14" tabindex="0">CenterLine.py</a></li><li><a href="#toc15" tabindex="0">lib_util.py</a></li><li><a href="#toc16" tabindex="0">lib_2d.py</a></li></ol></li></ol></li><li><a href="#toc17" tabindex="0">注意点</a></li><li><a href="#toc18" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">今回の目標：スケッチ関連の基本ライブラリを作る</span></h2>



<p>Python言語は、ほとんど初心者ですが、ネット情報やAiを参考にコードをコピペするだけでは、なかなか覚えられないと思っています。<br>そこで、基本的なコードをライブラリ化する事で、少しは理解も深まるかと思い、まずはスケッチ周りの基本コードをライブラリ化してみようと思います</p>



<h2 class="wp-block-heading"><span id="toc2">Aiの実力を試してみる</span></h2>



<p>さっそく、何種類かのLLMに質問してみました。</p>



<h3 class="wp-block-heading"><span id="toc3">fusionのpython API で直線を引くコード</span></h3>



<h4 class="wp-block-heading"><span id="toc4">ローカルLLM</span></h4>



<p>ローカルの場合、私の環境では、レスポンス的に30bぐらいが実用できる限界です。<br>そこで、「gemma-3-27b」「qwen3-32b」で試してみます</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>「fusionのpython API で直線を引くコードをだして」</p>
</blockquote>



<p>最初に、「import adsk.core, adsk.fusion, traceback」など<span class="marker-under">Fusion特有のパッケージをインポート</span>しするコードを出してくれるので、なかなかいいな！と思っていましたが、実際にFusionで実行してみても正常動作しませんでした。<br>特に、CAD画面上にメッセージを出力する場合、「ui.messageBox」を利用しますが、一般的なpythonの「print」文を使ったりしています。<br>また、私の環境で30bクラスのLLMでは、<span class="marker-under-blue">回答に５分以上</span>かかりました。<br>文章をまとめたり、翻訳したりの場合では、8bクラスでもいい回答をもらえますが、Fusion API のPython場合はちょっとマイナーなのかもしれません<br>参考にはなると思いますが、<span class="marker-under-red">私</span><span class="marker-under-red">の</span><span class="marker-under-red">環境</span><span class="marker-under-red">では</span><span class="marker-under-red">ちょっとレスポンスが悪いです</span>。</p>



<h4 class="wp-block-heading"><span id="toc5">オンラインLLM</span></h4>



<p>次に、オンラインの「chatGPT」と「gemini」で試してみました。<br><span class="marker-under">「chatGPT」も「gemini」も、正常に動作しました</span>。<br>ただし、ログインしないと、会話履歴や共有できないので、ログインしたほうがいいと思います。<br>制限がある場合がありますが、そこそこ無料利用できます。<br>やはり、さすがです。回答レスポンスも早いです。<br>今回の質問では、<a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/#toc6">一年前に、出してくれたコードとほとんど同じコードをだしてくれました。</a><br>一年前は、「bard(gemini)」のコードは、正常動作しないコードでしたが、現在の「gemini」は問題ないコードを出してくれます。<br>個人的は、ローカルLLMを使いたい気持ちがあるのですが、開発作業では、やはりレスポンスは重要なので、今後の学習はオンラインLLMを利用しようと思います。<br>まずは「Gemini 2.5Flash」を利用してみて、いい回答が出なかった場合には、「chatGPT」や「Gemini 2.5Pro」を使おうと思います</p>



<h3 class="wp-block-heading"><span id="toc6">コンポネントやスケッチのアクティブな状態を把握</span></h3>



<p><a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/#toc6">上記の直線を描くサンプルコード</a>では、ルートコンポネントに新しいスケッチを作成し、そのスケッチに直線を引いています。<br>もう少し、実践的な動作にしたいです。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<ul class="wp-block-list">
<li>スケッチモードであれば、そのスケッチに・・</li>



<li>スケッチモードでない場合、ルートにこだわらず、アクティブなコンポネントに新しいスケッチを作成しそのスケッチに・・</li>
</ul>
</blockquote>



<p>これを実現させるには、まず<span class="marker-under">現状のアクティヴな状態を把握する</span>必要があります<br>アクティブなコンポーネントを見つける関数はすぐ見つかりましたが、<span class="marker-under-red">スケッチのモード判定方法はなかなか見つか</span><span class="marker-under-red">らず</span>Aiのお陰でどうにかなりそうです。<br>こういった汎用的だけど苦労した処理を、ライブラリ化しておくと、後々便利だと思います</p>



<h4 class="wp-block-heading"><span id="toc7">現状がスケッチモードかどうかの判定</span></h4>



<p>何度かgemini に聞いてみたところ、「<strong>activeEditObject」</strong>「<strong>activeEnvironment</strong>」を使用する方法があるとの回答をもらいました。<br>ただし、Ai としては、<span class="marker-under-red">「<strong>activeEditObject</strong>」を推奨</span>するとの事でした</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-461f21f5f0623461ac160a0a7c456f79"><code>import adsk.core
import adsk.fusion

def is_sketch_mode_active():
    """
    現在スケッチモード（いずれかのスケッチが編集中）かどうかを判定します。

    Returns:
        bool: スケッチモードであれば <strong>True</strong>、そうでなければ <strong>False</strong>。
        adsk.fusion.Sketch: アクティブなスケッチオブジェクト（スケッチモードの場合）。
    """
    try:
        app = adsk.core.Application.get()
        
        # 現在編集中のオブジェクトを取得
        active_object = app.activeEditObject

        # 編集中のオブジェクトがスケッチ（Sketch）であるかを確認
        if active_object and <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-yellow-color">isinstance(active_object, adsk.fusion.Sketch):</mark>
            return <strong>True</strong>, active_object
        else:
            return <strong>False</strong>, None

    except:
        return False, None

# --- 実行例 ---
def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface

        is_active, active_sketch = is_sketch_mode_active()

        if is_active:
            ui.messageBox(f'はい、現在スケッチモードです。\nアクティブなスケッチ: {active_sketch.name}')
        else:
            ui.messageBox('いいえ、現在スケッチモードではありません。')

    except:
        if ui:
            ui.messageBox('エラーが発生しました。')</code></pre>



<p>判定で、「<span class="marker-under-red">isinstance()</span>」関数を使っています。<br>これは、自力では、なかなか探せなかったと思います。恐るべし、Aiです。</p>



<h2 class="wp-block-heading"><span id="toc8">python特有な構文</span></h2>



<p>Aiが出してくれた、サンプルコードを見ると、C言語とは違う書き方が結構出てきます<br>例えば</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>return<strong> True , active_object</strong></p>
</blockquote>



<p>のように、複数変数を返す事ができて、取り出しは、下記のように「,」で区切って利用できるのですね</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>is_active , active_sketch</strong> = is_sketch_mode_active()</p>
</blockquote>



<p>C++言語では、最近ではstd::tupleが利用できるみたいですが、それを知らない私は、classを使ったりしていますが、こちらのほうが、面倒ないですね。<br>「if文」も「<strong>三項演算子</strong>」と呼ばれている構文が結構使われていました。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6adc7d18a4400a93e3504e1accf22d81"><code>design = get_design()
return <strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-yellow-color">design.activeComponent if design else None</mark></strong></code></pre>



<p>C言語にも「三項演算子」はありますが、if文のほうが、分かりやすいかも・・<br>配列系も、多種類があるようで、Aiが出してくれたサンプルでも結構多用しています</p>



<pre class="wp-block-code"><code>plane = plane.lower()
planes_map = {
    "xy": component.xYConstructionPlane,
    "xz": component.xZConstructionPlane,
    "yz": component.yZConstructionPlane
}   
base_plane = planes_map.get(plane)</code></pre>



<p>この「<strong>.get(plane)</strong>」はなんだ？<br>と思いましたが、これもAiに聞くと、すぐに説明してくれました。<br><strong>planes_map[plane]</strong>でもアクセスできるようですが、<span class="marker-under-red"><strong>get()</strong>を使うと<strong>plane</strong>が存在しない場合安全に</span>デフォルト値（<code><strong>None</strong></code>または指定した値）を返してくれるようです。<br>本当にすぐに教えてくれるので、私のような独学の場合、参考書などをめくるよりも、言語の理解は数段速くなるでしょうね～</p>



<h2 class="wp-block-heading"><span id="toc9">Fusion スクリプトをライブラリ化する</span></h2>



<p>Fusion では、「ユーティリティ」⇒「アドイン」⇒「スクリプトとアドイン」⇒「+」で新規にスクリプトを作成できます</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="754" height="572" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript.png" alt="" class="wp-image-11300" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript.png 754w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript-500x379.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript-300x228.png 300w" sizes="(max-width: 754px) 100vw, 754px" /></figure>



<p>このダイアログの「<strong>フォルダの場所</strong>」に「<strong>名前</strong>」に入力のフォルダを作成し、その中に「<strong>名前.py</strong>」で実行スクリプトが作成されます。<br>「フォルダの場所」はデフォルトでは、かなり深いので、私は「D:\Fusion360\Scripts」のようにシンプルな場所に変更しています。<br>また、この場所は、<span class="marker-under">「基本設定」⇒「一般」⇒「API」</span>でデフォルトを変更できます<br>ただし、ここでの設定箇所に<span class="marker-under-red">「Scripts」は自動作成</span>されるので、<span class="marker-under-red">「D:\Fusion360」</span>になります</p>



<p>Fusionスクリプトは、Fusionオブジェクトモデルを介して、利用したいオブジェクトのコマンドを記述します。<br>したがって、スクリプトを作成するには、各オブジェクトの情報が必要となり、かなり複雑です。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="677" height="437" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2.png" alt="" class="wp-image-11332" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2.png 677w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2-500x323.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2-300x194.png 300w" sizes="(max-width: 677px) 100vw, 677px" /></figure>



<p><br>今回は、Pythonの学習も兼ねて、Fusionのスケッチ関連オブジェクトをカプセル化したライブラリを作成したいと思います。</p>



<h3 class="wp-block-heading"><span id="toc10">ライブラリの登録場所とpythonでの実装方法</span></h3>



<p>ライブラリフォルダは、Fusionが自動作成する、「Scripts」内の自作スクリプトと同じレベルに登録したいと思います</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>D:\Fusion360\Scripts<br>├── 新規スクリプト<br>├── CenterLine # 自作スクリプト<br>│ └── CenterLine.py # X,Y,Zの軸のセンターラインを作成する<br>│<br>├── library # 作成ライブラリ登録フォルダ<br>│ ├── <em>_init_</em>.py # 空ファイル（必要らしい）<br>│ ├── lib_util.py # Component &amp; Sketch 関連関数<br>│ └── lib_2d.py # 点や直線を作成（今後、円、円弧なども追加予定）<br></p>
</blockquote>



<p>私の環境では、このようなイメージです。<br>「library」フォルダ内に「lib_util.py」「lib_2d.py」スクリプトを作成<br>「lib_util.py」は、Component や sketch を提供する基本関数を記述します<br>「lib_2d.py」は、点や直線を扱う関数を作成しますが、<span class="marker-under">「<strong>lib_util.py</strong>」の関数も利用します</span><br>今回はこの二つのライブラリを利用して、 X,Y,Zの軸のセンターラインを作成する「CenterLine /CenterLine.py」スクリプトを作成します</p>



<h3 class="wp-block-heading"><span id="toc11">実行スクリプトと同じレベルのスクリプトをインポートするには？</span></h3>



<p>インポートするコードもわからないので、さっそくAiに聞いてみました<br>上記の構造をAiに渡して、実行スクリプト「CenterLine.py」から「lib_util.py」の関数を利用するコードを聞いてみました<br>この場合、正確なディレクトリ構造を取得する事が必要だと言うことで下記コードを教えてもらいました。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-99ee604cd6fe96d6d4cf1c7e56b1ef5c"><code>current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)</code></pre>



<p>この構成はよくライブラリや設定ファイルを<span class="marker-under">相対パスで読み込むときの定番のコード</span>のようです<br>もう少し、詳しく説明してもらいました。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>_file_：現在実行中のPythonスクリプトのファイルパス<br>os.path.abspath(__file__)：絶対パスに変換<br>os.path.dirname(…)：そのファイルが属するディレクトリを取得<br><br>D:/Fusion360/Scripts/<br>├── library/<br>│ └── __init__.py # モジュールの初期化用<br>│ └── lib_util.py<br>│ └── lib_2d.py<br>├── CenterLine/<br>│ └── CenterLine.py ← 実行スクリプト</p>



<p>__file__ → &#8220;./CenterLine/CenterLine.py&#8221;<br>abspath(__file__) → &#8220;D:/Fusion360/Scripts/library/CenterLine/CenterLine.py&#8221;<br>current_dir → &#8220;D:/Fusion360/Scripts/library/CenterLine&#8221;<br>script_dir → &#8220;D:/Fusion360/Scripts/library&#8221;</p>
</blockquote>



<p>このコードで、ライブラリのディレクトリを取り出し、<br>「sys.path.append(script_dir)」でpythonが内部でモジュール検索時に、指定ディレクトリを追加するの意味のようです<br>この設定後に、「from library import lib_util」コードで「library」ディレクトリ内の「lib_util.py」内の関数を使用できるようになります<br>具体的には、下記になります</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-8e2a343bbae44e922fe021104cc52319"><code>import os, sys

current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from <strong>library </strong>import <strong>lib_util</strong></code></pre>



<p>これで、新規作成したスクリプトに、このコードを追加すると、「lib_util」内の関数が使えます<br>さらに「lib_2d.py」ライブラリも、「lib_util.py」の関数も利用しますが、こちらは、<span class="marker-under">「lib_util.py」と同じディレクトリ内</span>なので、「script_dir = os.path.dirname(current_dir)」のコードは<span class="marker-under-red">不要</span>になりますね</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6f026c1782e213cab59b1b4af17510bf"><code>import os, sys
current_dir = os.path.dirname(os.path.abspath(__file__))
<s><strong>#</strong> script_dir = os.path.dirname(current_dir)</s>
sys.path.append(current_dir)
import lib_util
</code></pre>



<p>実際には結構時間がかかったのですが、これで、やっとライブラリが使えるようになりました。<br>本当、Ai様様です。<br>Aiの進歩で、コーディングの勉強は不要だとの意見もありますが、やっぱりコードの意味の理解は必要だと思います。<br>たぶん、Aiもそう思っているのでしょう！詳しいコメントを日本語で追記してくれます。<br>「あなたの言葉でコメントつけるから、覚えてね！」と言ってる気がします。<br>Ai利用でプログラミングの学習速度は、以前よりも圧倒的に速くなると思います</p>



<h2 class="wp-block-heading"><span id="toc12">ライブラリ利用方法</span></h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>./Scripts/<br>├── 新規スクリプト/ # &lt;&#8212;&#8212;&#8211; Fusion ダイアログで作成<br>│ └── 新規スクリプト.py<br>├── library/ #&lt;&#8212;&#8212;&#8212; Scripts/ 直下に作成<br>│ └── __init__.py # &lt;&#8212;&#8211; 空ファイル追加作成、モジュールの初期化用<br>│ └── lib_util.py # &lt;&#8212;&#8212;- ライブラリファイル<br>│ └── lib_2d.py # &lt;&#8212;&#8212;- ライブラリファイル<br>└── CenterLine/ # &lt;&#8212;&#8212;- 自作スクリプト用<br>│ └── CenterLine.py # &lt;&#8212;&#8212;- 自作スクリプトファイル<br>└─────── </p>
</blockquote>



<p>イメージ的には、このようになります。<br>Fusionで「スクリプトまたはアドイン作成」を実行すると、設定ダイアログが表示され、設定した「フォルダの場所」へ設定した名前のフォルダが自動作成され、さらにその中に、設定した名前.py の実行ファイルが作成されます。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="558" height="224" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins.png" alt="" class="wp-image-11358" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins.png 558w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins-500x201.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins-300x120.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></figure>



<p>今回紹介のライブラリは、Fusionで設定した「フォルダの場所」の直下に「library」の名前でフォルダを作成し、さらに「library」の直下に、「__init__.py」「lib_util.py」「lib_2d.py」を作成します<br>「__init__.py」は、空ファイルですが、Aiが言うには、ライブラリを利用する際必要みたいです。<br>「lib_util.py」「lib_2d.py」も一旦空ファイルを作っておいて、下記コードをコピペして保存します</p>



<h2 class="wp-block-heading"><span id="toc13">ライブラリを利用して、X,Y,Zの座標軸にセンターラインを描く</span></h2>



<p>まずは、Fusion 「スクリプトとアドイン」で、新規スクリプトを作成します<br>ここでは「CenterLine」という名前にしました。<br>これで、「./Scripts」ディレクトリ内に、「CenterLine/CenterLine.py」が作成されています。<br>CenterLine.pyファイルの内容を、下記コードで上書きして保存します</p>



<h4 class="wp-block-heading"><span id="toc14">CenterLine.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-669094fb191368c9558d98db4e1a51f8"><code>"""This file acts as the main module for this script."""

import traceback
import adsk.core
import adsk.fusion
# import adsk.cam

import os, sys, importlib
#library import
current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from library import lib_util,lib_2d

def run(context):
    try:
        lib_2d.draw_center_line(100,100,100)
 
    except:
        lib_util.disp_message('Failed:\n{}'.format(traceback.format_exc()))
</code></pre>



<p>下記が、ライブラリ用スクリプトファイルです</p>



<h4 class="wp-block-heading"><span id="toc15">lib_util.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-e25baaca05132da85fad5d0dc35a19a0"><code>import adsk.core, adsk.fusion, adsk.cam, traceback
from typing import Tuple, Optional

#このライブラリは
#Fusionが作成するスクリプトと同じディレクトリに置かれる事を想定している
#使用する場合には、下記コードにより読み込みパスを追加する
"""
import os, sys, importlib
current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from library import lib_util
"""
# ---------------------
## Get Fusion object
# ---------------------
def get_app():
    return adsk.core.Application.get()
def get_design():
    app = get_app() 
    return adsk.fusion.Design.cast(app.activeProduct)
def get_ui():
    app = get_app() 
    return app.userInterface

# ---------------------
## メッセージ表示
# ---------------------
def disp_message(msg: str):
    """ユーザーにメッセージボックスを表示"""
    ui = get_ui()
    if ui:
        ui.messageBox(msg)

# ---------------------
## Component &amp; Sketch Functions
# ---------------------
# /////////////////////////////////////////////////////////////
def get_root_component() -&gt; Optional&#91;adsk.fusion.Component]:
    """ルートコンポーネントを返す"""
    design = get_design()
    return design.rootComponent if design else None

# /////////////////////////////////////////////////////////////
def get_active_component() -&gt; Optional&#91;adsk.fusion.Component]:
    """現在アクティブなコンポーネントを返す"""
    design = get_design()
    return design.activeComponent if design else None

# /////////////////////////////////////////////////////////////
def create_new_component(name: str = 'New_Component') -&gt; Optional&#91;adsk.fusion.Component]:
    """新しいコンポーネントを作成し、アクティブなコンポーネントの配下に追加"""
    component = get_active_component()
    if not component:
        component = get_root_component()
    
    if not component:
        disp_message('コンポーネントが見つかりません。デザインがアクティブか確認してください。')
        return None
    
    try:
        occurrences = component.occurrences
        new_occurrence = occurrences.addNewComponent(adsk.core.Matrix3D.create())
        new_component = new_occurrence.component
        new_component.name = name
        return new_component
    except Exception:
        disp_message(f'新しいコンポーネントの作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def get_parent_sketch(obj: any) -&gt; Optional&#91;adsk.fusion.Sketch]:
    """指定されたオブジェクトの親スケッチを取得"""
    return obj.parentSketch if hasattr(obj, 'parentSketch') else None

# /////////////////////////////////////////////////////////////
def create_new_sketch(name: str = 'New_Sketch', plane: str = 'xy') -&gt; Optional&#91;adsk.fusion.Sketch]:
    """指定された平面に新しいスケッチを作成"""
    component = get_active_component()
    if not component:
        component = get_root_component()
    
    if not component:
        disp_message('スケッチを作成するコンポーネントが見つかりません。')
        return None
    
    plane = plane.lower()
    planes_map = {
        "xy": component.xYConstructionPlane,
        "xz": component.xZConstructionPlane,
        "yz": component.yZConstructionPlane
    }
    
    base_plane = planes_map.get(plane)
    if not base_plane:
        disp_message(f"サポートされていない平面: '{plane}' 'xy', 'xz', 'yz' のいずれかを選択してください。")
        return None
        
    try:
        sketches = component.sketches
        sketch = sketches.add(base_plane)
        sketch.name = name
        return sketch
    except Exception:
        disp_message(f'新しいスケッチの作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def is_sketch_mode_active() -&gt; Tuple&#91;bool, Optional&#91;adsk.fusion.Sketch]]:
    """現在スケッチモードがアクティブであるかを確認し、スケッチオブジェクトを返す"""
    app = get_app()
    active_object = app.activeEditObject
    # is_instance() を使うことで、より安全に型チェックを行う
    if isinstance(active_object, adsk.fusion.Sketch):
        return True, active_object
    else:
        return False, None

# /////////////////////////////////////////////////////////////
def get_sketch() -&gt; Optional&#91;adsk.fusion.Sketch]:
    """アクティブなスケッチを返す、アクティブでない場合は新しいスケッチを作成"""
    is_active, sketch = is_sketch_mode_active()
    if not is_active:
        sketch = create_new_sketch()
    return sketch
</code></pre>



<h4 class="wp-block-heading"><span id="toc16">lib_2d.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-be5884e5b0d369633af538947edd4e83"><code>import adsk.core, adsk.fusion, adsk.cam, traceback
from typing import Tuple, Optional

# 利用するlib_utilは、このライブラリと同じディレクトリ
import os, sys, importlib
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
import lib_util

# ---------------------
## カスタム、点基本クラス
# ---------------------
# /////////////////////////////////////////////////////////////
class kPoint:
    """3D空間の点を表す基本クラス"""
    def __init__(self, x: float, y: float, z: float = 0.0):
        self.x = x
        self.y = y
        self.z = z

# ---------------------
## カスタム、スケッチ点クラス
# ---------------------
# /////////////////////////////////////////////////////////////
class kSketchPoint(kPoint):
    """Fusion 360 のスケッチ点として使用される座標を、単位とスケッチ平面に応じて変換するクラス"""
    def __init__(self, x: float = 0.0, y: float = 0.0, z: float = 0.0, sketch: Optional&#91;adsk.fusion.Sketch] = None, unit: str = "mm"):
        unit = unit.lower()
        # 単位変換係数を辞書で管理
        scale_factors = {"mm": 0.1, "cm": 1.0, "m": 10.0}
        scale = scale_factors.get(unit, 1.0) # 存在しない単位は1.0 (cm) を使用

        if not sketch:
            sketch = lib_util.get_sketch() # スケッチが指定されていなければ、アクティブなスケッチを取得

        # スケッチ平面に応じて座標系を調整 (XZ平面はY軸が下向き)
        # 参照平面が'XZ'の場合は、y座標を反転させる
        # これはFusion 360の座標系の癖に対応
        direction_y = -1.0 if sketch and sketch.referencePlane.name == "XZ" else 1.0
        
        # 単位と座標系による方向を調整
        converted_x = x * scale
        converted_y = y * scale * direction_y
        converted_z = z * scale
        
        super().__init__(converted_x, converted_y, converted_z)
        self.sketch = sketch
        self.unit = unit
        
# ---------------------
## Sketch Geometry Creation Functions
# ---------------------
# /////////////////////////////////////////////////////////////
def is_equal_sketch_points(sp1: adsk.fusion.SketchPoint, sp2: adsk.fusion.SketchPoint, tolerance: float = 0.0001) -&gt; bool:
    """2つのスケッチ点が指定された許容差内で同じ位置にあるかどうかを判断"""
    # ジオメトリオブジェクトの距離を比較
    distance = sp1.geometry.distanceTo(sp2.geometry)
    return distance &lt; tolerance

# /////////////////////////////////////////////////////////////
def create_sketch_point(x: float = 0, y: float = 0, z: float = 0, sketch: Optional&#91;adsk.fusion.Sketch] = None) -&gt; Optional&#91;adsk.fusion.SketchPoint]:
    """指定された座標にスケッチ点を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()
    
    if not sketch:
        lib_util.disp_message('スケッチがアクティブでないか、新しいスケッチの作成に失敗しました。')
        return None
        
    try:
        # kSketchPoint を使用して単位と平面を考慮した座標を取得
        converted_point = kSketchPoint(x, y, z, sketch)
        # adsk.core.Point3D オブジェクトを作成
        point3d = adsk.core.Point3D.create(converted_point.x, converted_point.y, converted_point.z)
        # スケッチに点を追加
        sketchPoint = sketch.sketchPoints.add(point3d)
        return sketchPoint
    except Exception:
        lib_util.disp_message(f'スケッチ点の作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_sketchpoints(sp1: adsk.fusion.SketchPoint, sp2: adsk.fusion.SketchPoint, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """2つの既存のスケッチ点から直線を作成"""
    # 同じスケッチに属しているかチェック
    if lib_util.get_parent_sketch(sp1) != lib_util.get_parent_sketch(sp2):
        lib_util.disp_message('2つの点は異なるスケッチに属しています。')
        return None
        
    # 2つの点が同じ位置にあるかチェック
    if is_equal_sketch_points(sp1, sp2):
        lib_util.disp_message('2つの点が同じ位置にあります。直線を作成できません。')
        return None
        
    sketch = lib_util.get_parent_sketch(sp1)
    if not sketch:
        lib_util.disp_message('親スケッチが見つかりません。')
        return None
        
    try:
        line = sketch.sketchCurves.sketchLines.addByTwoPoints(sp1, sp2)
        line.isConstruction = construction
        line.isFixed = fixed
        return line
    except Exception:
        lib_util.disp_message(f'直線（スケッチ点から）の作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_coordinate(x1: float, y1: float, z1: float, x2: float, y2: float, z2: float, sketch: Optional&#91;adsk.fusion.Sketch] = None, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """座標から直接、スケッチ直線を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()

    if not sketch:
        return None

    # ヘルパー関数を利用して点を先に作成
    p1 = create_sketch_point(x1, y1, z1, sketch)
    p2 = create_sketch_point(x2, y2, z2, sketch)
    
    if p1 and p2:
        return create_line_from_sketchpoints(p1, p2, construction, fixed)
    else:
        lib_util.disp_message('直線を作成するための点の作成に失敗しました。')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_points(p1: kPoint, p2: kPoint, sketch: Optional&#91;adsk.fusion.Sketch] = None, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """カスタム `kPoint` オブジェクトからスケッチ直線を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()
    
    if not sketch:
        return None
        
    return create_line_from_coordinate(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, sketch, construction, fixed)

# /////////////////////////////////////////////////////////////
def draw_center_line(widthX=100,widthY=100,widthZ=100):
    """センターライン作成"""
    widthX = 100 if widthX == 0 else widthX
    widthY = 100 if widthY == 0 else widthY
    widthZ = 100 if widthZ == 0 else widthZ
    wx=widthX/2
    wy=widthY/2
    wz=widthZ/2
    sketch = lib_util.get_sketch()
    xp1 = kPoint(-wx,0)
    xp2 = kPoint(wx,0)
    yp1 = kPoint(0,-wy)
    yp2 = kPoint(0,wy)
    zp1 = kPoint(0,0,-wz)
    zp2 = kPoint(0,0,wz)
    create_line_from_points(xp1,xp2,sketch,True,True) #X Axis
    create_line_from_points(yp1,yp2,sketch,True,True) #Y Axis
    create_line_from_points(zp1,zp2,sketch,True,True) #Z Axis
</code></pre>



<h2 class="wp-block-heading"><span id="toc17">注意点</span></h2>



<p>実は、まだ解決できていない注意点があります<br>通常のライブラリ使用では問題ないと思いますが、Fusionでライブラリを利用したスクリプトを実行後、<span class="marker-under-red">ライブラリ内スクリプトを編集しても、編集内容が反映されません。</span><br>Aiに聞いてみると、Fusionの仕様でキャッシュが優先されているとの事です<br>キャッシュクリアのコードも教えてもらいましたが、現状では反映されません。<br><span class="marker-under-red">ライブラリの編集を反映させるには、Fusionを再起動</span>させるとキャッシュがクリアされ反映されます<br>ライブラリを試行錯誤している場合でも、ちょっと面倒です。<br>いい方法は、ないのかなぁ～？？</p>



<h2 class="wp-block-heading"><span id="toc18">まとめ</span></h2>



<p>pythonはド素人なので、勉強もかねて、Ai にコーディングを教えてもらいながら、FusionのComponentやsketch、直線作成などの関数をライブラリ化してみました。<br>Fusionオブジェクトモデルは、広範囲で奥が深いので、探すのも大変です。<br>よく使いそうな関数を、まとめたので、少しは取り組みやすくなるのではないか？と思っています。<br>今後も進化させようと思っていますが、Aiがなかったら、ここまで完成できなかったと思います。<br>ここで紹介しているコードも、一旦自分なりに作成したスクリプトを、Aiに張り付けて、添削してもらったコードを再編集したものです。<br>関数名やコメントの書き方なども、pythonの慣習を教えてもらい参考にしています</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AIに教えてもらいながら、どうにかUbuntu上の Docker EngineでDifyをサーバー化できた。</title>
		<link>https://www.kazuban.com/blog/ubuntu-dockerengine-dify/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Mon, 05 May 2025 01:17:22 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux (CentOS、Rocky、Ubuntu)]]></category>
		<category><![CDATA[AIとのやり取り]]></category>
		<category><![CDATA[Dify]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[ubuntu24]]></category>
		<category><![CDATA[wsl]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11029</guid>

					<description><![CDATA[前回までで、「Docker Engine」の設定は完了しています。今回は、「Docker」で「Dify」を起動させサーバー化が目的です。実現するにあたって、かなりAIに助けてもらったので、そのやり取りも紹介しています。  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><a href="https://www.kazuban.com/blog/wsl-ubuntu-dockerengine/">前回までで、「Docker Engine」の設定は完了しています。</a><br>今回は、「Docker」で「Dify」を起動させサーバー化が目的です。<br>実現するにあたって、かなりAIに助けてもらったので、そのやり取りも紹介しています。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Difyをクローン化</a><ol><li><a href="#toc2" tabindex="0">gitの確認</a></li><li><a href="#toc3" tabindex="0">Gitでdifyをクローン化する</a></li></ol></li><li><a href="#toc4" tabindex="0">Difyコンテナ起動</a><ol><li><a href="#toc5" tabindex="0">docker compose upでエラー発生！AIに聞いてみる。</a></li></ol></li><li><a href="#toc6" tabindex="0">Dify起動</a><ol><li><a href="#toc7" tabindex="0">初期画面</a></li><li><a href="#toc8" tabindex="0">Difyの動作と試用</a></li></ol></li><li><a href="#toc9" tabindex="0">Difyを自動起動</a></li><li><a href="#toc10" tabindex="0">Difyをサーバー化して、他のPCからもアクセスさせる</a><ol><li><a href="#toc11" tabindex="0">DifyPCのIPアドレス調査</a></li><li><a href="#toc12" tabindex="0">Windowsのアドレスからは、アクセスできない。</a></li><li><a href="#toc13" tabindex="0">docker ps コマンドで実行中のコンテナーを提出</a></li><li><a href="#toc14" tabindex="0">ファイヤーウォールとポートフォワーディング設定</a><ol><li><a href="#toc15" tabindex="0">１．ファイアウォール開放 (ポート 80):</a></li><li><a href="#toc16" tabindex="0">2．ポートフォワーディング設定 (ポート 80):</a></li><li><a href="#toc17" tabindex="0">アクセスできた～</a></li></ol></li></ol></li><li><a href="#toc18" tabindex="0">DifyにLLMを設定して、カスタムチャット環境を構築</a><ol><li><a href="#toc19" tabindex="0">DifyにLLMの設定方法</a><ol><li><a href="#toc20" tabindex="0">オンラインLLMの登録</a></li><li><a href="#toc21" tabindex="0">LM Studio モデルの登録</a></li><li><a href="#toc22" tabindex="0">Ollama　モデルの登録</a></li></ol></li></ol></li><li><a href="#toc23" tabindex="0">あとがき</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Difyをクローン化</span></h2>



<h3 class="wp-block-heading"><span id="toc2">gitの確認</span></h3>



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



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6c280a658549c20db340281f1ee6bbdb"><code>PS C:\Users\hogehoge2&gt; wsl

$ git -v
git version 2.43.0
インストールされていない場合には、インストール
$ sudo apt update
$ sudo apt install git</code></pre>



<h3 class="wp-block-heading"><span id="toc3">Gitでdifyをクローン化する</span></h3>



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



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-ad68e176018c4225a713c543c2c82523"><code>hogehoge2@hoge-PC:/mnt/c/Users/hogehoge2$
$ cd
$ git clone https://github.com/langgenius/dify.git
Cloning into 'dify'...
remote: Enumerating objects: 153846, done.
remote: Counting objects: 100% (536/536), done.
remote: Compressing objects: 100% (359/359), done.
remote: Total 153846 (delta 396), reused 178 (delta 177), pack-reused 153310 (from 3)
Receiving objects: 100% (153846/153846), 87.73 MiB | 5.07 MiB/s, done.
Resolving deltas: 100% (111131/111131), done.
$ ls
dify
$ cd dify/docker/
$ pwd
/home/hogehoge2/dify/docker</code></pre>



<h2 class="wp-block-heading"><span id="toc4">Difyコンテナ起動</span></h2>



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



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-69212d483fca0e2e7f0922dbf0b0ff47"><code>$ pwd
/home/hogehoge2/dify/docker
$ cp .env.example .env
$ docker compose up -d
&#91;+] Running 80/80    
✔ web Pulled             149.7s
✔ sandbox Pulled         221.1s
 ✔ ssrf_proxy Pulled      88.2s
 ✔ db Pulled             224.4s
 ✔ worker Pulled         402.2s
 ✔ plugin_daemon Pulled  404.6s
 ✔ nginx Pulled           36.4s
 ✔ weaviate Pulled       225.1s
 ✔ redis Pulled          221.2s
 ✔ api Pulled            402.2s
&#91;+] Running 12/12
 ✔ Network docker_default             Created    0.1s
 ✔ Network docker_ssrf_proxy_network  Created    0.0s
 ✔ Container docker-web-1             Started    3.7s
 ✔ Container docker-ssrf_proxy-1      Started    4.0s
 ✔ Container docker-sandbox-1         Started    3.7s
 ✔ Container docker-redis-1           Started    3.7s
 ✔ Container docker-weaviate-1        Started    3.7s
 ✔ Container docker-db-1              Healthy    10.7s
 ✔ Container docker-worker-1          Started    9.3s
 ✔ Container docker-plugin_daemon-1   Started    9.3s
 ✔ Container docker-api-1             Started    9.5s
 ✔ Container docker-nginx-1           Started    10.0s
</code></pre>



<h3 class="wp-block-heading"><span id="toc5">docker compose upでエラー発生！AIに聞いてみる。</span></h3>



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



<blockquote class="wp-block-quote has-vivid-red-color has-watery-red-background-color has-text-color has-background has-link-color wp-elements-663148c1df4e9167eb9abd3e83e97fcc is-layout-flow wp-block-quote-is-layout-flow">
<p>dependency failed to start: container docker-db-1 is unhealthy</p>
</blockquote>



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



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p>ログを見る限り、データベースの初期化自体は正常に完了しています (<code>PostgreSQL init process complete; ready for start up.</code>)。 その後の起動プロセスも進んでいますが、<strong><code>2025-04-29 00:02:07.998 UTC [557] FATAL: the database system is starting up</code></strong> という致命的なエラーが出力されています。</p>



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



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



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



<p><strong>データベースサービス (db または postgresql) の <code>healthcheck</code> 設定を見つける:</strong> <br><code>services</code> のセクションにある、データベースコンテナに対応するサービス定義（通常は <code>db</code> という名前）を探します。その中に <code>healthcheck</code> というブロックがあるはずです。<br><br><strong>YAML</strong><br><code>services: </code><br><br><code>db: # ... その他の設定 ...</code><br><code>  healthcheck: # ここに設定があります </code><br>　　・<br><code>    test: ["CMD-EXEC", "pg_isready -U &lt;db_user&gt; -d &lt;db_name&gt;"] # 例 </code><br><code>    interval: 10s </code><br><code>    timeout: 5s </code><br><code>    retries: 5 </code><br><code>    start_period: 30s # &lt;-- この値を調整します</code></p>



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



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#dddddd"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon has-background has-light-grey-background-color">
<p>docker-compose.yamlを確認した所、「<code>start_period:</code>」の設定がありません。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p><code>start_period</code> が指定されていない場合、コンテナが起動を開始すると同時にヘルスチェックが始まります。今回のデータベースのログで見たように、起動直後の一時的な準備期間中に接続を試みると <code>FATAL: the database system is starting up</code> のようなエラーが発生することがあります。</p>



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



<p><strong>解決策:</strong></p>



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



<ol class="wp-block-list">
<li><strong><code>healthcheck</code> 設定に <code>start_period</code> を追加する:</strong> データベースが起動して準備ができるまでの猶予期間として、<code>start_period</code> を設定します。<br>例えば <code>30s</code> または <code>60s</code> (30秒または60秒) を指定します。 <br><strong>YAML</strong><br><code>services: </code><br><code>db: # ... その他の設定 ... </code><br><br><code>  healthcheck: </code><br><code>    test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ] </code><br><code>    interval: 5s # 例: 毎秒ではなく5秒ごとにチェックに緩和 </code><br><code>    timeout: 3s </code><br><code>    retries: 10 # 例: リトライ回数を調整 (intervalを長くすればretriesは少なくても良い) </code><br><code>    start_period: 60s # &lt;- この行を追加 (例: 60秒待つ)</code> <br><br><strong>ポイント:</strong> <code>start_period</code> の間は、ヘルスチェックが失敗してもコンテナは <code>starting</code> 状態のままとなり、<code>unhealthy</code> とは判定されません。<code>start_period</code> が経過した後に初めて、ヘルスチェックの失敗が <code>unhealthy</code> の判定に使われます。</li>



<li><strong><code>interval</code> も少し長めにすることをお勧めします:</strong> <code>interval: 1s</code> は開発時などに素早く確認したい場合には便利ですが、本番に近い環境や安定性を重視する場合は <code>5s</code> や <code>10s</code> に設定することが一般的です。これにより、データベースへの不要な負荷も軽減されます。</li>



<li><strong><code>docker-compose.yml</code> を保存する。</strong></li>



<li><strong>Docker Compose を再起動する:</strong> 変更を反映させるために、コンテナを再作成して起動します。</li>
</ol>
</div></div>



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



<h2 class="wp-block-heading"><span id="toc6">Dify起動</span></h2>



<h3 class="wp-block-heading"><span id="toc7">初期画面</span></h3>



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



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="755" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-800x755.png" alt="" class="wp-image-11052" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-800x755.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-500x472.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-300x283.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-768x725.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost.png 1200w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h3 class="wp-block-heading"><span id="toc8">Difyの動作と試用</span></h3>



<p>とりあえず、起動しました。<br>以前このサイトでも説明していますが、<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc1">簡単なチャットボットを作成</a>し試してみます。<br>LLMモデルはオンラインの「gemini」を登録し、動作を確認できました。<br>オンラインであれば、「LM Studio」や「Ollama」など、ローカルLLMを利用するアプリは必要ないので、すぐに確認できます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="571" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-800x571.png" alt="" class="wp-image-11056" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-800x571.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-500x357.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-300x214.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-768x548.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try.png 1577w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h2 class="wp-block-heading"><span id="toc9">Difyを自動起動</span></h2>



<p><span class="marker-under">Difyを動作させるには、Dockerが起動していなくてはいけません。</span><br>それには、WSL上で、ubuntuも起動している必要があります。<br>手動でやる場合、</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>・windowsターミナル起動<br>・wslコマンドで、ubuntuターミナル起動<br>・ubuntuターミナルでカレントディレクトリを、Difyのクローンディレクトリに移動<br>・「docker compose up -d」 コマンド実行</p>
</blockquote>



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



<pre class="wp-block-code has-black-color has-watery-yellow-background-color has-text-color has-background has-link-color wp-elements-28b6e40086f38030cefb644c1904cdfc"><code>@echo off
title Starting Dify via WSL

echo Starting WSL and navigating to ~/dify/docker...
echo Running 'docker compose up -d'...
echo WSL window will remain open after commands.

REM WSLを起動し、bashシェル内でコマンドを実行します。
REM cd ~          : ホームディレクトリに移動 (念のため)
REM cd ./dify/docker : dify/docker ディレクトリに移動
REM docker compose up -d : docker compose をバックグラウンドで起動
REM exec bash     : 上記コマンド実行後、インタラクティブなbashシェルを開始して終了させない
wsl.exe -e bash -c "cd ~/dify/docker &amp;&amp; docker compose up -d &amp;&amp; echo '--- Dify containers started (or attempted to start) ---' &amp;&amp; exec bash"

echo WSL window launched. This batch window can be closed if desired.
REM pause REM Optionally uncomment this line to keep the batch window open until a key is pressed</code></pre>



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



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



<div class="wp-block-media-text is-stacked-on-mobile is-vertically-aligned-top"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="622" height="989" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder.png" alt="" class="wp-image-11070 size-full" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder.png 622w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder-500x795.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder-300x477.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></figure><div class="wp-block-media-text__content">
<p>特に必須ではないですが、ターミナルは起動状態にさせるので邪魔になる場合、作成したショートカットファイルを、マウス右ボタンで「プロパティ」を開きます。<br>「プロパティ」の「ショートカット」タブの<span class="marker-under">「実行時の大きさ」を「最小化」</span>に設定すると、起動時にタスクバーに最小化状態で起動できます。</p>
</div></div>



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



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="732" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-800x732.png" alt="" class="wp-image-11073" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-800x732.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-500x458.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-300x275.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-768x703.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin.png 875w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p>この画面が開くと、ローカルPCでは、Difyを利用する事ができますが、<span class="marker-under">今回はサーバーとして利用したい</span>ので、<span class="marker-under-red">LAN上の別のPCからのアクセスも必要</span>です。</p>



<h2 class="wp-block-heading"><span id="toc10">Difyをサーバー化して、他のPCからもアクセスさせる</span></h2>



<p>同じLAN上であっても、「localhost」では、他のPCではアクセスできません。<br><a href="https://www.kazuban.com/blog/wsl-ubuntu-dockerengine/#toc15">前回後半で少し話題にしました</a>が、「windowsホスト」「WSL(ubuntu)」「Docker」と複雑な通信環境なので面倒です。</p>



<h3 class="wp-block-heading"><span id="toc11">DifyPCのIPアドレス調査</span></h3>



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



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p>詳細な情報ありがとうございます！ipconfig と ip a の結果から状況がより明確になりました。<br>原因の特定<br>・Windows ホスト:<br>　あなたの Windows PC の Wi-Fi アダプターには 192.168.0.94 という IP アドレスが割り当てられています。<br>　これはご自宅などの LAN 内の IP アドレスです。<br>・WSL (Ubuntu):<br>　Windows Subsystem for Linux (WSL) 環境内の Ubuntu には、eth0 インターフェースに 172.31.226.6 という IP アドレスが割り当てられています。<br>　これは WSL が使用する仮想ネットワーク内の IP アドレスです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p>WSL2 環境で Docker コンテナを動かしている場合、Windows ホストからそのコンテナ内のサービスにアクセスするには、通常以下のいずれかのアドレスを使用します。<br>１．localhost: <br>　Windows ホストのブラウザで http://localhost/chat/&#8230;と入力する。<br>　WSL2 は localhost 経由でのポートフォワーディングをサポートしています。 <br>　（これが最も一般的な方法です）<br>２．WSL の IP アドレス: http://172.31.226.6/chat/&#8230;<br>　(今回アクセスできている方法)<br><br>・http://192.168.0.94/chat/&#8230; でアクセスできないのは、WSL2 と Docker のネットワークアーキテクチャ上、自然なことです。<br>サービスが Windows ホストの物理的な IP アドレスに直接公開されているわけではないためです。<br>・もし、LAN 内の他の PC (例: 192.168.0.100) からもこの Dify 環境にアクセスしたい場合は、追加の設定が必要になる可能性があります:<br><br>１．Windows ファイアウォールの設定: Windows のファイアウォールで、外部からのポート 80 (または Dify が使用しているポート) への着信接続を許可する必要があります。<br>２．ポートフォワーディング (状況による): WSL2 のネットワーク設定によっては、Windows ホストの 192.168.0.94 のポート 80 へのアクセスを、WSL の 172.31.226.6 のポート 80 へ転送する設定が必要になる場合があります。<br>これは 「netsh interface portproxy」 コマンドなどで設定できますが、まずは localhost や WSL の IP でアクセスできることを確認するのが先決です。<br><br>要約:<br>・Windows ホストからアクセスする場合: http://localhost/chat/… または http://172.31.226.6/chat/… を使用してください。<br>・http://192.168.0.94/chat/&#8230; でアクセスできないのは仕様であり、問題ではありません。<br></p>
</div></div>



<h3 class="wp-block-heading"><span id="toc12">Windowsのアドレスからは、アクセスできない。</span></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon">
<p>http://localhost や http://172.31.226.6 からはアクセスできています。<br>今回は、LAN上の別のPCからhttp://192.168.0.94 にアクセスしたいため、自分PCで試したら、アクセスできませんでした</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p>なるほど、LAN上の他のPCからアクセスできるようにしたい、ということですね。承知いたしました。</p>



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



<p><strong>設定手順</strong></p>



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



<ol class="wp-block-list">
<li><strong>Difyが使用しているポートを確認 (重要):</strong>
<ul class="wp-block-list">
<li>まず、DifyがWSL内でどのポート番号で待ち受けているか確認します。HTTPなので通常は <strong>80番</strong> ですが、Dockerの設定によっては異なるポート（例: 3000番など）がホスト(WSL)に公開されている場合があります。</li>



<li>Docker Composeを使っている場合は <code>docker-compose.yml</code> ファイルの <code>ports:</code> セクションを確認してください。例えば <code>ports: - "80:80"</code> や <code>ports: - "3000:80"</code> のようになっています。左側の数字がWSL側で公開されているポート番号です。</li>



<li><code>docker ps</code> コマンドを実行しても確認できます。<code>PORTS</code> 列に <code>0.0.0.0:80-&gt;80/tcp</code> や <code>0.0.0.0:3000-&gt;80/tcp</code> のように表示されます。<code>0.0.0.0:</code> の後の数字がWSL側で公開されているポート番号です。</li>



<li><strong>以降の説明では、Difyがポート <code>80</code> を使用していると仮定します。もし異なるポート（例: 3000）だった場合は、コマンド内の <code>80</code> をその番号に読み替えてください。</strong></li>
</ul>
</li>



<li><strong>Windows ファイアウォールでポートを開放:</strong>
<ul class="wp-block-list">
<li>LAN内の他のPCからのアクセスを許可するために、WindowsのファイアウォールでDifyが使用するポート（ここでは80番）を開ける必要があります。</li>



<li><strong>管理者としてPowerShellを開き</strong>、以下のコマンドを実行します。<br><code>powershell New-NetFirewallRule -DisplayName "Allow Dify Access from LAN" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code><br><em>(もしコマンドプロンプトを使いたい場合は、管理者として開き <code>netsh advfirewall firewall add rule name="Allow Dify Access from LAN" dir=in action=allow protocol=TCP localport=80</code> を実行)</em></li>
</ul>
</li>



<li><strong>ポートフォワーディングの設定:</strong>
<ul class="wp-block-list">
<li>Windowsホスト (<code>192.168.0.94</code>) のポート80に来た通信を、WSL (<code>172.31.226.6</code>) のポート80に転送するように設定します。</li>



<li><strong>管理者としてPowerShell（またはコマンドプロンプト）を開き</strong>、以下のコマンドを実行します。 <code>powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code>
<ul class="wp-block-list">
<li><code>listenport=80</code>: Windows側で外部からの接続を待ち受けるポート番号。</li>



<li><code>listenaddress=0.0.0.0</code>: Windowsの全てのIPアドレス（<code>192.168.0.94</code> を含む）で待ち受ける設定。特定のIP (<code>192.168.0.94</code>) だけを指定することも可能です。</li>



<li><code>connectport=80</code>: 転送先のWSL内でDifyが待ち受けているポート番号。</li>



<li><code>connectaddress=172.31.226.6</code>: 転送先のWSLのIPアドレス。</li>
</ul>
</li>
</ul>
</li>



<li><strong>動作確認:</strong>
<ul class="wp-block-list">
<li>設定後、まずご自身のPCのブラウザから <code>http://192.168.0.94/chat/84aj9r6azPSYjXt8</code> にアクセスできるか試してください。 (ポートが80以外の場合は <code>http://192.168.0.94:ポート番号/chat/...</code> のように指定)</li>



<li>アクセスできれば、LAN内の他のPCからも同じアドレス (<code>http://192.168.0.94/chat/...</code>) でアクセスできるはずです。</li>
</ul>
</li>
</ol>



<p><strong>注意点:</strong></p>



<ul class="wp-block-list">
<li><strong>WSLのIPアドレスの変動:</strong> WSLを再起動すると、WSLのIPアドレス (<code>172.31.226.6</code>) が変わる可能性があります。もしアクセスできなくなった場合は、<code>ip a</code> コマンドでWSLの新しいIPアドレスを確認し、手順3のポートフォワーディング設定を一度削除して再作成する必要があります。
<ul class="wp-block-list">
<li>削除コマンド: <code>netsh interface portproxy delete v4tov4 listenport=80 listenaddress=0.0.0.0</code></li>



<li>再作成コマンド: (新しい <code>connectaddress</code> を指定して再度実行)</li>
</ul>
</li>



<li><strong>管理者権限:</strong> ファイアウォールとポートフォワーディングの設定には管理者権限が必要です。</li>



<li><strong>ポート番号:</strong> Difyが使用しているポート番号を正確に確認し、コマンド内の <code>80</code> を適宜修正してください。</li>
</ul>



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



<h3 class="wp-block-heading"><span id="toc13"><em>docker ps コマンドで実行中のコンテナーを提出</em></span></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon">
<p>docker ps では下記になっています。<br>$ docker ps<br>・・<br>・<br>・</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p><code>docker ps</code> の出力結果、ありがとうございます。</p>



<p>コンテナ <code>docker-nginx-1</code> の <code>PORTS</code> 列にご注目ください。</p>



<pre class="wp-block-code"><code>PORTS
0.0.0.0:80-&gt;80/tcp, &#91;::]:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp, &#91;::]:443-&gt;443/tcp</code></pre>



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



<ul class="wp-block-list">
<li><code>0.0.0.0:80-&gt;80/tcp</code>: WSLホスト（<code>172.31.226.6</code> など）の <strong>ポート 80</strong> (HTTP) へのTCP接続を、<code>docker-nginx-1</code> コンテナ内部のポート 80 に転送する。</li>



<li><code>[::]:80-&gt;80/tcp</code>: 上記のIPv6版。</li>



<li><code>0.0.0.0:443-&gt;443/tcp</code>: WSLホストの <strong>ポート 443</strong> (HTTPS) へのTCP接続を、<code>docker-nginx-1</code> コンテナ内部のポート 443 に転送する。</li>



<li><code>[::]:443-&gt;443/tcp</code>: 上記のIPv6版。</li>
</ul>



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



<p><strong>結論</strong></p>



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



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



<ol class="wp-block-list">
<li><strong>ファイアウォール開放 (ポート 80):</strong> <code>New-NetFirewallRule -DisplayName "Allow Dify Access from LAN (HTTP)" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code></li>



<li><strong>ポートフォワーディング設定 (ポート 80):</strong><br><code>powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code></li>
</ol>



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



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



<h3 class="wp-block-heading"><span id="toc14">ファイヤーウォールとポートフォワーディング設定</span></h3>



<p><span class="marker-under-red">ファイアウォールを開放</span>し、<span class="marker-under-red">ポートフォワーディング設定をしろ</span>、のアドバイスです。<br>教わったコードを実行してみます。</p>



<h4 class="wp-block-heading"><span id="toc15">１．ファイアウォール開放 (ポート 80):</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-2a1baa688c4d7f0081410424df4fffa6"><code>PowerShell
PS C:\Users\hoge2&gt;　New-NetFirewallRule -DisplayName "Allow Dify Access from LAN (HTTP)" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code></pre>



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



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="638" src="https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-800x638.png" alt="" class="wp-image-11155" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-800x638.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-500x399.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-300x239.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-768x612.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender.png 1200w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h4 class="wp-block-heading"><span id="toc16">2．ポートフォワーディング設定 (ポート 80):</span></h4>



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



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-407ff20f71ed0d5d65d19b8abe74f839"><code>PowerShell（管理者）
PS C:\Users\hoge2&gt; netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code></pre>



<p>「netsh interface portproxy show v4tov4」で確認できます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-3b28731fc08b3c287046ad304f896c2a"><code>PS C:\Users\hoge2&gt; netsh interface portproxy show v4tov4
ipv4 をリッスンする:         ipv4 に接続する:
Address         Port        Address         Port
--------------- ----------  --------------- ----------
0.0.0.0         80          172.31.226.6    80</code></pre>



<h4 class="wp-block-heading"><span id="toc17">アクセスできた～</span></h4>



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



<h2 class="wp-block-heading"><span id="toc18">DifyにLLMを設定して、カスタムチャット環境を構築</span></h2>



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



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="407" height="690" src="https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm.png" alt="" class="wp-image-11167 size-full" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm.png 407w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm-300x509.png 300w" sizes="(max-width: 407px) 100vw, 407px" /></figure><div class="wp-block-media-text__content">
<p>次に、このDifyにLLMモデルを設定することで、チャットボットをはじめカスタムLLMアプリを開発する事ができるようになります。<br>左図の例では、<br>一番上の「Gemini」はオンラインで公開されているLLMです。<br>二番目は、「LM Studio」でダウンロードしたローカルLLMです。<br>三番目は、「Ollama」で読み込んでいるローカルLLMです。<br>このように、「Dify」ではオンライン、ローカルあまり意識せず、使用するLLMを自由にカスタマイズできます。</p>
</div></div>



<h3 class="wp-block-heading"><span id="toc19">DifyにLLMの設定方法</span></h3>



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



<h4 class="wp-block-heading"><span id="toc20"><a href="https://www.kazuban.com/blog/dify-lmstudio/#toc3">オンラインLLMの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc3" title="ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。</div><div class="blogcard-snippet internal-blogcard-snippet">LM StudioとDifyをローカルで連携させたのでレポートします。記事を書いている時に、Dify設定にLM Studioのプラグインを発見したので、そちらの設定も追加してます。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.23</div></div></div></div></a>
</div></figure>



<h4 class="wp-block-heading"><span id="toc21"><a href="https://www.kazuban.com/blog/dify-lmstudio/#toc6">LM Studio モデルの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc6" title="ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。</div><div class="blogcard-snippet internal-blogcard-snippet">LM StudioとDifyをローカルで連携させたのでレポートします。記事を書いている時に、Dify設定にLM Studioのプラグインを発見したので、そちらの設定も追加してます。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.23</div></div></div></div></a>
</div></figure>



<h4 class="wp-block-heading"><span id="toc22"><a href="https://www.kazuban.com/blog/dify-ollama/#toc6">Ollama　モデルの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-ollama/#toc6" title="DifyとOllamaを連携させ、ローカルチャットボット環境を作る" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">DifyとOllamaを連携させ、ローカルチャットボット環境を作る</div><div class="blogcard-snippet internal-blogcard-snippet">前回はLM StudioとDifyの連携でしたが、今回は、Ollamaと連携させてみました。どちらもそれぞれ特徴があるので、使い分けてもいいと思います。私的には、スタンドアローンで使うならLM Studio。Difyとの連携であればOllama かな？と思っています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.30</div></div></div></div></a>
</div></figure>



<h2 class="wp-block-heading"><span id="toc23">あとがき</span></h2>



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