0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker ComposeでローカルにWikiと全文検索環境を構築する

0
Last updated at Posted at 2026-09-26

チーム内のメモや検証結果をWikiに集約しても、ページ数が増えると「どこに書いたか分からない」という問題が起きます。Wiki側の検索だけでは検索条件を細かく指定しにくく、複数のデータソースを横断したいケースでは別の検索基盤も必要です。

そこで今回は、Docker Composeを使ってローカルに以下の環境を構築しました。

  • Wiki.js:ドキュメント管理
  • PostgreSQL:Wiki.jsのデータベース
  • OpenSearch:全文検索エンジン

Wiki.jsとOpenSearchは役割を分離し、まずは検索用インデックスへAPIで文書を登録する構成です。ローカル検証や個人用ナレッジベースの土台として、比較的少ない設定で動かせます。

構成と前提

今回の構成は次の通りです。

ブラウザ
  ├─ Wiki.js      : http://localhost:8080
  └─ OpenSearch   : http://localhost:9200

Wiki.js ── PostgreSQL

Docker DesktopとDocker Composeが使える環境を前提にしています。OpenSearchはメモリを使用するため、Docker Desktopには最低でも2〜4GB程度のメモリを割り当てておくと安定します。

プロジェクト用のディレクトリを作成します。

mkdir local-wiki
cd local-wiki

Docker Composeを作成する

compose.yamlを作成します。

services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: wiki
      POSTGRES_USER: wikijs
      POSTGRES_PASSWORD: wikijs-password
    volumes:
      - postgres-data:/var/lib/postgresql/data

  wiki:
    image: ghcr.io/requarks/wiki:2
    restart: unless-stopped
    depends_on:
      - db
    ports:
      - "8080:3000"
    environment:
      DB_TYPE: postgres
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: wikijs
      DB_PASS: wikijs-password
      DB_NAME: wiki

  search:
    image: opensearchproject/opensearch:2.17.1
    restart: unless-stopped
    environment:
      discovery.type: single-node
      DISABLE_SECURITY_PLUGIN: "true"
      DISABLE_INSTALL_DEMO_CONFIG: "true"
      bootstrap.memory_lock: "true"
      OPENSEARCH_JAVA_OPTS: "-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - opensearch-data:/usr/share/opensearch/data
    ulimits:
      memlock:
        soft: -1
        hard: -1

volumes:
  postgres-data:
  opensearch-data:

今回のOpenSearchはローカル検証用としてセキュリティプラグインを無効にしています。本番やネットワーク越しで利用する場合は、認証・TLS・アクセス制御を必ず設定してください。

起動します。

docker compose up -d
docker compose ps

wiki、db、searchの3サービスがrunningになっていれば起動完了です。

Wiki.jsを初期設定する

ブラウザでhttp://localhost:8080を開くと、Wiki.jsの初期設定画面が表示されます。

管理者メールアドレスとパスワードを入力し、データベース設定はComposeの環境変数と同じ内容にします。

Database Type: PostgreSQL
Host: db
Port: 5432
User: wikijs
Password: wikijs-password
Database: wiki

Composeネットワーク内では、接続先にlocalhostではなくサービス名のdbを指定する点がポイントです。

初期設定が完了したら、テスト用のページを作成します。私は次のようなページを用意しました。

タイトル: Docker Composeのメモ

本文:
Docker Composeでは複数のコンテナをサービスとして定義できる。
docker compose up -dでバックグラウンド起動する。

Wiki.js単体の動作確認としては、ページの作成、編集、検索ができれば問題ありません。

OpenSearchに検索インデックスを作る

次に、OpenSearchへWikiページ用のインデックスを作成します。

日本語を扱うため、今回は形態素解析プラグインを追加せず、2文字単位のngramトークナイザーを使います。小規模なローカルWikiでは、設定が簡単で部分一致にも対応しやすい方法です。

まずOpenSearchが応答するか確認します。

curl http://localhost:9200

続いてインデックスを作成します。

curl -X PUT http://localhost:9200/wiki-pages \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "analysis": {
        "tokenizer": {
          "jp_bigram": {
            "type": "ngram",
            "min_gram": 2,
            "max_gram": 2
          }
        },
        "analyzer": {
          "jp_text": {
            "type": "custom",
            "tokenizer": "jp_bigram",
            "filter": ["lowercase"]
          }
        }
      }
    },
    "mappings": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "jp_text"
        },
        "body": {
          "type": "text",
          "analyzer": "jp_text"
        },
        "path": {
          "type": "keyword"
        },
        "tags": {
          "type": "keyword"
        }
      }
    }
  }'

インデックスが作成できたら、Wikiページに相当する文書を登録します。

curl -X PUT http://localhost:9200/wiki-pages/_doc/docker-compose \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Docker Composeのメモ",
    "body": "Docker Composeでは複数のコンテナをサービスとして定義できる。docker compose up -dでバックグラウンド起動する。",
    "path": "/docker-compose",
    "tags": ["docker", "compose"]
  }'

登録した文書を検索します。

curl -X GET http://localhost:9200/wiki-pages/_search \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "multi_match": {
        "query": "バックグラウンド起動",
        "fields": ["title", "body"]
      }
    }
  }'

レスポンスのhits.hitsに、タイトルや本文、検索スコアが含まれていれば成功です。

Wiki.jsと検索インデックスを同期する

Wiki.jsのページ変更をOpenSearchへ反映する流れは次の通りです。

今回の構成では、Wiki.jsにページを作成しただけではOpenSearchへ自動登録されません。ここは意識して設計する必要があります。

最初の検証では、検索APIの確認を優先して手動登録しました。実際に運用する場合は、次のような同期処理を追加します。

  1. Wiki.jsのページ更新を検知する
  2. ページのタイトル、本文、パス、タグを取得する
  3. OpenSearchのドキュメントを作成または更新する
  4. ページ削除時は検索インデックスからも削除する

Wiki.jsにはGraphQL APIがあるため、アクセストークンを使ってページ情報を取得する同期スクリプトを作れます。ページ数が少ないうちは、Markdownをエクスポートして定期的にインデックスを作り直す方法でも十分です。

同期処理では、Wiki.js側のページIDをOpenSearchのドキュメントIDとして使うと、更新時に同じ文書を上書きできます。

OpenSearch document ID = Wiki.js page ID

検索結果からWikiページへ戻るために、pathも必ず保存しておくと便利です。

実運用で気を付けた点

まず、OpenSearchのインデックス設定は作成後に簡単には変更できません。ngramのサイズやフィールド構成を変えたい場合は、新しいインデックスを作成してデータを移行します。

また、ngramは検索しやすい一方で、通常の単語分割よりインデックスサイズが大きくなります。数万ページ規模になった場合は、kuromojiなどの日本語解析を検討した方がよいでしょう。

データを初期化したい場合は、次のコマンドでボリュームごと削除できます。

docker compose down -v

このコマンドを実行すると、Wiki.jsのデータベースとOpenSearchのインデックスも削除されます。検証環境では便利ですが、残したいデータがある場合は実行前にバックアップしてください。

まとめ

Docker Composeを使うと、Wiki.js、PostgreSQL、OpenSearchをローカルだけでまとめて起動できます。

今回のポイントは次の3つです。

  • Wiki.jsと検索エンジンをコンテナ単位で分離する
  • 日本語検索にはngramを使って部分一致を実現する
  • Wiki更新とOpenSearch更新を同期処理として設計する

まずは手動登録で検索の動きを確認し、その後にWiki.jsのAPIを使った同期処理を追加すると、段階的に構築できます。個人の技術メモからチーム内のナレッジベースまで、用途に合わせて拡張しやすい構成です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?