GPU および永続的なモデルストレージを使用する Docker Compose での Ollama

GPU および永続性を備えた Compose ファーストの Ollama サーバー。

目次

Ollama は、メタル(物理マシン)上で非常に良好に動作します。それをサービスとして扱うと、さらに興味深くなります。安定したエンドポイント、固定されたバージョン、永続的なストレージ、そして GPU が利用可能か不可かの明確な状態が確保されます。

この投稿の目的は 1 つです。Docker Compose を使用し、GPU 加速と永続的なモデルストレージを備えた、再現性の高いローカルまたはシングルノードの Ollama「サーバー」を構築することです。

ollama docker compose

ここでは、Docker や Compose の一般的な基礎知識についてはあえて触れません。最も頻繁に使用するコマンド(イメージ、コンテナ、ボリューム、docker compose など)のコンパクトなリストが必要な場合は、Docker チートシート が役に立つ相棒になります。

Ollama の前に HTTPS を導入し、正しいストリーミングと WebSocket プロキシ機能を備え、エッジ制御(認証、タイムアウト、レート制限)を実現したい場合は、Caddy または Nginx を使用した逆プロキシ裏での Ollama による HTTPS ストリーミング をご覧ください。

Ollama が vLLM、Docker Model Runner、LocalAI、クラウドホスティングのトレードオフとどのように共存するかについては、 2026 年の LLM ホスティング:ローカル、セルフホスト、クラウドインフラの比較 を参照してください。

Compose がメタルインストールに勝るケース

ネイティブインストールは、1 人の開発者が 1 台のマシンで使用する場合は摩擦なく導入できます。しかし、以下のいずれかの状況が生じた瞬間から、Comose の方が操作しやすさが勝ります。

チーム環境では、サービス定義がレビュー可能、バージョン管理可能、共有可能なファイルとして存在するためメリットがあります。シングルノードサーバーでは、アップグレードがイメージタグの更新と再起動だけで済む一方で、モデルストレージは(ボリューム上にあれば)そのままで済みます。Ollama は、Web UI、逆プロキシ、認証ゲートウェイ、ベクトル DB、エージェントランタイムなどのサイドカーと共存する傾向があります。Compose は「1 つのコマンドでスタック全体を起動する」のに優れており、ホストを「スノーフレーク(独自の構成)」にする必要がありません。

このアプローチは、公式の Ollama コンテナの設計思想とも合致します。イメージはデフォルトで ollama serve を実行し、ポート 11434 を公開し、マウント可能なディレクトリ下で状態を保持することを目的としています。

Ollama に実際に役立つ Compose の骨子

まずは 2 つの決定から始めましょう。

第一に、バージョンをどのように固定するかです。Docker Hub のイメージは ollama/ollama なので、latest に依存するのではなく、.env ファイルで特定のタグを固定できます。

第二に、モデルデータをどこに配置するかです。公式ドキュメントでは、コンテナが置換されるたびにモデルを再ダウンロードしないよう、ボリュームを /root/.ollama にマウントすることを推奨しています。

以下は、これらの決定を組み込み、設定パラメータ(ノブ)をサービス近くに保った Compose ファイルの例です。

services:
  ollama:
    image: ollama/ollama:${OLLAMA_IMAGE_TAG:-latest}
    container_name: ollama
    restart: unless-stopped

    # デフォルトではローカルに保持し、必要に応じて公開します。
    ports:
      - "${OLLAMA_BIND_IP:-127.0.0.1}:11434:11434"

    # モデルとサーバー状態の永続化。
    volumes:
      - ollama:/root/.ollama

    environment:
      # 公式イメージはすでにコンテナ内で 0.0.0.0:11434 にデフォルトでバインドされますが、
      # 後でオーバーライドする際に明示的に設定しておくことが役立ちます。
      - OLLAMA_HOST=0.0.0.0:11434

      # サービスタイニング。
      - OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-5m}
      - OLLAMA_NUM_PARALLEL=${OLLAMA_NUM_PARALLEL:-1}
      - OLLAMA_MAX_LOADED_MODELS=${OLLAMA_MAX_LOADED_MODELS:-1}

      # オプションですが、ブラウザベースの UI が直接 Ollama と通信する場合に関連します。
      # 存在理由については Networking セクションを参照してください。
      - OLLAMA_ORIGINS=${OLLAMA_ORIGINS:-}

    # GPU 予約は以下の別セクションにあります。
    # 実際には NVIDIA GPU を搭載したホストでのみ追加してください。

volumes:
  ollama: {}

対応する .env ファイルがあれば、アップグレードも退屈なく済みます。

# テスト済みのイメージバージョンを固定します。
OLLAMA_IMAGE_TAG=latest

# デフォルトではローカルにします。意図的に公開する場合は 0.0.0.0 に変更してください。
OLLAMA_BIND_IP=127.0.0.1

# キープアライブ設定は、コールドスタートの遅延とメモリフットプリントのバランスを調整します。
OLLAMA_KEEP_ALIVE=5m

# 並行性の調整。
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1

# ブラウザクライアントが直接 Ollama にアクセスする場合以外は、空のままにします。
OLLAMA_ORIGINS=

少しだけ重要なニュアンスがあります。Ollama 自体の一般的な設定ではデフォルトホストバインドが 127.0.0.1:11434 ですが、公式コンテナイメージでは OLLAMA_HOST=0.0.0.0:11434 を設定しており、これが公開されたポートを通じてアクセス可能になります。

クライアント SDK を使用せずに素早く健全性チェックを行いたい場合、Ollama API には GET /api/tags エンドポイントに「ローカルモデルのリスト」が用意されています。

永続的なモデルストレージと、最もストレスなく移動する方法

1 つだけ覚えるなら、これにしてください:コンテナには永続的なストレージが必要です。そうでなければ、再ビルドのたびにモデルを再ダウンロードすることになります。

Ollama は OLLAMA_MODELS を使用してモデルディレクトリを選択できます。参照実装では、デフォルトは $HOME/.ollama/models であり、OLLAMA_MODELS を設定することでこれを上書きできます。

公式 Docker イメージ内では、$HOME は文書化されたボリュームマウント(/root/.ollama)で使用される /root レイアウトに自然にマップされます。これが、公式の docker run 例でそのディレクトリをマウントする理由です。

実際の運用でよく機能するストレージパターンの 2 つがあります。

名前付き Docker ボリュームが最もシンプルで移植性が高いです。ただし、誤って孤立させる(オーファン化する)リスクもあるため、意図的に名前を付与(例:ollama)し、Compose のリファクタリングを通じて安定性を保つことが重要です。

モデルサイズがルートファイルシステムを支配し始めた場合は、専用ディスクへのバインドマウントが優れています。その場合、/root/.ollama 全体をそのディスクにマウントするか、カスタムディレクトリをマウントして OLLAMA_MODELS でそれを指すかのいずれかになります。

ストレージの再編成を積極的に行っている場合、明示的な「モデルの移動」プレイブックが役立ちます。参照:move-ollama-models

Compose と NVIDIA Container Toolkit を使った NVIDIA GPU サポート

Ollama は Docker 内で NVIDIA GPU を使用できますが、イメージが魔法のように GPU を出現させることはできません。ホストには動作する NVIDIA ドライバーと NVIDIA Container Toolkit が必要であり、Docker もそれを使用するように構成する必要があります。Ollama の Docker ドキュメントでは、nvidia-container-toolkit のインストール、nvidia-ctk runtime configure --runtime=docker によるランタイムの構成、そして Docker の再起動を明確に指示しています。

Compose 側では、クリーンで現代的な方法はデバイスの予約です。Docker は、deploy.resources.reservations.devices を使用して Compose で GPU アクセスを文書化しており、capabilities: [gpu]driver: nvidia、そして countall を含む)または device_ids を指定します。

NVIDIA ホストを使用する場合、ollama サービスに以下を追加します。

deploy:
  resources:
    reservations:
      devices:
        - driver: nvidia
          count: all
          capabilities: [gpu]

複数の GPU を持ち、特定のデバイスで Ollama を動作させたい場合は、Docker が文書化しているように count から device_ids に切り替えます(これらは排他的です)。

時々、runtime: nvidia を使用したレガシーな Compose 例を見かけるかもしれませんが、新しいセットアップでは「unknown or invalid runtime name: nvidia」というエラーで失敗することがあります。これは、サポートされているデバイス予約パターンに移行し、ホストでツールキットが構成されていることを確認するべきという強力なヒントです。

平然と隠れている有用な詳細:公式 ollama/ollama イメージは NVIDIA_VISIBLE_DEVICES=allNVIDIA_DRIVER_CAPABILITIES=compute,utility を設定しています。これらは NVIDIA コンテナランタイムによって認識される標準的な設定であり、上書きしない限りすでに存在します。

実際に GPU 推論が得られているか(単にコンテナが起動するだけでなく)を確認するには、Ollama は ollama ps を使用して「Processor」カラムを確認することを推奨しています。ここには、モデルが GPU メモリにロードされているかが表示されます。

プラットフォームの現実確認:Ollama によると、Docker での GPU 加速は Linux(および WSL2 を含む Windows)で利用可能ですが、GPU パススルーの欠如により macOS の Docker Desktop では利用できません。

ネットワーク選択:ホスト vs ブリッジ、ポート、CORS

ネットワーク設定は、多くの「動作するが、アプリからは接続できない」というバグの発生源です。

公開ポートを使用したブリッジネットワーキング

デフォルトの Compose ネットワークはブリッジネットワークです。この設定では、11434:11434 を公開することで、ホストからはポート 11434 で Ollama にアクセスできますが、他のコンテナはサービス名 ollamalocalhost ではない)を使用して通信する必要があります。コンテナ内の localhost が「このコンテナ自身」を指し、「Ollama コンテナ」を指さないため、多くの人がここで躓きます。

Ollama 自体はポート 11434 で HTTP サーバーを実行しており(イメージが公開)、一般的な慣例として、ポートが公開されている場合、ホスト上のクライアントは http://localhost:11434 を使用します。

ホストネットワーキング

network_mode: host は、シングルノードサーバーでは誘惑的な選択肢です。ポート公開が不要になり、localhost のセマンティクスが単純化されるためです。しかし、トレードオフとして、ブリッジネットワークの分離とネームスペースのメリットを失い、ポート競合に遭遇する可能性が高くなります。

Ollama の意図的な公開

通常のインストールでは、Ollama はデフォルトで 127.0.0.1 にバインドされ、バインドアドレスを変更する文書化された方法は OLLAMA_HOST の設定です。

Docker では 2 つのレイヤーがあります:

OLLAMA_HOST で制御される Ollama のバインドアドレス(コンテナイメージはコンテナ内ですべてのインターフェースにバインドするデフォルト)。

コンテナ外からの到達性は、Compose の ports とホストのファイアウォールで制御されます。

私が好きなパターンは、127.0.0.1:11434:11434 で「デフォルトでローカルにバインド」し、公開する理由がある場合にのみ 0.0.0.0:11434:11434 に切り替えることです。

ブラウザクライアントと OLLAMA_ORIGINS

ブラウザベースの UI や拡張機能が Ollama に直接呼び出す場合、CORS の領域に入ります。Ollama はデフォルトで 127.0.0.10.0.0.0 からのクロスオリジンリクエストを許可しており、OLLAMA_ORIGINS を使用して追加のオリジンを構成できます。

これはシングルノードでも重要です。「curl で動作する」ことが「ブラウザアプリから動作する」ことを意味しないからです。

シングルノードサーバーに適したアップグレードとロールバックのパターン

Ollama は急速に進化します。Compose ファイルを使用することで、その変化を静かなプロセスとして扱い、深夜の意外な事態を防げます。

“latest"の動作に期待するのではなく、タグを上げてアップグレードする

最も実用的なアップグレード戦略は、.env ファイルで既知の良好なタグにイメージを固定し、意図的にそれを上げることです。イメージは Docker Hub で ollama/ollama として公開されています。

モデルデータとサーバー状態はマウントされたディレクトリ下(公式ドキュメントでは /root/.ollama)に保存されるため、コンテナを置換してもモデルの再ダウンロードは発生しません。

ロールバックはタグを元に戻すだけ

ロールバックは逆のメカニズムです:前のタグを設定し、コンテナを再作成し、同じボリュームを保持します。ここが、固定(ピン)の恩恵が得られる場所です。

データ移行は主にストレージパスについて

シングルノード設定におけるほとんどの「移行」は、データベーススキーマについてではありません。ディスクレイアウトについてです。モデルディレクトリを変更した場合(OLLAMA_MODELS を介して)、またはマウントされたボリュームを新しいディスクに移動した場合、それがデータ移行となるのは言うまでもありません。

実際のマシンでモデルディレクトリを再編成するための実用的なガイドが必要な場合は、以下を参照してください:move-ollama-models

見落としがちな最終的な注記:Ollama の API ドキュメントでは、API は安定しており後方互換性があり、リリースノートで告知される稀な非推奨化を除いて変化しないことが明示されています。これは、シングルノードサービスエンドポイントにおいて「サーバーをアップグレードしてもクライアントは動作し続ける」ことが合理的なデフォルトの期待であることを意味します。

一般的な失敗:GPU 権限、ドライバーの不一致、OOM

このセクションは意図的に症状主導です。目標は「あり得るすべての Docker エラー」ではなく、Ollama + GPU + 永続ストレージのセットアップで特に発生する失敗のみを扱うことです。

ホストでは GPU が確認できるが、コンテナでは見つからない

ホストに動作する NVIDIA ドライバーがあるにもかかわらず、コンテナで GPU が見えない場合、一般的な原因は以下の通りです:

NVIDIA Container Toolkit がインストールされていないか、Docker ランタイムが nvidia-ctk を介して構成されていない。Ollama の Docker ドキュメントではこれが直接指摘されています。

Compose が GPU デバイスを予約していない。Docker が文書化している通り、deploy.resources.reservations.devicesgpu キャパビリティを指定するのがサポートされている方法です。

レガシーな runtime: nvidia 構成が、それを認識しないデーモンで使用されており、「unknown or invalid runtime name: nvidia」というエラーが発生しています。

検証のために ollama ps を使用すると実用的なチェックが可能です。モデルが GPU メモリにロードされているかが表示されます。

GPU デバイスへのアクセス権限エラー

「アクセス拒否(permission denied)」という GPU 失敗のタイプは、Ollama 自体よりも環境制約を指す傾向があります。例としては、ルートを介さない Docker の実行、セキュリティポリシー、デバイスノードが意図通りに公開されていないなどが挙げられます。Docker Compose の GPU サポートドキュメントでは、ホストに GPU デバイスが必要であり、Docker デーモンがそれに応じて設定されている必要があると明確にしています。

疑わしい場合は変数を減らしてください:まずツールキット構成(ホスト)、次に GPU 予約(Compose)、そして GPU 使用状況(ollama ps)を確認します。

ドライバーの不一致、期待の誤り

Docker 内の Ollama はホストのドライバースタックに依存します。ホストのドライバーが欠落している、古すぎる、または誤って構成されている場合、「Ollama が壊れている」ように見える失敗が発生しますが、実際には「CUDA スタックが使用できない」という状態です。公式ドキュメントでは、NVIDIA GPU の使用における前提条件として、コンテナツールキットと Docker デーモン構成を位置付けています。

メモリ不足:VRAM または RAM が急速に消失する

OOM(メモリ不足)は、ローカル推論において最も予測可能な失敗モードであり、通常は構成による自己責任です。

Ollama は、複数のロードされたモデルと並行リクエスト処理による並行処理をサポートしていますが、利用可能なメモリ(CPU 推論の場合はシステム RAM、GPU 推論の場合は VRAM)に制約されます。GPU 推論を使用する場合、並行モデルロードを可能にするには、新しいモデルが VRAM に収まる必要があります。

2 つの構成詳細は、第一級の「サーバー設定」として扱う価値があります:

OLLAMA_NUM_PARALLEL はモデルあたりの並行リクエスト処理を増加させますが、必要なメモリは OLLAMA_NUM_PARALLEL * OLLAMA_CONTEXT_LENGTH に比例してスケーリングします。

OLLAMA_KEEP_ALIVE はモデルがロードされたままになる時間を制御します(デフォルトは 5 分)。モデルをロードしたままにすることでコールドスタートの遅延は減りますが、メモリも固定されます。

負荷下でシングルノードサービスを安定化させる場合、劇的な修正ではなく、以下のような非劇的な修正が一般的です:

何かを変更する前に、並行性とコンテキストのデフォルト値を下げる。

同時にロードされたままにされるモデルの数を制限する。

ボトルネックがメモリであり、生計算能力ではない場合、Flash Attention (OLLAMA_FLASH_ATTENTION=1) や低い精度の K/V キャッシュタイプ (OLLAMA_KV_CACHE_TYPE) などのメモリ削減機能を検討する。

Ollama が原因ではない場合:Docker Model Runner の選択

時として、「失敗」は実際にはツールのミスマッチです。組織がすでに Docker ネイティブなアーティファクトとワークフローを標準化している場合、長寿命のサービスコンテナとして Ollama を実行するよりも、Docker Model Runner (DMR) の方が適している可能性があります。

Docker は、DMR を Docker Hub や他の OCI レジストリから直接モデルを管理、実行、提供し、OpenAI 互換および Ollama 互換の API を提供する手段として位置付けています。

また、複数の推論エンジン(llama.cpp や、Linux 上で NVIDIA GPU を使用した vLLM など)をサポートしており、単に「1 つのモデルをローカルで実行する」だけでなく、スループット特性を重視する場合に重要になります。

実用的なコマンド参照とより深い比較の視点が必要な場合は、以下を参照してください:Docker Model Runner チートシート:コマンドと例