Docker ComposeでOllamaとOpen WebUIを構築する|GPU・永続化・LAN公開まで

Docker Composeにすると何が楽になるのか

Ollamaはコマンドだけでも使えますが、ブラウザから会話したい場合はOpen WebUIのようなUIを組み合わせると便利です。

ただし、2つを別々のdocker runで起動すると、次の問題が起きやすくなります。

  • コンテナを作り直したらモデルや会話履歴が消えた
  • Open WebUIからOllamaへ接続できない
  • GPUを積んでいるのにCPUで推論している
  • 更新手順が分からず、古いコンテナが残る
  • LANへ公開したら認証なしで誰でも使える状態になった

Docker Composeなら、コンテナ、ネットワーク、ボリューム、再起動設定を1つのcompose.yamlで管理できます。

この記事では、次の構成を作ります。

ブラウザ
  ↓ http://localhost:3000
Open WebUIコンテナ
  ↓ http://ollama:11434
Ollamaコンテナ
  ↓
ollama_dataボリューム(モデル)

open_webui_dataボリューム(ユーザー・設定・会話履歴)

ポイントは、コンテナ間の接続先にlocalhostを使わないことです。Composeの同じネットワーク内では、サービス名のollamaがホスト名になります。

必要なもの

事前にDockerをインストールし、次のコマンドが動くことを確認します。

docker --version
docker compose version

WindowsとmacOSではDocker Desktopを使うのが簡単です。LinuxではDocker EngineとComposeプラグインを利用できます。

NVIDIA GPUを使う場合は、ホスト側で次も確認します。

nvidia-smi

LinuxではNVIDIA Container Toolkitも必要です。WindowsでGPUを使う場合は、Docker DesktopのWSL 2バックエンドを利用します。

CPUだけで動かす最小構成

作業用フォルダを作り、その中にcompose.yamlを作成します。

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    volumes:
      - ollama_data:/root/.ollama
    networks:
      - ai-network

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    depends_on:
      - ollama
    ports:
      - "3000:8080"
    environment:
      OLLAMA_BASE_URL: http://ollama:11434
      WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY}
    volumes:
      - open_webui_data:/app/backend/data
    networks:
      - ai-network

volumes:
  ollama_data:
  open_webui_data:

networks:
  ai-network:

同じフォルダに.envを作り、十分に長いランダムな文字列を設定します。

WEBUI_SECRET_KEY=ここを十分に長いランダム文字列へ変更する

OpenSSLが使える環境なら、次のコマンドで生成できます。

openssl rand -hex 32

WEBUI_SECRET_KEYを固定しておくと、コンテナを作り直してもセッションや暗号化データを安定して扱えます。.envはGitへコミットしないでください。

起動します。

docker compose up -d

状態を確認します。

docker compose ps

ブラウザで次を開きます。

http://localhost:3000

最初に登録したユーザーが管理者になります。LANに公開する予定がある場合は、第三者が先に登録しないよう、起動直後に管理者アカウントを作成してください。

モデルをダウンロードする

Ollamaコンテナ内でモデルを取得します。モデル名は例なので、使用するメモリや目的に合うものへ変更してください。

docker compose exec ollama ollama pull gemma3:4b

ダウンロード済みモデルを確認します。

docker compose exec ollama ollama list

Open WebUIを再読み込みすると、モデル選択欄に表示されます。

APIが応答するかをコンテナ内で確認する場合は次のようにします。

docker compose exec ollama ollama ps

ホストからOllama APIへ直接アクセスする必要がなければ、11434:11434のポート公開は不要です。Open WebUIとOllamaはCompose内部のネットワークで通信できます。

NVIDIA GPUを使う構成

GPUを使う場合は、ollamaサービスへGPU予約を追加します。

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    networks:
      - ai-network

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    depends_on:
      - ollama
    ports:
      - "3000:8080"
    environment:
      OLLAMA_BASE_URL: http://ollama:11434
      WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY}
    volumes:
      - open_webui_data:/app/backend/data
    networks:
      - ai-network

volumes:
  ollama_data:
  open_webui_data:

networks:
  ai-network:

Docker ComposeのGPU予約ではcapabilities: [gpu]が必須です。また、countdevice_idsは同時に指定できません。GPUを1台だけ割り当てるなら上記のcount: 1で十分です。

設定を反映します。

docker compose up -d

OllamaからGPUが見えているか、ログを確認します。

docker compose logs ollama

推論中に別のターミナルでnvidia-smiを実行し、VRAM使用量とOllamaのプロセスが増えるかを見る方法も確実です。

GPUが認識されない場合は、Ollamaの前にDocker自体からGPUが見えるかを確認します。

docker run --rm --gpus all ubuntu nvidia-smi

このコマンドが失敗する場合、原因はComposeやOllamaではなく、ドライバー、WSL 2、NVIDIA Container Toolkit、Dockerランタイム側にあります。

なぜlocalhost:11434では接続できないのか

Open WebUIの設定で最も多い間違いがこれです。

environment:
  OLLAMA_BASE_URL: http://localhost:11434

コンテナ内のlocalhostは、そのコンテナ自身を指します。つまりOpen WebUIコンテナから見たlocalhostはOpen WebUIであり、別コンテナのOllamaではありません。

同じCompose内なら、正しくはサービス名を使います。

environment:
  OLLAMA_BASE_URL: http://ollama:11434

接続を切り分けるには、Open WebUIコンテナからOllamaのAPIへ到達できるかを調べます。

docker compose exec open-webui curl http://ollama:11434/api/tags

モデル一覧を含むJSONが返れば、コンテナ間の通信はできています。ここが成功するのに画面へモデルが出ない場合は、Open WebUI側の接続設定やログを確認します。

docker compose logs --tail=200 open-webui

ホストに入れたOllamaへ接続する場合

OllamaをコンテナではなくWindowsやmacOSへ直接インストールしている場合、Open WebUIの接続先は次のようにします。

environment:
  OLLAMA_BASE_URL: http://host.docker.internal:11434

この構成では、ホスト側のOllamaが外部からの接続を受けられる必要があります。Ollamaは標準では127.0.0.1:11434へバインドするため、環境によってはOLLAMA_HOST=0.0.0.0:11434の設定が必要です。

ただし、単に2つを同じPCで使うだけなら、OllamaもComposeへ含めた方がネットワーク構成を理解しやすくなります。

モデルと会話履歴を消さないための永続化

この構成では2つの名前付きボリュームを使っています。

ollama_data
  モデルデータ

open_webui_data
  ユーザー、設定、会話履歴など

コンテナを削除しても、ボリュームを削除しなければデータは残ります。

docker compose down
docker compose up -d

一方、次のコマンドはボリュームも削除します。

docker compose down -v

-vを付けると、ダウンロードしたモデルとOpen WebUIのデータを失う可能性があります。初期化する意図がない限り実行しないでください。

使用中のボリュームは次で確認できます。

docker volume ls
docker volume inspect プロジェクト名_ollama_data
docker volume inspect プロジェクト名_open_webui_data

LAN内のスマホや別PCから使う

Composeで次のポート設定をしている場合、通常はホストの全インターフェースで3000番ポートを待ち受けます。

ports:
  - "3000:8080"

ホストPCのIPアドレスが192.168.1.20なら、同じLAN内の端末から次へアクセスします。

http://192.168.1.20:3000

つながらない場合は、次の順で確認します。

1. ホストPC自身で http://localhost:3000 が開くか
2. docker compose ps で3000番ポートが公開されているか
3. 接続先IPアドレスが現在のホストPCのものか
4. Windows Defenderファイアウォールなどが3000番を遮断していないか
5. 端末同士が同じLANにいるか
6. ゲストWi-Fiの端末間通信禁止が有効になっていないか

自分のPCだけから使うなら、ポートをループバックへ限定できます。

ports:
  - "127.0.0.1:3000:8080"

LAN公開するなら認証を無効化しないでください。Open WebUIにはWEBUI_AUTH=Falseもありますが、これは個人PC内だけで使う単一ユーザー構成向けです。認証無効のままLANやインターネットへ公開するのは危険です。

インターネットへ直接ポート開放しない

3000番ポートをルーターでそのまま開放する構成はおすすめしません。TLS、アクセス制御、アップデート、総当たり攻撃対策まで考える必要があるためです。

外出先から使いたい場合は、まずTailscaleやWireGuardなどのVPN経由を検討します。リバースプロキシやトンネルを使う場合も、HTTPSと認証を必須にし、Ollamaの11434番ポートは外部へ直接公開しない方が安全です。

Open WebUIだけを入口にすれば、Ollama APIはCompose内部に閉じたままにできます。

安全に更新する

現在のイメージを確認します。

docker compose images

新しいイメージを取得し、コンテナを作り直します。

docker compose pull
docker compose up -d

不要になった古いイメージは、動作確認後に整理します。

docker image prune

本番運用や、更新による不具合を避けたい環境では、latestmainのような変動するタグではなく、確認済みのバージョンへ固定します。

services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:vX.Y.Z

更新前にはOpen WebUIのリリースノートを確認し、データをバックアップします。開発版の:devと本番データのボリュームを共有してはいけません。後方互換性のないデータベース変更が入る可能性があります。

よくあるエラーと切り分け

Open WebUIにモデルが表示されない

まず接続先がhttp://ollama:11434になっているか確認します。

docker compose exec open-webui curl http://ollama:11434/api/tags

その後、モデルが実際に入っているか確認します。

docker compose exec ollama ollama list

connection refusedになる

Ollamaが起動していないか、接続先が間違っています。

docker compose ps
docker compose logs --tail=200 ollama

depends_onは起動順を制御しますが、アプリが完全に利用可能になるまで待つ保証ではありません。起動直後だけ失敗する場合は、少し待ってOpen WebUIを再読み込みします。

推論が遅く、GPUを使っていないように見える

次を順番に確認します。

nvidia-smi
docker run --rm --gpus all ubuntu nvidia-smi
docker compose logs ollama

ホストでGPUが見える、Dockerから見える、Ollamaから見える、という3段階で切り分けると原因を絞れます。

モデルのダウンロードでディスクがいっぱいになる

モデルは名前付きボリュームへ保存されます。使用量を確認します。

docker system df -v
docker compose exec ollama ollama list

不要なモデルだけを削除します。

docker compose exec ollama ollama rm モデル名

原因が分からないままdocker system prune --volumesを実行すると、他のプロジェクトを含む未使用ボリュームまで削除する可能性があります。

再作成後にログアウトされる

.envWEBUI_SECRET_KEYが毎回変わっていないか確認します。固定値にして、.env自体は安全に保管します。

運用で使うコマンド一覧

# 起動
docker compose up -d

# 状態確認
docker compose ps

# ログを追う
docker compose logs -f

# モデル一覧
docker compose exec ollama ollama list

# 実行中モデル一覧
docker compose exec ollama ollama ps

# モデル取得
docker compose exec ollama ollama pull gemma3:4b

# 停止(データは残る)
docker compose down

# 更新
docker compose pull
docker compose up -d

まとめ

OllamaとOpen WebUIをComposeで動かすときに重要なのは、次の5点です。

コンテナ間の接続先は http://ollama:11434
モデルとOpen WebUIデータを別々のボリュームへ保存する
NVIDIA GPUはComposeのデバイス予約で渡す
11434番ポートは必要がなければホストへ公開しない
LAN・外部公開では認証とネットワーク境界を意識する

特に、localhostの意味とボリュームの削除条件を理解しておくと、接続トラブルとデータ消失の多くを避けられます。

まずCPU構成でOpen WebUIからモデルが見えるところまで確認し、その後GPU設定とLAN公開を1つずつ追加すると、問題が起きても原因を追いやすくなります。

参考資料