はじめに
ChatGPT や Perplexity のような「検索しながら答えてくれる AI」を、ローカルで・無料で・自分のデータを外に出さずに実現したい。そう思って調べると、Ollama + OpenWebUI + SearxNG という構成が定番として出てくる。
構成としてはシンプルで、ドキュメントを読めばなんとなく動きそうに見える。実際、コンテナを2つ立てて URL を設定するだけ、のはずだった。
ところが実際にやってみると、各コンポーネントの「デフォルトでオフになっている設定」が絶妙に噛み合っていて、何も考えずに繋ごうとすると各所でエラーになる。エラーのほとんどはメッセージだけでは原因が分からないタイプで、初見だとかなり時間を食う。
この記事では、構築手順とあわせて「ここで詰まった」というポイントを全部書いておく。同じ構成を試している人の時間を少しでも節約できれば。
環境は以下の通り。
| 項目 | 内容 |
|---|---|
| マシン | Mac mini (2024) |
| OS | macOS Tahoe 26.3.1 (arm64) |
| CPU | Apple M4 (10コア / 4.46 GHz) |
| メモリ | 32 GB |
| コンテナ実行環境 | Docker Desktop |
構成
[OpenWebUI :3000] → [SearxNG :8080] → Web検索
↕
[Ollama(ホスト)]
OpenWebUI と SearxNG はそれぞれ独立した Docker コンテナで動かす。
Ollama はホストに直インストール済みの前提。
1. コンテナを起動する
OpenWebUI
docker run -d \
-e WEBUI_WORKERS=2 \
-p 3000:8080 \
-v openwebui:/app/backend/data \
--name openwebui \
--restart always \
ghcr.io/open-webui/open-webui:main
http://localhost:3000 でアクセスできれば OK。
SearxNG
docker run -d \
-p 8080:8080 \
--name searxng \
searxng/searxng
http://localhost:8080 でアクセスして検索画面が出れば OK。
2. SearxNG の設定を変える(ここが最大の罠)
SearxNG はデフォルトで JSON フォーマットの API レスポンスが無効になっている。
そのまま OpenWebUI から叩くと、JSON を期待しているのに以下のエラーが返ってくる。
Forbidden
You don't have the permission to access the requested resource.
ブラウザで http://localhost:8080/search?q=test&format=json を叩いてみると一目瞭然。
コンテナに入って settings.yml を編集する
ここで最初にやりがちなミス。bashで入ろうとするとこうなる:
$ docker exec -it searxng /bin/bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory
SearxNG のイメージは Alpine ベースなので /bin/bash が存在しない。/bin/sh を使う:
docker exec -it searxng /bin/sh
入れたら settings.yml を編集する:
vi /etc/searxng/settings.yml
search: セクションに json を追加する:
search:
formats:
- html
- json # これを追加
保存して抜けたらコンテナを再起動:
docker restart searxng
確認
http://localhost:8080/search?q=test&format=json
JSON が返ってきたら成功。
3. OpenWebUI の Web 検索設定
OpenWebUI の管理画面から設定する。
設定 → ウェブ検索
| 項目 | 値 |
|---|---|
| ウェブ検索 | ON |
| ウェブ検索エンジン | searxng |
| Searxng クエリ URL | http://host.docker.internal:8080 |
localhost ではなく host.docker.internal を使う理由
OpenWebUI はコンテナの中で動いている。コンテナ内から localhost を叩いても、それはコンテナ自身の localhost であり、ホストマシンの 8080 には届かない。
Docker Desktop(Mac / Windows)では、ホストマシンを指すための特別なホスト名として host.docker.internal が用意されている。
✗ http://localhost:8080 → コンテナ自身を見に行く(つながらない)
✓ http://host.docker.internal:8080 → ホストの 8080 に届く
Linux + Docker Engine の場合は host.docker.internal が使えないケースがあるので注意(--add-host=host.docker.internal:host-gateway が別途必要)。
4. モデル設定で Web Search を有効化(見落としやすい)
SearxNG の URL を設定しただけでは Web 検索は動かない。モデルごとに Web Search を有効化する必要がある。
管理者パネル → モデル → 使用するモデルを選択(例:gemma4:latest)
モデル設定画面を下にスクロールすると「デフォルト機能」というセクションがある。
デフォルト機能
☑ ウェブ検索 ☐ 画像生成 ☐ コードインタプリタ
ここの **「ウェブ検索」にチェックを入れて「保存して更新」**する。
デフォルトではオフになっているので見落としやすい。チャット画面で検索マークが表示されていても、このチェックがオフだと実際には検索が走らず、モデルの学習データの範囲でしか回答しない。
設定前は「今日のセキュリティニュースを教えて」と聞いても、学習データ時点の情報を返すだけだった(しかも「リアルタイム情報は持っていません」と言いつつそれっぽい回答を生成する、という挙動をする)。
5. 動作確認
今日のセキュリティニュースを教えて
SearxNG 経由でリアルタイムに検索した結果を元に回答が返ってくれば完成。
まとめ:詰まりポイント一覧
| 症状 | 原因 | 対処 |
|---|---|---|
docker exec /bin/bash が失敗する |
Alpine イメージに bash がない |
/bin/sh を使う |
format=json で 403 Forbidden |
JSON API がデフォルト無効 |
settings.yml に formats: [html, json] を追加 |
| OpenWebUI から SearxNG につながらない | コンテナ内の localhost はホストではない | URL を host.docker.internal:8080 にする |
| 設定したのに検索が動かない | モデルごとの「デフォルト機能」がオフ | 管理パネル → モデル → デフォルト機能 → ウェブ検索をオン |
おわりに
構成自体はシンプルだが、「Alpine に bash はない」「Docker コンテナ内の localhost はホストではない」「SearxNG の JSON API はデフォルト無効」「モデルごとに Web Search を有効化しないといけない」という4つの落とし穴が重なると地味に時間を食う。
特に最後のモデル設定は、グローバルの Web 検索設定とは別に存在するので、「設定したのに動かない」という状況になりやすい。同じところで詰まった人の助けになれば。