OllamaをDocker Composeで起動する方法|GPUパススルー・マルチサービス構成・環境変数管理で開発環境を整備する手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)ローカルLLM > OllamaをDocker Composeで起動する方法|GPUパススルー・マルチサービス構成・環境変数管理で開発環境を整備する手順
「DockerでOllamaを動かしたいが、GPUパススルーをcompose.ymlにどう書けばいいか分からない」
「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で障害時の自動復旧を仕組みとして組み込める


OllamaをDocker Composeで起動する方法|GPUパススルー・マルチサービス構成・環境変数管理で開発環境を整備する手順

「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

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

`docker compose`(スペース区切り)のプラグイン形式が動く必要がある。古い`docker-compose`コマンド(ハイフン区切り)は非推奨になっている。v2.20以降を想定して本記事の手順を書いているので、古いバージョンの場合はアップグレードを先に済ませてほしい。

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

`nvidia-smi`の出力にGPU情報が表示されれば設定は完了だ。CPUのみで運用する場合はこの手順はスキップしてよい。その場合、後述するcompose.ymlの`deploy`ブロックも不要になる。

基本的な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:

ポイントを3つ押さえておく。

・`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とは何か一言で"

`/api/tags`が`{"models":[]}`を返せばOllamaは正常起動している。モデルのダウンロードは`docker compose exec ollama ollama pull`で行う。ホスト上の`ollama pull`コマンドとは別物なので混同しないようにしたい。どのモデルがチームの用途に合うか迷ったときはローカルLLMのモデル比較・使い分けガイドで確認してほしい。

マルチサービス構成に拡張する

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:

`OLLAMA_BASE_URL=http://ollama:11434`のホスト名部分が`ollama`になっている点が重要だ。Docker Composeの内部ネットワークでは、サービス名がそのままDNS名として使える。`localhost`や実IPを指定するとコンテナ外を向いてしまい接続できない。

`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

compose.ymlのservicesブロックにnginxを追記する。

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

これで`http://サーバーIP/`にアクセスするとOpen WebUIが表示され、`/api/`へのリクエストはOllamaに転送される構成になる。HTTPS化や認証の追加については社内ネットワーク公開のベストプラクティスを押さえた上で検討してほしい。

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が表示されることを確認

`ollama`コンテナのSTATUSが`Up (healthy)`になっていれば、healthcheckが通っている状態だ。

.envファイルで環境変数とモデルパスを管理する

チームで使う場合、設定値をcompose.yml内に直接書くのは避けた方がいい。.envファイルに切り出すことで、環境ごとに設定を切り替えやすくなる。

1. .envファイルの書き方

# .env ファイル(compose.ymlと同じディレクトリに配置) WEBUI_PORT=3000 NGINX_PORT=80 WEBUI_SECRET_KEY=your-secret-key-here

compose.ymlでは`${変数名}`形式で参照する。

services: webui: ports: - "${WEBUI_PORT}:8080" environment: - OLLAMA_BASE_URL=http://ollama:11434 - WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY} nginx: ports: - "${NGINX_PORT}:80"

.envファイルはGitにコミットしないこと。`.gitignore`に`.env`を追加しておき、代わりに`.env.example`(実際の値を空にしたサンプル)をコミットするのがチーム運用の定番だ。

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定義は削除してよい

外付けNVMeや大容量HDDのマウントポイントを指定すれば、named volumeのサイズ制限を気にせずモデルを格納できる。NASをNFSマウントして共有モデルストレージにする構成もこの応用だ。ただしNFS越しのモデルロードは速度に影響が出やすいので、推論サーバーはローカルNVMeを使う方が実務では安定する。

ヘルスチェックと自動再起動を設定する

本番に近い環境で運用するなら、障害時の自動復旧を仕組みとして組み込んでおきたい。

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に含まれない)

`start_period`はコンテナ起動直後の猶予時間だ。Ollamaの初期化に時間がかかる環境では40秒~60秒程度に設定するとよい。この期間中にhealthcheckが失敗してもretriesのカウントに含まれないので、誤った`unhealthy`判定を防げる。

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 ...

`dpkg -l`で出力がない場合はNVIDIA Container Toolkitが未インストールだ。前述の手順でインストールしてからDockerデーモンを再起動する。

ポートが既に使用中(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":[...]}

webコンテナ内からollamaコンテナへcurlが通れば、ネットワーク設定は正常だ。両サービスが同じnetwork(`llm_net`等)に属していることを合わせて確認する。

社内での活用シナリオについては社内で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ハンズオン形式で実施しています。

>> ローカルAIマスターセミナーの詳細を確認する
ローカルLLMの構築・運用に関する関連記事もあわせて参考にしてください。

Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。