ローカルLLM構築による機密情報を守るセキュアな生成AI活用環境

完全閉域網で動く!機密情報を守るローカルLLM構築|OllamaとDockerで作るセキュアな社内AI基盤

この記事は急速に進化する技術について解説しています。最新情報は公式ドキュメントをご確認ください。

約18分で読めます
文字サイズ:
完全閉域網で動く!機密情報を守るローカルLLM構築|OllamaとDockerで作るセキュアな社内AI基盤
目次

この記事の要点

  • 機密情報の外部漏洩リスクをゼロに
  • 完全閉域網でのLLM運用を実現
  • OllamaとDockerによるセキュアな構築例

導入:データ主権を取り戻すための技術的決断

企業における生成AI活用が進む一方で、多くのCTOやインフラエンジニアが頭を抱えている問題があります。それは「機密情報の漏洩リスク」です。SaaS型のAIサービスは非常に強力ですが、顧客データや独自の技術情報を外部のサーバーへ送信することに対し、コンプライアンス部門が首を縦に振らないケースは枚挙にいとまがありません。

例えば、設計図面や特殊な配合データといったコアコンピタンスに関わる情報を扱う製造業や研究機関などでは、外部クラウドの利用が厳しく制限されている環境も珍しくありません。しかし、現場のエンジニアや研究者からは「開発効率を飛躍させるためにAIを業務に組み込みたい」という切実な要望が日々上がってきます。

この強固なセキュリティ要件と業務効率化のジレンマを解消する現実的な解が、「ローカルLLM(大規模言語モデル)」による社内専用APIの構築です。

本記事では、インターネットへのデータ流出を物理的・論理的に完全に遮断した閉域網内で、OpenAI互換の生成AI APIを構築するための技術仕様を解説します。これは単に個人のPCでモデルをテスト起動するようなホビーユースの話ではありません。開発チーム全体が安全に利用できる「社内標準インフラ」としての堅牢性と、監査可能な管理機能を備えた本格的なシステムの実装アプローチです。

使用する主軸の技術スタックは、推論エンジンとしてのOllama、認証とルーティングを担うLiteLLM、そしてこれらをシームレスにオーケストレーションするDockerです。
最近のOllamaは目覚ましい進化を遂げており、単なるテキスト生成にとどまらず、高度なOCRモデルやコーディングに特化した強力なモデルのサポートを拡充しています。また、基盤となるDocker環境も継続的なセキュリティ更新によってエンタープライズ水準の信頼性を高めています。これらを適切に組み合わせることで、最新の商用APIに匹敵する利便性を維持しながら、組織の完全なデータ主権を両立させることが可能になります。

組織の機密データを確実に守りながら、AIの恩恵を最大限に引き出すためのセキュアなAI基盤構築のステップを紐解いていきましょう。

1. 社内ローカルAPIアーキテクチャ概要

1. 社内ローカルAPIアーキテクチャ概要 - Section Image

本記事で構築するシステムの全体像を明確に定義します。最大の目的は、外部インターネットへの依存を完全に排除しつつ、社内ネットワーク(Intranet)内に存在するアプリケーションや開発者に対して、標準的かつスケーラブルなAIインターフェースを提供することです。機密性の高い業務データを扱う以上、完全閉域網での動作は譲れない要件となります。

システム構成図とデータフロー

アーキテクチャは、責任を明確に分離した3層構造で設計します。システム全体を俯瞰し、技術的な課題を構造的に捉えることが重要です。

  1. プレゼンテーション層(Client): 社内チャットツール、IDEプラグイン、各種業務アプリケーションなどが該当します。これらはすべてOpenAI互換のHTTPリクエストを送信するよう構成します。
  2. ゲートウェイ層(LiteLLM Proxy): クライアントからのリクエストを一手に受け付け、APIキーによる厳格な認証、アクセスログの記録、そしてレートリミットの適用を担います。システム全体のセキュリティとガバナンスを担保する要石となる層です。
  3. 推論エンジン層(Ollama): 実際にLLMをメモリにロードし、トークン生成の演算を行います。GPUリソースを直接制御し、ハードウェアの性能を最大限に引き出す役割を持ちます。

データフローは極めてシンプルかつセキュアです。クライアントから送信されたプロンプトは、閉域網内のゲートウェイ層で正当性を検証された後、推論エンジン層へ安全に転送されます。生成された回答テキストは逆の経路を辿ってクライアントへ返却されます。この一連のプロセスにおいて、業務データがインターネット(外部ネットワーク)へ流出することは構造上一切ありません。

採用技術スタックの選定理由

  • Ollama: LlamaやMistralなどのオープンモデルをローカル環境で軽量に動作させ、REST APIを提供するランタイムとして現在最も成熟した選択肢です。近年、LLMはMoE(Mixture of Experts)アーキテクチャの導入や、膨大なコンテキスト長への対応、マルチモーダル化など急速な進化を遂げています。Ollamaはこれらの最新アーキテクチャにも迅速に追従しています。さらに、モデルの量子化(Quantization)をサポートしているため、限られたVRAM容量のGPU環境であっても実用的な推論速度を叩き出せる点が極めて優秀です。英語タスクには最新の汎用モデルを用い、日本語の精度が求められるタスクには日本語特化の派生モデルやQwen系モデルへ切り替えるといった、要件に応じた柔軟な運用も容易に実現できます。
  • LiteLLM: 多種多様なLLMバックエンドを、デファクトスタンダードであるOpenAI互換のAPI形式に統一する強力なプロキシサーバーです。特筆すべきは、データベース(RedisやPostgreSQL)と連携することで、高度なユーザー管理機能とコストトラッキング機能を提供できる点にあります。企業ユースにおいては「誰が、いつ、どのモデルを、どれだけのトークン消費で利用したか」という監査証跡の取得が必須となります。そのため、Ollamaを直接公開するのではなく、LiteLLMを前段に配置する構成を強く推奨します。

セキュリティ境界の定義

本システムにおけるセキュリティ境界(Trust Boundary)は、ゲートウェイ層の入口に厳格に設定します。ここより内側(推論エンジンが稼働する領域)は信頼されたゾーンとして扱いますが、外側からのアクセスは全て疑って検証するゼロトラスト(Zero Trust)の思想を基本設計とします。したがって、ゲートウェイ層におけるTLS終端による通信の暗号化と、強固なAPIキー認証の実装は、妥協の許されない必須要件となります。

2. APIサーバー構築と環境仕様

ここでは、APIサーバーをホストするためのインフラ要件と、Docker Composeを用いた構築手順を仕様化します。システムの安定性とセキュリティを両立させるため、ホスト環境には最新のDocker EngineとDocker Composeを導入することを前提とします。再現性を担保するため、以下の構成ファイルを使用し、堅牢な基盤を構築します。

GPUリソースの割り当て要件

ローカルLLMの実用性は、基盤となるGPUスペックに大きく依存します。社内共有APIとして複数人の同時リクエストを捌く場合、コンシューマー向けGPUであればNVIDIA GeForce RTX 4090 (24GB VRAM)、サーバー向けであればNVIDIA L4やA100などが推奨されます。

  • VRAM要件: 7Bパラメータのモデル(4bit量子化)で約6GB、70Bクラスのモデルで約40GBを消費します。コンテキスト長(一度に処理できるトークン数)を長く取る場合、さらにメモリが必要となるため、余裕を持ったサイジングが重要です。
  • ドライバ: ホストOSには最新のNVIDIA Driverとnvidia-container-toolkitがインストールされていることを前提とします。特に最新のDocker環境ではセキュリティ更新が頻繁に行われるため、ドライバとの互換性を定期的に確認することが安定稼働の鍵となります。

Docker Composeによるデプロイ仕様

以下のdocker-compose.ymlは、OllamaとLiteLLM、そして監査ログ保存用のPostgreSQLを連携させる構成です。最新のDocker Compose環境(v2系以降)での動作を想定しており、レガシーな機能に依存しないセキュアな設計となっています。

version: '3.8'

services:
  # 推論エンジン
  ollama:
    image: ollama/ollama:latest
    container_name: internal-llm-engine
    ports:
      - "11434:11434"
    volumes:
      - ./ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    restart: always
    environment:
      - OLLAMA_HOST=0.0.0.0

  # 監査ログ用データベース
  db:
    image: postgres:15-alpine
    container_name: llm-audit-db
    environment:
      POSTGRES_USER: litellm_user
      POSTGRES_PASSWORD: secure_password_change_me
      POSTGRES_DB: litellm_logs
    volumes:
      - ./pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U litellm_user"]
      interval: 5s
      timeout: 5s
      retries: 5

  # 認証・プロキシ層
  litellm:
    image: ghcr.io/berriai/litellm:main-latest
    container_name: internal-ai-gateway
    ports:
      - "4000:4000"
    depends_on:
      ollama:
        condition: service_started
      db:
        condition: service_healthy
    environment:
      - DATABASE_URL=postgresql://litellm_user:secure_password_change_me@db:5432/litellm_logs
      - LITELLM_MASTER_KEY=sk-admin-secret-key-change-me
      - STORE_MODEL_IN_DB=True
    volumes:
      - ./litellm_config.yaml:/app/config.yaml
    command: ["--config", "/app/config.yaml", "--detailed_debug"]

この構成により、http://localhost:4000がアプリケーション向けのエンドポイントとなり、http://localhost:11434(Ollama直接)は外部から遮断するネットワーク設計が可能になります。また、LiteLLMをプロキシとして挟むことで、将来的に完全閉域網のOllamaだけでなく、外部のChatGPTなどのAPIとルーティングを統合するハイブリッド環境への移行も、アプリケーション側のコード変更なしで対応できる利点があります。

モデルロード設定とメモリ管理

Ollamaは初回リクエスト時にモデルをロードする仕様ですが、業務利用においては応答遅延を防ぐため、あらかじめロードしておくことが望ましいです。コンテナ起動後に以下のコマンドを実行し、モデルをプル(またはインポート)して準備を整えます。

# コンテナ内でモデルを実行(インターネット接続がある場合)
docker exec -it internal-llm-engine ollama pull Llamaモデル

# 完全オフライン環境の場合
# 事前にダウンロードしたモデルファイル(.gguf)をModelfile経由でインポートする手順が必要

完全オフライン環境で運用する場合、インターネットに接続された別端末で.gguf形式のモデルファイルをダウンロードし、USBメモリ等の物理媒体でサーバーに持ち込む必要があります。その後、独自のModelfileを作成し、ollama createコマンドを用いてローカル環境にモデルを構築することで、機密情報を外部に一切出さないセキュアな推論環境が完成します。メモリの枯渇を防ぐため、稼働させるモデルのパラメータ数とVRAMの空き容量を常に監視する仕組みを導入することも推奨されます。導入後の運用まで見据えた丁寧な設計が、実務において真に役立つシステムを生み出します。

3. 認証・認可ミドルウェア仕様

3. 認証・認可ミドルウェア仕様 - Section Image

Ollama自体には認証機能が存在しません。そのまま社内公開すれば、誰でも無制限にGPUリソースを消費できてしまいます。最新のDocker Engine(v29.1など)を用いてセキュアなコンテナ環境を構築する場合でも、LiteLLMプロキシを用いた認証層の実装は、ガバナンスの観点から必須です。

LiteLLMプロキシの設定

litellm_config.yamlにて、Ollamaへのルーティングとモデル定義を行います。

model_list:
  - model_name: gpt-5.2 # クライアントが指定する汎用モデル名(エイリアス)
    litellm_params:
      model: ollama/llama3 # 実際に動作するバックエンドモデル
      api_base: http://ollama:11434
      api_key: "ignore" # Ollamaはキー不要だがLiteLLMの仕様上ダミーが必要
  - model_name: gpt-5.3-codex # クライアントが指定するコーディング特化モデル名
    litellm_params:
      model: ollama/codellama
      api_base: http://ollama:11434
      api_key: "ignore"

general_settings:
  master_key: sk-admin-secret-key-change-me
  alerting: ["slack"] # エラー時の通知先などを設定可能

この設定の妙は、クライアント側がAPIリクエストでgpt-5.2gpt-5.3-codexといったOpenAIの最新モデル名を指定しても、裏側ではローカルで稼働するLlamaなどのモデルが応答する点にあります。OpenAI APIではレガシーモデル(GPT-4oなど)が廃止され、GPT-5.2等の新モデルへの移行が進んでいます。このプロキシ構成を採用すれば、最新のOpenAI API仕様に合わせたアプリケーションのコードを書き換えることなく、接続先URLを変更するだけで完全なローカルLLM環境へ切り替えることが可能になります。

APIキーの発行と管理

LiteLLMの管理APIを使用して、部門やプロジェクトごとのAPIキーを発行します。curlコマンドで以下のように実行します。

curl -X POST 'http://localhost:4000/key/generate' \
-H 'Authorization: Bearer sk-admin-secret-key-change-me' \
-H 'Content-Type: application/json' \
-d '{
    "models": ["gpt-5.2", "gpt-5.3-codex"], 
    "metadata": {"user": "dev-team-alpha", "project": "code-gen"}
}'

レスポンスとしてsk-litellm-...から始まるキーが返却されます。これを各開発チームに配布します。modelsの配列に使用を許可するモデル名(汎用タスク向け、コーディング特化向けなど)を明記し、metadataフィールドに部署名や用途を含めておきます。これにより、後述するログ監査時に「どの部署が、どの用途で、どれくらいリソースを消費しているか」を正確に追跡できます。

アクセスログの監査仕様

PostgreSQLには、リクエストごとのプロンプト、応答トークン数、処理時間、使用されたAPIキー情報が詳細に記録されます。機密情報保護の観点から、プロンプト内容自体のログ保存を無効化したい場合は、LiteLLMの設定でlitellm_disable_logging: trueとすることも可能です。

しかし、セキュリティ監査や利用実態の把握(例えば、コーディング支援モデルが適切に活用されているかの検証など)のためにはログを保持し、データベースへのアクセス権を厳格に管理する運用を推奨します。また、Docker環境のアップデート(v29系への移行など)を行う際は、データベースボリュームの永続化設定が正しく引き継がれているか、事前の互換性確認を忘れないようにしましょう。

4. エンドポイントリファレンス:Chat Completions

開発者が最も頻繁に利用するチャット補完エンドポイントPOST /v1/chat/completionsの仕様を解説します。このエンドポイントは、社内システムや外部アプリケーションからAIモデルを呼び出す際の標準的なインターフェースとして機能します。基本的にはOpenAI APIの仕様と完全互換ですが、ローカル環境でモデルを稼働させるからこその特有の挙動や設定が存在するため、正確な理解が求められます。

リクエストパラメータ詳解

  • model (string, 必須): litellm_config.yamlなどで定義したモデルのエイリアス名(例: gpt-5.2llama3)。OpenAI公式APIでは2026年2月にGPT-4oなどのレガシーモデルが廃止され、標準モデルがGPT-5.2、コーディング特化モデルがGPT-5.3-Codexへと移行しています。APIプロキシを利用してローカルモデルとクラウドモデルを併用する場合、古いモデル名を指定してエラーにならないよう、ルーティング設定を最新のモデル体系に合わせて更新しておく必要があります。
  • messages (array, 必須): システムプロンプトやユーザーの入力、AIの返答といったチャット履歴を含むメッセージオブジェクトの配列です。
  • temperature (number, 任意): 0.0〜2.0の範囲で指定します。社内ドキュメントに基づく回答やコード生成など、決定論的で正確な出力が必要な業務タスクでは、この値を0または0.1に設定してハルシネーションのリスクを最小限に抑えます。
  • stream (boolean, 任意): trueに設定すると、Server-Sent Events (SSE) 形式でトークンが逐次返却されます。生成の待ち時間を体感的に短縮できるため、UX向上の観点からチャットUIを構築する際には必須の実装要件となります。

ローカル特有のパラメータと注意点

Ollamaバックエンドを利用する場合、OpenAIの標準仕様には含まれない追加パラメータをextra_bodyなどを通じて渡すことで、モデルの挙動を細かく制御できるケースがあります。しかし、将来的なシステム拡張や他のモデルへの切り替え時の互換性を重視するのであれば、可能な限り標準パラメータの利用に留めるべきです。

特にインフラ設計において注意すべきはコンテキストウィンドウ(num_ctx)の扱いです。Ollamaのデフォルト設定では2048トークンや4096トークンに制限されていることが多いです。長大な社内ドキュメントを読み込ませるRAG(検索拡張生成)システムを構築する場合、Ollama起動時の環境変数OLLAMA_NUM_CTXModelfileを使用して、あらかじめこの上限値を拡張しておく必要があります。APIリクエストのたびに動的に変更するのはパフォーマンスへの悪影響が大きいため、インフラ側で固定値を定義するアプローチを推奨します。

さらに、OllamaをDockerコンテナとして運用する際の基盤環境にも注意を払う必要があります。2026年2月時点の最新のDocker Engine(v29系)などでは、セキュリティ強化やアーキテクチャ刷新に伴い一部のレガシー機能が削除されています。そのため、コンテナの起動ワークフローやGPUリソースのパススルー設定が最新のDocker環境と互換性があるか、デプロイ前に検証を行ってシステムの安定稼働を担保することが重要です。

5. クライアント実装サンプルコード

構築したローカルAPIに接続するための具体的なコードスニペットを提供します。ここではPythonの標準的な openai ライブラリを使用した例を示します。

ローカルLLMを導入する最大の利点は、完全閉域網でありながらクラウドのAPIと全く同じインターフェースを利用できる点にあります。これにより、既存のアプリケーションコードを大幅に書き換えることなく、セキュアな社内AI基盤へとシームレスに切り替えることが可能です。

Python (OpenAI SDK) での接続例

既存のコードから変更すべき点は、エンドポイントを指定する base_url と、認証用の api_key の2点のみです。

OpenAI APIのエコシステムでは、2026年2月にGPT-4o等のレガシーモデルが廃止され、GPT-5.2が新たな標準モデルへと移行しました。このようなクラウド側のモデル移行が発生しても、プロキシとなるLiteLLM側で gpt-5.2 というモデル名(エイリアス)を社内のローカルモデル(Ollamaで動くLlamaなど)にマッピングしておけば、クライアント側のコードはクラウドの最新仕様に合わせたまま、実際にはローカル環境で安全に処理させることができます。

以下は、ストリーミングレスポンスを活用した実用的な実装例です。

import os
from openai import OpenAI

# セキュリティ観点から、環境変数から設定を読み込む運用を推奨します
# export OPENAI_BASE_URL="http://localhost:4000"
# export OPENAI_API_KEY="sk-litellm-user-key..."

client = OpenAI(
    base_url=os.getenv("OPENAI_BASE_URL", "http://localhost:4000"),
    api_key=os.getenv("OPENAI_API_KEY", "sk-litellm-user-key")
)

try:
    response = client.chat.completions.create(
        model="gpt-5.2",  # LiteLLMでローカルモデルにマッピングされた最新の標準エイリアス
        messages=[
            {"role": "system", "content": "あなたは熟練したPythonエンジニアです。"},
            {"role": "user", "content": "フィボナッチ数列を生成する効率的な関数を書いて。"}
        ],
        temperature=0.7,
        stream=True  # ストリーミングを有効化して体感速度を向上
    )

    print("AIの回答:")
    for chunk in response:
        if chunk.choices[0].delta.content is not None:
            print(chunk.choices[0].delta.content, end="", flush=True)
    print()  # 改行

except Exception as e:
    print(f"接続エラーが発生しました: {e}")

また、コーディング特化のタスクを実行する場合は、モデル指定を gpt-5.3-codex のような開発タスクに最適化されたモデルのエイリアスに切り替える運用も考えられます。用途に応じて最適なローカルモデルへリクエストをルーティングする設計が、柔軟で拡張性の高いAI基盤の要となります。

LangChainからの接続設定

LangChainを使用して高度なRAG(検索拡張生成)システムや自律型エージェントを構築している場合も、同様に ChatOpenAI クラスをそのまま利用できます。

Ollamaを直接呼び出す ChatOllama クラスを使用することも技術的には可能ですが、システム全体を俯瞰したアーキテクチャ設計としてはお勧めしません。LiteLLMをプロキシとして経由し、ChatOpenAI クラスからアクセスする構成を採用することで、APIキーによる一元的な認証、詳細なリクエストログの管理、トークン使用量の監視といった、本番運用に不可欠な恩恵を享受できるからです。

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="http://localhost:4000",
    api_key="sk-litellm-user-key",
    model="gpt-5.2",
    temperature=0
)

result = llm.invoke("社内セキュリティガイドラインの要約を作成して")
print(result.content)

このように、エンドポイントのURLとAPIキーをローカル環境に向けるだけで、高度な推論機能を備えたアプリケーションを、機密情報を一切外部に出すことなく安全に運用できます。Dockerコンテナ群(最新のEngine環境など)で構築された堅牢なバックエンドと組み合わせることで、開発効率とセキュリティ要件を高い次元で両立させた理想的な環境が実現します。

6. エラーハンドリングとトラブルシューティング

4. エンドポイントリファレンス:Chat Completions - Section Image 3

ローカル環境での運用において、避けて通れないのがリソース制約によるエラーです。運用担当者が直面しやすい問題とその対処法を定義します。また、基盤となるDocker環境の保守も安定稼働には欠かせません。

GPUメモリ不足時の挙動と対策

最も頻発するのは、複数のリクエストが重なった際や、大きなモデルをロードした際のOOM(Out Of Memory)です。

  • 現象: APIがタイムアウトする、またはDockerコンテナが強制終了する。
  • 対策:
    1. Ollamaの並列数制限: 環境変数OLLAMA_NUM_PARALLELを調整し、同時に処理するリクエスト数を物理メモリに見合った数(例: 2〜4)に制限します。
    2. キューイング: LiteLLM側でリクエストをキューイングし、バックエンドの負荷を平準化する設定を検討します。
    3. 量子化レベルの変更: モデルをfp16からq4_k_m(4bit量子化)に変更することで、VRAM消費を大幅に削減できます。
    4. 基盤環境の更新と互換性確認: Docker Engine v29.1などのメジャーアップデート時には一部機能が削除されることがあるため、これらに依存するコンテナ設定やワークフローの挙動変更に注意が必要です。

推論速度低下時のボトルネック特定

「生成が遅い」という報告が上がった場合、原因切り分けのフローは以下の通りです。

  1. CPUオフロードの確認: docker logs internal-llm-engineを確認し、モデルの一部がVRAMに乗り切らずシステムRAM(CPU)にオフロードされていないかチェックします。CPU処理が入ると速度は一桁低下します。
  2. コンテキスト長: 入力トークン数が多すぎる場合、Prefill(最初の読み込み)に時間がかかります。RAG等のシステムで不要なコンテキストを詰め込みすぎていないか見直します。
  3. セキュリティパッチの適用: オープンソース環境では脆弱性対応も重要となります。Docker環境においてCVE-2025-58181のようなセキュリティ更新が提供された際は、速やかにパッチを適用し、パフォーマンス低下を防ぎつつ安全な運用を維持する必要があります。

まとめ:セキュアなAI基盤がもたらす競争優位

本記事で解説したアーキテクチャを構築することで、組織は「機密情報の保護」と「最先端AIの活用」という、一見相反する課題を同時に解決できます。

外部APIへの依存を断ち切ることは、コスト削減だけでなく、ビジネスの継続性を自社のコントロール下に置くことを意味します。例えば、クラウドAIサービスではGPT-4o等のレガシーモデルが廃止され、GPT-5.2のような新モデルへ強制移行されるといった仕様変更が頻繁に発生します。しかし、ローカルLLMであればそうした外部要因による予期せぬシステム改修に振り回されることなく、安定した運用が可能です。

AI技術は日々進化していますが、データの安全性という土台があってこそ、その真価を発揮できます。過度な最新技術の押し付けではなく、真に業務に役立つ解決策として、このアーキテクチャが機能するはずです。

まずは手元のワークステーションや開発用サーバーで、紹介したDocker Composeを立ち上げてみてください。わずか数分で、誰にも覗かれることのない専用の知能が動き出します。この小さなデモ環境が、やがて全社のDXを加速させる強固な基盤となるでしょう。

完全閉域網で動く!機密情報を守るローカルLLM構築|OllamaとDockerで作るセキュアな社内AI基盤 - Conclusion Image

コメント

コメントは1週間で消えます
コメントを読み込み中...