「Open WebUIやNginxも一緒に立ち上げて、開発環境を一発で整えたい」
そんな課題を抱えるインフラエンジニアやサーバー管理者は多い。OllamaはUbuntu Serverへの直接インストールが一般的だが、Docker Composeを使えばGPU対応コンテナとして起動でき、サービス間の連携や環境の再現性が大きく向上する。この記事では、GPUパススルーを含むcompose.ymlの書き方から、Open WebUI・Nginxを加えたマルチサービス構成、.envによる環境変数管理、ヘルスチェックと自動再起動の設定まで、実務に直結する内容をステップごとに解説する。
この記事のポイント
・deploy.resources.reservations.devicesブロックでNVIDIA GPUをコンテナへ割り当てる
・named volumeでモデルデータを永続化し、コンテナ削除後もモデルが消えない設計にする
・Open WebUI・Nginxをdepends_onとnetworkでOllamaに紐付けて一括起動できる
・healthcheckとrestart: alwaysで障害時の自動復旧を仕組みとして組み込める
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
Docker ComposeでOllamaを動かすメリットと適用場面
OllamaはLinuxホストに直接インストールして運用するのが最もシンプルな構成だ。では、あえてDocker Composeを使うのはどんな場面か。3つの観点で整理する。1. 環境の再現性が上がる
compose.ymlと.envファイルさえあれば、別のUbuntuホストでも同じ構成を即座に再現できる。Ubuntu ServerへのOllama直接インストールは手軽だが、チームが増えると「あの設定どうやったっけ」という状況が起きやすい。Dockerならcompose.ymlがそのまま構成ドキュメントになる。2. 複数サービスの起動順序と依存を管理しやすい
OllamaとOpen WebUI、Nginxを組み合わせる場合、起動順序の管理が必要になる。Docker Composeのdepends_onとhealthcheckを組み合わせれば、Ollamaが完全に起動してからOpen WebUIを立ち上げる、という制御が宣言的に書ける。手動でsystemdユニットの起動順を管理するより確実だ。3. 将来のKubernetes移行への橋渡しになる
compose.ymlはKubernetes manifestに近い構造を持つ。コンテナ化して運用した実績があれば、本番スケールへ移行するときの障壁が下がる。開発・検証環境をDockerで動かし、本番はK8sで動かすという段階的な展開が現実的になる。適用場面としては、「開発・検証環境を素早く構築したい」「チームメンバーが同じ構成を手元で動かす必要がある」「将来的にコンテナ基盤への移行を見込んでいる」といったケースが典型的だ。
前提環境を確認する
Docker ComposeでOllamaのGPU機能を使うには、Docker Engine本体に加えてNVIDIA Container Toolkitが必要だ。順番に確認する。1. Docker Engineのインストール確認
Dockerがすでに入っているか確認する。# Dockerバージョン確認 $ docker --version Docker version 26.1.4, build 5650f9b # Docker Composeバージョン確認(プラグイン形式) $ docker compose version Docker Compose version v2.27.1
2. NVIDIA Container Toolkitの導入
GPUを使う場合、NVIDIA Container Toolkitが必要だ。すでに導入済みの場合はスキップしてよい。# GPGキーとリポジトリを追加 $ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg $ curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \ | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list # インストール $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit # DockerランタイムへNVIDIAを登録してデーモンを再起動 $ sudo nvidia-ctk runtime configure --runtime=docker $ sudo systemctl restart docker # コンテナ内でGPUが見えるか動作確認 $ docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi
基本的なcompose.ymlを書いてOllamaを起動する
まずOllamaだけをDocker Composeで起動する最小構成から始める。動作を確認してからサービスを追加していく順番が失敗しにくい。1. 作業ディレクトリとcompose.ymlの準備
# 作業ディレクトリを作成して移動 $ mkdir ~/ollama-compose && cd ~/ollama-compose # compose.ymlを新規作成 $ vim compose.yml
2. GPUパススルーを含むcompose.ymlの書き方
以下が最小構成のcompose.ymlだ。services: ollama: image: ollama/ollama:latest container_name: ollama restart: always ports: - "11434:11434" volumes: - ollama_data:/root/.ollama deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] environment: - OLLAMA_HOST=0.0.0.0 volumes: ollama_data:
・`deploy.resources.reservations.devices`ブロックがGPUパススルーの核心部分。`driver: nvidia`と`capabilities: [gpu]`が必須
・`volumes`の`ollama_data`はnamed volume。コンテナを削除してもモデルデータが消えない
・`OLLAMA_HOST=0.0.0.0`でコンテナ外からのAPIアクセスを受け付ける設定にする
CPUのみで動かす場合は`deploy`ブロック全体を削除する。`docker compose up`はdeploy.resourcesをswarmモードなしでも処理できるが、toolkitが未導入の状態でGPUブロックを書くとエラーになるので注意が必要だ。
3. 起動と動作確認
# バックグラウンドで起動 $ docker compose up -d # コンテナのログを確認 $ docker compose logs -f ollama # APIが応答するか確認(modelsが空配列なら正常) $ curl http://localhost:11434/api/tags {"models":[]} # モデルをダウンロード(コンテナ内でollamaコマンドを実行) $ docker compose exec ollama ollama pull llama3.3:8b-instruct-q4_K_M # 推論テスト $ docker compose exec ollama ollama run llama3.3:8b-instruct-q4_K_M "Linuxとは何か一言で"
マルチサービス構成に拡張する
OllamaだけでなくOpen WebUIとNginxも追加し、チームで使えるマルチサービス構成を作る。サービス名がそのままDockerの内部DNS名になるため、IPアドレスを管理する必要がない点が大きな利点だ。1. Open WebUIをサービスとして追加する
compose.ymlのservicesブロックに追記する。Ollamaにhealthcheckとnetworkブロックも加えている。services: ollama: image: ollama/ollama:latest container_name: ollama restart: always volumes: - ollama_data:/root/.ollama deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] environment: - OLLAMA_HOST=0.0.0.0 networks: - llm_net healthcheck: test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] interval: 30s timeout: 10s retries: 3 start_period: 40s webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui restart: always ports: - "3000:8080" volumes: - webui_data:/app/backend/data environment: - OLLAMA_BASE_URL=http://ollama:11434 networks: - llm_net depends_on: ollama: condition: service_healthy networks: llm_net: volumes: ollama_data: webui_data:
`depends_on`の`condition: service_healthy`を使うと、OllamaのhealthcheckがOKになってからOpen WebUIを起動するという順序制御が確実になる。
2. Nginxでリバースプロキシを加える
チームに対してHTTPで提供するためにNginxを追加する。まずNginx設定ファイルを用意する。# Nginx設定ディレクトリを作成 $ mkdir -p nginx/conf.d # Nginx設定ファイルを作成 $ cat > nginx/conf.d/ollama.conf << 'EOF' server { listen 80; server_name _; location / { proxy_pass http://webui:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_read_timeout 300s; } location /api/ { proxy_pass http://ollama:11434; proxy_set_header Host $host; proxy_read_timeout 300s; } } EOF
nginx: image: nginx:alpine container_name: nginx restart: always ports: - "80:80" volumes: - ./nginx/conf.d:/etc/nginx/conf.d:ro networks: - llm_net depends_on: - webui
3. 全サービスを一括起動して確認する
# 全サービスを一括起動 $ docker compose up -d # 各コンテナのステータスを確認 $ docker compose ps NAME IMAGE STATUS nginx nginx:alpine Up open-webui ghcr.io/open-webui/open-webui:main Up ollama ollama/ollama:latest Up (healthy) # ブラウザで http://サーバーIP/ にアクセスしてOpen WebUIが表示されることを確認
.envファイルで環境変数とモデルパスを管理する
チームで使う場合、設定値をcompose.yml内に直接書くのは避けた方がいい。.envファイルに切り出すことで、環境ごとに設定を切り替えやすくなる。1. .envファイルの書き方
# .env ファイル(compose.ymlと同じディレクトリに配置) WEBUI_PORT=3000 NGINX_PORT=80 WEBUI_SECRET_KEY=your-secret-key-here
services: webui: ports: - "${WEBUI_PORT}:8080" environment: - OLLAMA_BASE_URL=http://ollama:11434 - WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY} nginx: ports: - "${NGINX_PORT}:80"
2. モデルストレージを外付けディスクへ切り替える
大容量モデルを扱う場合、named volumeではなくホスト側の特定ディレクトリをマウントする方法が柔軟だ。# .envに追記 OLLAMA_MODELS_PATH=/mnt/nvme/ollama # compose.ymlのollamaサービスvolumesを変更 services: ollama: volumes: - ${OLLAMA_MODELS_PATH}:/root/.ollama # volumesブロックのollama_data定義は削除してよい
ヘルスチェックと自動再起動を設定する
本番に近い環境で運用するなら、障害時の自動復旧を仕組みとして組み込んでおきたい。1. healthcheckブロックの書き方と各パラメータの意味
Ollamaの場合、`/api/tags`エンドポイントへのGETリクエストが成功するかどうかをhealthcheckの判定に使う。services: ollama: healthcheck: test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] interval: 30s # チェック間隔(デフォルト30s) timeout: 10s # タイムアウト(デフォルト30s) retries: 3 # 失敗許容回数(デフォルト3) start_period: 40s # 起動後の猶予期間(この間の失敗はretriesに含まれない)
2. restartポリシーの選択
`restart`ポリシーには4つの選択肢がある。・`no`(デフォルト): コンテナが停止しても再起動しない
・`always`: 停止理由に関わらず常に再起動する。Dockerデーモン再起動後も自動起動する
・`on-failure`: 終了コードが0以外の場合のみ再起動する
・`unless-stopped`: `docker compose stop`で明示的に停止した場合を除いて常に再起動する
常時起動が必要なサービスには`always`か`unless-stopped`を使う。`unless-stopped`は手動メンテナンス時に`docker compose stop`で一時停止できる点が`always`との違いだ。
注意点として、ホスト上のOllamaのsystemdサービスが動いていると11434番ポートが競合する。Docker Composeで運用するときはsystemd側のOllamaサービスを停止・無効化しておく必要がある。
よくあるトラブルと対処法
実際にDocker ComposeでOllamaを動かしていると、いくつかの典型的なトラブルに遭遇する。対処法をまとめる。GPUが認識されない(could not select device driver エラー)
このエラーはNVIDIA Container Toolkitが正しく設定されていないか、Dockerデーモンが再起動されていない場合に起きる。# Dockerデーモンを再起動してからGPUが見えるか確認 $ sudo systemctl restart docker $ docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi # nvidia-container-toolkitがインストールされているか確認 $ dpkg -l | grep nvidia-container-toolkit ii nvidia-container-toolkit 1.15.0-1 ...
ポートが既に使用中(Bind for 0.0.0.0:11434 failed エラー)
ホスト上でOllamaのsystemdサービスが動いていると、11434番ポートが競合する。# 競合プロセスを確認 $ sudo ss -tlnp | grep 11434 LISTEN 0 4096 0.0.0.0:11434 0.0.0.0:* users:(("ollama",pid=1234,fd=7)) # OllamaのsystemdサービスをDockerと競合しないよう停止・無効化 $ sudo systemctl stop ollama $ sudo systemctl disable ollama # その後 docker compose up -d を再実行 $ docker compose up -d
Open WebUIがOllamaに接続できない(Connection refused)
`OLLAMA_BASE_URL`に`localhost`や`127.0.0.1`を指定しているケースで起きる。コンテナ間通信ではサービス名を使う必要がある。# 誤った設定(localhostはOpen WebUIコンテナ自身を指す) # OLLAMA_BASE_URL=http://localhost:11434 ← NG # 正しい設定(サービス名で指定する) OLLAMA_BASE_URL=http://ollama:11434 # コンテナ内からollamaコンテナへの疎通確認 $ docker compose exec webui curl -f http://ollama:11434/api/tags {"models":[...]}
社内での活用シナリオについては社内でChatGPTが使えないときのローカルLLM選択肢も参考になる。コンテナで構築したOllamaを社内ネットワークにどう組み込むか、導入の背景を整理したい場合はそちらを読んでほしい。
まとめ
Docker ComposeでOllamaを起動する方法を、GPUパススルー・マルチサービス構成・環境変数管理・ヘルスチェックの順に解説した。ベアメタルへの直接インストールと比べると初期設定の手間は増えるが、チームでの環境共有や設定の再現性という面で明確なメリットがある。compose.ymlという単一ファイルに構成が集約されるので、構成変更の追跡やレビューもしやすくなる。| 項目 | コマンド・設定例 | ポイント |
|---|---|---|
| 起動 | docker compose up -d | バックグラウンドで全サービス一括起動 |
| GPUパススルー | deploy.resources.reservations.devices | driver: nvidia、capabilities: [gpu]が必須 |
| モデル取得 | docker compose exec ollama ollama pull llama3.3:8b-instruct-q4_K_M | コンテナ内でollamaコマンドを実行する |
| コンテナ間通信 | OLLAMA_BASE_URL=http://ollama:11434 | サービス名がDNS名として使える |
| データ永続化 | ollama_data:/root/.ollama(named volume) | コンテナ削除後もモデルが保持される |
| ヘルスチェック | test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] | start_period: 40sで起動猶予を設ける |
| 自動再起動 | restart: always | unless-stoppedなら手動停止が可能 |
OllamaのDocker運用をハンズオンで体験する
この記事で解説したDocker Composeによるコンテナ構成・GPUパススルー・マルチサービス連携は、読むだけでは習得しにくい部分が多い。実機GPU環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Ollamaのトラブルシューティングガイド|接続エラー・モデル読み込み失敗・GPU認識問題をLinuxで解決する手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます