Mastodon (Docker 環境) への Elasticsearch 導入メモ

Mastodon の 最近のアップデート で、 Elasticsearch による全文検索機能がサポートされました。

全文検索機能はデフォルトでは有効化されておらず、筆者の運営する Mastodon インスタンス theboss.tech では、最近のメンテナンスでこの機能を有効化しました。

非 Docker 環境への導入については クラゲ丼 を運営されている ぜま さんの記事に詳しく書かれています。

参考: マストドンに日本語対応の全文検索を導入 - クラゲ丼

本記事では Docker 環境への導入手順と、作業メモを記述します。

Mastodon (Docker 環境) の Elasticsearch 導入

日本語プラグイン入り Elasticsearch イメージの作成

Elasticsearch は、標準では日本語を正しく検索できず、 Kuromoji というプラグインを入れる必要があります。今回は NEologd にも対応したプラグイン を加えた専用の Docker イメージを作成しました。

Docker イメージ: luckybeastakatheboss/docker-elasticsearch-kuromoji-neologd - Docker Hub

イメージは以下のファイルをビルドし、 Docker Hub にプッシュしたものです。

Dockerfile: theboss/docker-elasticsearch-kuromoji-neologd

docker build . -t luckybeastakatheboss/docker-elasticsearch-kuromoji-neologd:6.2.3
docker push luckybeastakatheboss/docker-elasticsearch-kuromoji-neologd:6.2.3

Elasticsearch サービスの作成

先程の Docker イメージでサービスを作成します。

  es:
    restart: always
    image: luckybeastakatheboss/docker-elasticsearch-kuromoji-neologd:6.2.3
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    networks:
      - internal_network
### Uncomment to enable ES persistance
    volumes:
      - ./elasticsearch:/usr/share/elasticsearch/data

設定ファイルを修正する

Docker 設定と、 .env ファイルを修正します。修正は 公式リポジトリにある設定ファイル から、 ES 関連をコメントアウト解除するだけでできました。

インデックス作成タスクの設定変更、検索上限数拡大

マストドンに日本語対応の全文検索を導入 - クラゲ丼 で解説されているとおり、 Kuromoji や Kuromoji-NEologd を使う場合、インデックス作成タスクの設定変更が必要です。検索上限数は必要に応じて変更します。

追記: Kuromoji-NEologd のインデックス設定は以下のようにしました。

class StatusesIndex < Chewy::Index
  settings index: { refresh_interval: '15m' }, analysis: {
    analyzer: {
      content: {
        type: 'custom',
        tokenizer: 'kuromoji_neologd_tokenizer',
        filter: %w(
          kuromoji_neologd_baseform
          kuromoji_neologd_stemmer
          cjk_width
          lowercase
        ),
      },
    },
  }

max_map_count 拡大

Elasticsearch を Docker で動かす場合、 max_map_count という Linux のシステム設定値が一定以上である必要があります。

# 現在の設定値を確認
sysctl -a | grep vm.max_map_count
# 262144 よりも小さければ以下コマンドで変更
sudo sysctl -w vm.max_map_count=262144

インデックス作成タスクの実行、起動

chewy:deploy というタスクを実行します。この処理には時間がかかるのと、メモリを大きく消費するため Mastodon 稼働中に実行するのは避けたほうがよいかもしれません。筆者はインスタンスを停止してから実行しました。

# Docker イメージ取得・更新
docker-compose pull
# インデックス作成タスク実行
docker-compose run --rm web rails db:migrate assets:precompile chewy:deploy
# 起動
docker-compose up -d --remove-orphans

以上で全文検索が有効になります。

補足: Elasticsearch を独立した Docker サーバで起動する場合

theboss.tech では、 Elasticsearch サービスを Mastodon サービスと同じ Docker ネットワークで構築していましたが、負荷が大きいため別サーバに移動しました。

本来ならば Docker Swarm や Kubernetes を使い複数サーバにまたがるコンテナネットワークを形成するべきですが、今回は時間の都合上、単に独立した Docker サーバとしました。

このような場合、以下の設定変更が必要になります。

  • docker-compose の Elasticsearch サービスに external_networkPORTS オプションを設定する必要があります。
  • .env.productionES_HOST はサービス名でなく IP アドレスにする必要があります。

トラブルシュート

Elasticsearch 起動時にエラー (AccessDeniedException)

es_1            | [2018-03-21T07:47:04,075][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
es_1            | org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: Failed to create node environment
(snip)
es_1            | Caused by: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/nodes

elasticsearch ディレクトリを起動前に作成しておくか、 root で作成されてしまったディレクトリのオーナーを 1000:1000 に変更する必要があります。

sudo chown 1000:1000 elasticsearch

Elasticsearch 起動時にエラー (max virtual memory areas vm.max_map_count [65530] is too low)

es_1            | ERROR: [1] bootstrap checks failed
es_1            | [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

前述の手順の通り、 vm.max_map_count の値を大きくする必要があります。

web から接続できない

rails コマンドを実行したら以下エラーが起きました。 これは最初、 docker-compose.yml にて webdepends_ones を追加していなかったためでした。

Caused by:
SocketError: getaddrinfo: Name does not resolve
/mastodon/vendor/bundle/ruby/2.4.0/gems/httplog-0.99.7/lib/httplog/adapters/net_http.rb:38:in `connect'

が、追加しても上記エラーが起き、直後にもう一度 rails コマンドを実行したらうまくいきました。 es 起動後にリッスン開始するまで時間がかかっていた?のではないかと思われます。

その他メモ

冒頭の記事に従って、検索結果の上限件数を大きくしているため、 Mastodon 自体のイメージもビルドする必要がありました。このイメージも Docker Hub に上げておくと、 テスト用インスタンス と共有できて便利でした。

docker-compose build
docker push luckybeastakatheboss/mastodon
docker-compose -f docker-compose-masi.yml run --rm web rails chewy:deploy

See also