ここ数年で、AIモデルが今後も多くのアプリケーションの基本的なコンポーネントであることが明らかになりました。問題は、それらが根本的に 異なる タイプのコンポーネントでもあり、複雑なソフトウェアとハードウェアの要件が(まだ)コンテナ指向の開発ライフサイクルとアーキテクチャの制約にうまく適合していないことです。この問題に対処するために、Docker は Docker Desktop 4で Docker Model Runner をリリースしました。40。それ以来、私たちは Docker Model Runner の拡張に積極的に取り組み、OS とハードウェアのサポートを追加し、一般的な Docker ツールとのより緊密な統合を行い、パフォーマンスとユーザビリティを改善してきました。
Docker Model Runner とその将来に関心のある方のために、その設計、開発、ロードマップの舞台裏をご紹介します。
手記: Docker Model Runner は、実際には Model Runner と Model Distribution Specification の 2 つの コンポーネントです。この記事では、前者について説明しますが、ストーリーの同様に重要な配布の側面については、Emily Caseyによる コンパニオンブログ投稿 を必ずチェックしてください。
設計目標
Docker Model Runnerの主な設計目標は、ユーザーが AIモデルをローカルで実行 し、コンテナとホストプロセスの両方からアクセスできるようにすることでした。これは簡単に表現できますが、それでも解決策を見つけるための巨大なデザイン空間が残されています。幸いなことに、私たちは小さなエンジニアリングチームであり、野心的なタイムラインを持っていたという制約がありました。最も重要なことは、UXを一度に提供できなくても、UXに妥協したくなかったことです。最終的には、これが設計上の決定を動機付け、これまでのところ、実行可能なソリューションを提供しながら、将来の改善の余地を十分に残すことができました。
複数のバックエンド
早い段階でわかっていたことの 1 つは、独自の推論エンジンを作成するつもりはないということでした (Docker の操舵室はコンテナ化された開発であり、低レベルの推論エンジンではありません)。また、私たちはオープンソースの大きな支持者でもあり、既存の素晴らしいソリューションがたくさんありました。llama.cppがあります、vLLM、MLX、ONNX、PyTorch など、さまざまなものがあります。
もちろん、選択の余地がないというのは呪いにもなり得ます - どちらを選ぶべきか?明白な答えは、一度にすべてではなく、できるだけ多くの人を選ぶことでした。
最初の実装では llama.cpp を採用することにしましたが、ユーザーが将来の複数のバックエンドを利用できるように、意図的に追加のオプションのパスコンポーネント (/engines/{name} の {name}}) を使用して API を設計しました。また、他のバックエンドのインターフェースを設計し、実装をスタブアウトして、開発の衛生状態を良好に保ち、1つの「初期」実装に縛られるのを避けました。
OpenAI API の互換性
私たちが行わなければならなかった 2 番目の設計上の選択は、推論をコンテナ内の消費者にどのように公開するかでした。推論 API の分野でもかなりの選択肢がありましたが、OpenAI API 標準が初期ツールの互換性として最適であるように思われることがわかりました。また、Docker 内のいくつかのチームが、すでにこの API をさまざまな現実世界の製品に使用しているという事実にも動機付けられました。将来的には追加の API をサポートする可能性がありますが、これまでのところ、この API サーフェスはほとんどのアプリケーションにとって十分であることがわかりました。私たちが知っているギャップの1つは、このAPIサーフェスと の完全な 互換性であり、これは私たちが繰り返し取り組んでいることです。
この決定は、最初のバックエンドとしてllama.cppを選択するきっかけにもなりました。llama.cppプロジェクトは、 サーバー の実装を通じて、OpenAI API互換性のターンキーオプションをすでに提供していました。いくつかの小さな変更を加える必要がありましたが(例:Unix ドメインソケットのサポート)、これにより、ソリューションへの最速の道筋が提供されました。また、これらの小さなパッチをアップストリームで提供し始めており、将来的にはこれらのプロジェクトへの貢献を拡大したいと考えています。
Docker API のモデルに対する第一級市民権
OpenAI API 標準は、既存のツールの中で最もユビキタスなオプションでしたが、 Docker Engine API ではモデルを最級市民にしたいこともわかっていました。モデルの実行ライフサイクルは、通常コンテナの ENTRYPOINTを構成するプロセスとは根本的に異なるため、Docker Engine API の標準の /containers エンドポイントにはうまく適合しません。ただし、コンテナ、イメージ、ネットワーク、ボリュームと同様に、モデルは基本的なコンポーネントであるため、独自の API リソースタイプに本当に値します。これにより、/images エンドポイントを厳密にモデルにした一連の /models エンドポイントを追加する動機となりましたが、ディストリビューションのブログ記事で最もよく説明されている理由から分離されています。
GPUアクセラレーション
もう 1 つの重要な設計目標は、推論演算の GPU アクセラレーションのサポートでした。最も小さくて有用なモデルでさえ、非常に計算負荷が高くなりますが、より洗練されたモデル(ツール呼び出し機能を備えたモデルなど)は、ローカルハードウェアに適合させるのは困難です。GPUのサポートは、便利なエクスペリエンスのために交渉の余地がないものでした。
残念ながら、Docker Desktop で VM の境界を越えて GPU を渡すことは、特にプラットフォーム間で信頼性が高く、コンテナ内で使用可能な計算 API を提供する方法では、不可能であるか、非常に不安定なものでした。
妥協案として、Docker Desktop VM の外部で推論操作を実行し、VM からホストへの API 呼び出しを単純にプロキシすることにしました。このアプローチにはいくつかのリスクがありますが、macOS と Windows でのコンテナホスト型サンドボックス化により、これらを軽減する取り組みに取り組んでいます。さらに、Docker が提供するモデルとアプリケーションが提供するプロンプトを使用すると、特に推論が主に数値演算で構成されていることを考えると、リスクはいくらか低くなります。Docker Desktop のリスクは、 host.docker.internal を介してホスト側のサービスにアクセスする場合とほぼ同等であると評価しています (これはデフォルトですでに有効になっています)。
しかし、モデル出力でツールの使用を促進するエージェントは、より重大な副作用を引き起こす可能性があり、それに対処する必要がありました。幸いなことに、 Docker MCP Toolkit を使用すると、エフェメラル コンテナ内でツールの呼び出しを実行でき、モデルが引き起こす可能性のある副作用を確実にカプセル化できます。このハイブリッドなアプローチにより、ツールを使用する際に比較的安心して、可能な限り最高のローカルパフォーマンスを提供することができます。
Docker Desktop のコンテキスト以外では、たとえば Docker CE では、ホスト ハードウェアとコンテナの間に VM 境界 (ハイパーバイザーの場合は少なくとも 非常に透明な VM 境界) がないため、非常に有利な立場にあります。Docker CE でスタンドアロン モードで実行すると、Docker Model Runner はホスト ハードウェアに直接 ( NVIDIA Container Toolkit などを介して) アクセスでき、コンテナ内で推論操作を実行します。
モジュール性、イテレーション、オープンソース化
前述のように、Docker Model Runner チームは比較的小規模であるため、Docker Model Runner の開発作業を効果的に並列化するためには、モノリシック アーキテクチャに頼ることはできませんでした。さらに、私たちは早くから、可能な限りオープンソースにするという包括的な指示を持っていました。
私たちは、開発作業を整理するための 3 つの高レベルのコンポーネント ( モデル ランナー、 モデル配布ツール、 モデル CLI プラグイン) を決定しました。
これらのコンポーネントを分割することで、作業をより効果的に分割し、より迅速に反復し、異なる懸念事項間で明確な API 境界を定義することができました。依存関係にはいくつかの厄介なハードルがありましたが (特にクローズドソースのコンポーネントと統合する場合)、モジュラーアプローチにより、新しいプラットフォームの迅速な増分変更とサポートが促進されたことがわかりました。
高レベルのアーキテクチャ
大まかに言うと、Docker Model Runner アーキテクチャは、上記の 3 つのコンポーネント (ランナー、ディストリビューション コード、CLI) で構成されていますが、それぞれには興味深いサブコンポーネントもいくつかあります。

図 1:Docker Model Runnerの高レベルアーキテクチャ
これらのコンポーネントがどのようにパッケージ化され、ホストされるか (およびそれらがどのように相互作用するか) は、デプロイされるプラットフォームによっても異なります。いずれの場合も、見た目は少し異なります。ホスト上で実行される場合もあれば、VM で実行される場合もあれば、コンテナーで実行される場合もありますが、全体的なアーキテクチャは同じように見えます。
モデル ストレージとクライアント
中核となるアーキテクチャ コンポーネントは モデル ストアです。このコンポーネントは、モデル配布コードによって提供され、実際のモデルテンソルファイルが格納される場所です。これらのファイルは、 (1) 高エントロピーで特に圧縮性がなく、 (2) 推論エンジンが mmap() を介して仮想アドレス空間にマッピングするようなことをするために、ファイルに直接アクセスする必要があるため、画像とは異なる (そして別々に) 保存されます。詳細については、付属のモデル配布に関するブログ記事を参照してください。
モデル配布コードは、 モデル配布クライアントも提供します。このコンポーネントは、OCIレジストリに対してモデル配布プロトコルを使用して操作(モデルのプルなど)を実行します。
モデルランナー
モデル ストアの上に構築されるのは 、モデル ランナーです。モデルランナーは、インバウンド推論APIリクエスト(例:/v1/chat/completions または /v1/embeddings requests) を、推論エンジンとモデルのペアをホストしているプロセスに送信できます。これには、モデルを同時にロードできない場合でも、同時リクエストを処理できるように、メモリ内およびメモリ外へのモデルの読み込みを調整するスケジューラ、ローダー、およびランナーコンポーネントが含まれます(例:リソースの制約のため)。これにより、モデルの実行ライフサイクルはコンテナの実行ライフサイクルとは異なり、エンジンとモデルは一時的なプロセス(ほとんどがユーザーから隠される)として機能し、必要に応じて(またはアイドル状態のときに)メモリから終了およびアンロードできます。エンジンの組み合わせごとに異なるバックエンドプロセスが実行されます (例:llama.cpp)およびモデル(例:ai/qwen3:8B-Q4_K_M)推論 API リクエストで必要に応じて (ただし、同じペアを対象とする複数のリクエストは、可能であれば同じランナーとバックエンド プロセスを再利用します)。
ランナーには、バックエンドのバイナリとライブラリを動的にダウンロードできるインストーラーサービスも含まれており、ユーザーは数百MBの依存関係のダウンロードが必要になる可能性のある機能(CUDAサポートなど)を選択的に有効にすることができます。
最後に、モデルランナーは、 /models API (モデル配布コードにルーティングされる) や /engines API (スケジューラーにルーティングされる) など、すべての Docker Model Runner API の中央サーバーとして機能します。このAPIサーバーは、 503 レスポンスのようなものを返すのではなく、リソース(主にRAMまたはVRAM)がそれらを処理するために使用できるまで、常に処理中のリクエストを保持することを選択します。これは、複数のエージェントが異なるモデルで実行されている場合や、埋め込みと完了の両方に対する同時要求など、多くの使用パターンにとって重要です。
モデルCLI
Docker Model Runner アーキテクチャの主要なユーザー向けコンポーネントは、 モデル CLI です。このコンポーネントは、 docker image コマンドと非常によく似たインターフェイスを提供する標準の Docker CLI プラグイン です。モデル実行のライフサイクルはコンテナのライフサイクルとは異なりますが、概念(プッシュ、プル、実行など)は、既存のDockerユーザーにとって十分に馴染み深いものでなければなりません。
モデル CLI は、モデル ランナーの API と通信して、ほぼすべての操作を実行します (ただし、その通信のトランスポートはプラットフォームによって異なります)。モデル CLI はコンテキスト対応であるため、Docker Desktop モデルランナー、Docker CE モデルランナー、またはカスタムプラットフォーム上のモデルランナーと通信しているかどうかを判断できます。標準のDocker CLIプラグインフレームワークを使用しているため、標準の Docker Context 機能をすべて無料で利用でき、この検出がはるかに容易になります。
APIの設計とルーティング
前述のように、Docker Model Runner は、Docker スタイルの API と OpenAI 互換の API の 2 つの API セットで構成されています。Docker スタイルの API ( /image API をモデルにしています) には、次のエンドポイントが含まれます。
- POST /models/create (モデルのプル)
- GET /models (モデル一覧)
- GET /models/{namespace}/{name} (モデルメタデータ)
- DELETE /models/{namespace}/{name} (モデルの削除)
これらのリクエストの本文は、画像の類似物と非常によく似ています。現時点ではドキュメントはありませんが、 対応するGoタイプを見ることで、形式を垣間見ることができます。
対照的に、OpenAI エンドポイントは、異なるが RESTful な規則に従います。
- GET /engines/{engine}/v1/models (OpenAI形式のモデルリスト)
- GET /engines/{engine}/v1/models/{namespace}/{name} (OpenAI 形式のモデルメタデータ)
- POST /engines/{engine}/v1/chat/completions (チャットの完了)
- POST /engines/{engine}/v1/completions (チャットの完了 (レガシー エンドポイント))
- POST /engines/{engine}/v1/embeddings (埋め込みを作成する)
現時点では、サポートされている {engine} 値は 1 つだけです (llama.cpp)。また、デフォルト(llama.cpp)の使用を省略することもできますエンジン。
これらの API は、いくつかの異なるエンドポイントで使用できるようにします。
まず、Docker Desktop では、Docker ソケット (/var/run/docker.sock) で使用できます。コンテナの内側と外側の両方。これは、Docker Engine API でモデルを第一級市民として持つという設計目標にサービスを提供するものです。現時点では、これらのエンドポイントの先頭には /exp/vDD4が付けられています40path (開発中に進化する可能性のある API への依存を避けるため) ですが、これらの API は現在ほとんど安定しており、下位互換性のある方法で進化するため、次のいくつかのリリースでこのプレフィックスを削除する可能性があります。
次に、Docker Desktop でも、コンテナからのみアクセス可能な特別な model-runner.docker.internal エンドポイントで API を利用できるようにします (ただし、推論サンドボックスを最初に実装したいため、現在は ECI コンテナからではありません)。この TCP ベースのエンドポイントは、(Docker API 全体ではなく) /models API エンドポイントと /engines API エンドポイントのみを公開し、既存のツール (Unix ドメイン ソケット経由で API にアクセスできない可能性が高い) を提供するように設計されています。/exp/vDD4がありません。40この場合、プレフィックスが使用されます。
最後に、Docker Desktop と Docker CE の両方で、/models API エンドポイントと /engines API エンドポイントをホスト TCP エンドポイント (localhost:12434で、デフォルトで /exp/vDD4 なしで使用できるようにします40プレフィックス)。Docker Desktop では、これはオプションであり、デフォルトでは有効になっていません。Docker CE では、API エンドポイントへのアクセス方法の重要なコンポーネントであり、現在、Docker CE の /var/run/docker.sock にエンドポイントを追加したり、カスタムの model-runner.docker.internal ホスト名を挿入したりするための統合がないため、標準の 172.17.0.1 を使用することをお勧めします。この localhost に公開されているポートにアクセスするためのホスト ゲートウェイ アドレス (例:OpenAI API のベース URL を http://172.17.0.1:12434/engines/v1) に設定します。近い将来、これをDockerプラットフォーム間で統合できるようになることを願っています(以下のロードマップを参照)。
まずは、Docker Desktop
Docker Model Runner の自然な最初のステップは、Docker Desktop への統合でした。Docker Desktop では、Docker エンジンとの統合や、モデルランナーコンポーネントのホストに使用できる既存のプロセスをより直接的に制御できます。この場合、モデルランナーとモデル配布コンポーネントはDocker Desktopホストバックエンドプロセス( com.docker.backend プロセスが実行されているのを見たことがあるかもしれません)に存在し、特別なミドルウェアとネットワーキングマジックを使用して 、/var/run/docker.sock と model-runner.docker.internal 上のリクエストをモデルランナーのAPIサーバーにルーティングします。個々の推論バックエンドプロセスは com.docker.backend のサブプロセスとして実行されるため、たとえば、推論バックエンドがメモリ不足 (OOM) エラーによって強制終了された場合、Docker Desktop でクラッシュするリスクはありません。
当初は、モデルランナー機能を開発するための最も統一されたプラットフォームを提供した Apple Silicon 上の macOS のサポートから始めましたが、すべての Docker Desktop プラットフォーム向けにビルドとテストを行う途中でほとんどの機能を実装しました。これにより、AMD64 および ARM64 プラットフォーム上の Windows への移植が大幅に容易になり、そこで見つかった GPU のバリエーションも使用できるようになりました。
Windows で問題になったのは、GPU ベースのバックエンドのサポートライブラリの依存関係のサイズが大きいことでした。Docker Desktop for Windowsインストーラーにさらに 500 MB〜 1 GBを追加しても実現不可能(または許容)ではなかったため、Docker Desktop for WindowsのCPUベースのバックエンドをデフォルトにし、オプションでGPUバックエンドをサポートすることにしました。これが、モデルランナーの動的インストーラーコンポーネントの主な動機付けでした(さらに、さまざまなバックエンドへの増分更新を望んでいました)。
これはすべて非常によく計画された演習のように聞こえ、実際、3つのコンポーネント設計と厳密に強制されたAPI境界から始めましたが、実際には、Docker Desktopソースコードのサブパッケージとしてモデルランナーサービスコードから始めました。これにより、特にさまざまなサービスのアーキテクチャを探求する際に、迅速なイテレーションがはるかに容易になりました。幸いなことに、コードに対して比較的厳格な分離ポリシーを堅持し、API とインターフェイスを通じてクリーンな依存関係を強制することで、オープンソース化の目的でコード (優れた git-filter-repo ツールに称賛を送ります) を別のリポジトリに簡単に抽出することができました。
次の目的地:Docker CE
Docker のオープンソース化へのこだわりは別として、Docker Model Runner のソースコードを公開したいと考えた主な理由の 1 つは、Docker CE への統合をサポートすることでした。私たちの目標は、docker buildx や docker compose と同じ方法で docker model コマンドをパッケージ化することでした。
Docker CE の秘訣は、Docker Model Runner を「バニラ」の Docker CLI プラグイン (つまり、特別な権限やAPIアクセスがない)、つまり、モデルランナーサービスをホストできるバックエンドプロセスがなかったのです。ただし、Docker CE の場合、ホスト ハードウェアとコンテナ プロセスの間の境界は中断がはるかに少ないため、実際にはコンテナ内で Docker Model Runner を実行し、アクセラレータ ハードウェアを直接利用できるようにすることができます。そのため、スタンドアロンの BuildKit ビルダーコンテナと同様に、Docker Model Runner を Docker CE のスタンドアロンコンテナとして実行し、モデルストレージ用に特別な名前のボリュームを使用します (つまり、モデルを再プルせずにランナーをアンインストールできます)。この「インストール」は、 docker/model-runner イメージをプルしてコンテナを起動することにより、モデル CLI によって自動的に (必要に応じて) 実行されます。ランナーの明示的な設定は、 docker model install-runner コマンドを使用して指定することもできます。必要に応じて、 docker model uninstall-runner を使用してモデルランナー (およびオプションでモデルストレージ) を削除することもできます。
残念ながら、これはUXとの小さな妥協点の1つにつながります:現在、 /var/run/docker.sock または特別な model-runner.docker.internalURL でモデルランナーAPIをサポートしていません。代わりに、モデルランナー API サーバーは、ホストシステムのループバックインターフェイスである localhost: の lamp:12434 (デフォルト) をリッスンします。これは、ほとんどのコンテナ内で 172. . .17.0.1:12434.必要に応じて、ユーザーはこれをmodel-runner.docker.internalで利用できるようにすることもできます12434–add-host=model-runner.docker.internal:host-gateway のようなものを利用するdocker run または docker create コマンドを実行する場合。これは、Compose YAML ファイルで extra_hosts キーを使用しても実現できます。今後のリリースでは、これをより人間工学に基づいたものにする予定です。
これからの道...
現状は、macOSおよびWindowsのDocker DesktopでのDocker Model Runnerのサポートと、Linux(WSL2を含む)でのDocker CEのサポートですが、それで話が終わるわけではありません。今後数か月の間に、Docker Model Runner のユーザー エクスペリエンス、パフォーマンス、セキュリティを再構築すると思われるいくつかのイニシアチブを計画しています。
追加のGUIおよびCLI機能
今後数か月の間に登場する最も目立つ機能は、モデルCLIとDocker Desktopダッシュボードの[モデル]タブです。モデルの実行の監視と制御をより直接的にサポートする新しいコマンド ( df、 ps、 unload など) が登場する予定です。また、[モデル] タブには、新しいレイアウトと拡張されたレイアウトと機能が表示されます。
OpenAI API サポートの拡張
Docker Model Runner のユーザー エクスペリエンスであまり目立たないが、同様に重要な側面は、OpenAI API との互換性です。サポートするエンドポイントとパラメータは多数あります(すでに多くのパラメータをサポートしています)ため、実際のユースケースに焦点を当て、既存のツールとの互換性を優先して、APIサーフェスの互換性の拡大に取り組みます。
containerdとMobyの統合
私たちが検討している長期的な取り組みの1つは、 containerdとの統合です。containerdは、ストレージと調整されたタスク実行を可能にするモジュラーランタイムシステムをすでに提供しています。私たちは、これが正しい方法であり、モデルの保存、モデルの実行、およびモデルの実行サンドボックスの関係をより適切に体系化できると信じています。
containerdの作業と組み合わせて、Mobyプロジェクトとのより緊密な統合も望んでいます。既存のDocker CE統合は実行可能でパフォーマンスの高いソリューションを提供しますが、より直接的な統合により、より優れた人間工学を実現できると考えています。特に、Docker CE での model-runner.docker.internal DNS 解決のサポートなどの優れた点が注目されています。おそらく、この緊密な統合による最大の利点は、Docker Model Runner API を Docker ソケットに公開し、API エンドポイント (例:/models)Docker Engine API の公式ドキュメントを参照してください。
Kubernetes
Docker Model Runnerの製品目標の1つは、開発の内部ループから本番環境まで一貫したエクスペリエンスを実現することであり、Kubernetesは間違いなくその道の一部です。Docker CE に使用している既存の Docker Model Runner イメージは、Kubernetes クラスター内でも機能し、現在、Kubernetes クラスターで Docker Model Runner インスタンスを設定する手順を開発しています。Kubernetesとの大きな違いは、使用されているクラスターとアプリケーションのアーキテクチャが多様であることであるため、さまざまなシナリオでDocker Model Runnerを構成する方法について、さまざまな「レシピ」が必要になる可能性があります。
vLLMの
多くのお客様から寄せられた声の 1 つは、vLLM がプロダクション スタックの中核コンポーネントであるということです。これは、モデルランナーリポジトリにスタブアウトした最初の代替バックエンドでもあり、実装を突っ込み始める時が来ました。
さらに増える...
最後に、まだお話しできない部分もありますが、それらは開発者がモデルと対話する方法を根本的に変えるでしょう。7 月 9日から11 日まで開催される WeAreDevelopers の Docker のセッションでは、Docker の AI 関連の取り組みに関するエキサイティングな発表をご覧いただけます。
さらに詳しく
- モデル分散仕様の背後にある ストーリー をご覧ください
- Docker Model Runner のクイックスタートガイドをお読みください。
- Model Runner のドキュメントが見つかります。
- Docker Navigator ニュースレターを購読してください。
- Docker は初めてですか? アカウントを作成します。
- 質問がありますか? Docker コミュニティがお手伝いします。