Dockerで始めるElasticsearch入門ガイド

Dockerで始めるElasticsearch入門ガイド

はじめに

インターネット上の情報の海は日々膨張し続けています。私たちがビジネスや研究、あるいは個人的な探求のために必要な情報を見つけ出すためには、効率的かつ高速な検索システムが不可欠です。このようなニーズに応える強力な全文検索エンジン、それがElasticsearchです。

Elasticsearchは、分散型のRESTful検索・分析エンジンであり、大量のデータをほぼリアルタイムで保存、検索、分析する能力を持っています。ログ分析、メトリクス監視、Webサイト検索、アプリケーション検索、セキュリティインテリジェンスなど、多岐にわたるユースケースで利用されています。その柔軟性、スケーラビリティ、そして強力な検索機能により、多くの企業や開発者に選ばれています。

しかし、Elasticsearchを始めるにあたって、そのセットアップは初心者にとって少々複雑に感じられるかもしれません。Javaの実行環境の準備、各種設定ファイルの編集、そして分散環境を構築する際の考慮事項など、乗り越えるべきハードルがいくつか存在します。

そこで登場するのがDockerです。Dockerは、アプリケーションとその依存関係をコンテナと呼ばれる軽量な仮想化環境にパッケージングする技術です。Dockerを使うことで、OSや環境の違いを吸収し、開発環境のセットアップを劇的にシンプルにすることができます。Elasticsearchも公式にDockerイメージを提供しており、Dockerを利用することで、複雑なセットアップ手順を気にすることなく、迅速にElasticsearch環境を立ち上げ、すぐに使い始めることが可能です。

この記事は、Elasticsearchをこれから学び始めたいと考えている開発者やITエンジニアの皆さんを対象としています。特に、「まずはローカル環境でElasticsearchを動かしてみたい」「複雑な環境構築は避けたい」という方に最適です。Dockerの基本的な知識があることを前提としていますが、ElasticsearchやDocker Composeについては詳しく解説しますのでご安心ください。

この記事を読むことで、以下の内容を習得できます。

  • Elasticsearchの基本的な概念
  • Dockerを使ったElasticsearch環境の基本的なセットアップ方法
  • Kibana(ElasticsearchのUIツール)のセットアップと連携
  • KibanaのDev Toolsを使ったElasticsearchの基本的な操作(インデックス作成、データ投入、検索)
  • DockerとElasticsearchを使う上での注意点(メモリ、永続化など)

約5000語というボリュームで、各ステップと概念を詳細に解説していきます。さあ、Dockerを使ってElasticsearchの世界に飛び込みましょう!

Elasticsearchの基本概念

Elasticsearchを使い始める前に、いくつかの重要な概念を理解しておくことが重要です。これらの概念は、Elasticsearchがどのようにデータを格納し、検索を実行するのかを理解する上で基盤となります。

ドキュメント (Document)

Elasticsearchの最も基本的なデータ単位は「ドキュメント」です。ドキュメントは、JSON形式で表現される単一の情報の塊です。リレーショナルデータベースにおける「行」や「レコード」に相当しますが、スキーマレスである点が大きく異なります(ただし、実際にはMappingによってスキーマに近い構造を持ちます)。

例えば、顧客情報、製品情報、ログイベント、ブログ記事など、どのような情報でもドキュメントとして格納できます。各ドキュメントは一意のIDを持ちます。

json
{
"id": "1",
"title": "Dockerで始めるElasticsearch入門",
"author": "Jane Doe",
"publish_date": "2023-10-27T10:00:00Z",
"tags": ["docker", "elasticsearch", "入門", "検索"],
"content": "この記事では、Dockerを使ってElasticsearch環境を構築し、基本的な操作を学びます..."
}

インデックス (Index)

インデックスは、関連するドキュメントの集まりです。リレーショナルデータベースにおける「データベース」に似ていますが、より検索エンジンに特化した概念です。Elasticsearchは、インデックス単位でドキュメントを管理し、検索や分析を実行します。

例えば、顧客情報のドキュメントは customers インデックスに、製品情報のドキュメントは products インデックスに格納するといった使い分けをします。インデックス名は小文字で始める必要があり、特殊文字には制限があります。

インデックスは、その中に格納されるドキュメントのフィールドのデータ型や分析方法を定義する「Mapping」を持ちます。Mappingは、ドキュメントがインデックスに追加される際に自動的に推測されることもありますが、明示的に定義することで検索の精度やパフォーマンスを細かく制御できます。

タイプ (Type) – 非推奨/廃止

Elasticsearchの古いバージョンでは、インデックス内に複数の「タイプ」を定義することができました。タイプは、異なる構造を持つドキュメントを同じインデックス内に共存させるために使用されました。リレーショナルデータベースにおける「テーブル」に相当する概念でした。

しかし、Elasticsearchの内部的な変更(特にLuceneのデータ構造との整合性)により、このタイプという概念は廃止されつつあります。Elasticsearch 6.xではインデックスごとに1つのタイプのみが許可され、7.x以降では完全に廃止されました。現在は、1つのインデックスは1つのタイプ(デフォルトでは_doc)を持つ、あるいはタイプという概念そのものがなくなり、インデックスがリレーショナルデータベースのテーブルに相当する概念として扱われるようになっています。

したがって、最新のElasticsearchを使う場合は、1つのインデックスに1種類の構造(Mapping)のドキュメントを格納し、もし異なる種類のドキュメントを扱いたい場合は、別のインデックスを作成するという設計が推奨されます。

クラスター (Cluster)

クラスターは、1つまたは複数のノードの集まりです。Elasticsearchは分散システムとして設計されており、複数のマシン(ノード)を連携させてクラスターを構成することで、データの冗長性、可用性、および水平スケーラビリティを実現します。

クラスター内の各ノードは互いに通信し、協調してデータの格納、検索、管理を行います。クラスター全体は単一の論理エンティティとして機能し、クライアントからのリクエストはクラスター内のどのノードが受け付けても処理されます。

単一ノードの場合でも、技術的には1ノードのクラスターとして扱われます。本番環境では通常、高可用性や大量のデータを処理するために複数のノードでクラスターを構築します。

ノード (Node)

ノードは、Elasticsearchの単一のインスタンスです。クラスターに参加する個々のサーバーやコンテナを指します。ノードはデータを格納し、クラスターのインデックス作成や検索能力に貢献します。

ノードにはいくつかの役割があります。主要な役割としては、マスターノード(クラスター全体の管理)、データノード(データの格納と検索処理)、インジェストノード(ドキュメントの取り込み前処理)、コーディネイティングノード(クライアントからのリクエストを受け付け、適切なノードに転送し、結果をまとめる)などがあります。通常、1つのノードが複数の役割を持つことができます。

入門用途や開発環境では、1つのノードがすべての役割を兼任する構成が一般的です。

シャード (Shard)

シャードは、Elasticsearchがインデックスを分散管理するための仕組みです。インデックスは、プライマリシャードと呼ばれる複数の小さな論理的な部分に分割されます。各プライマリシャードは、インデックスのデータの一部を保持しており、独立したLuceneインデックスとして機能します。

インデックスを複数のシャードに分割することで、Elasticsearchは以下のメリットを得ます。

  • 水平スケーリング: 大量のデータを複数のノードに分散して格納できます。
  • パフォーマンス: 複数のシャードを並行して検索することで、検索処理を高速化できます。

インデックス作成時に、プライマリシャードの数を指定します。一度作成されたプライマリシャードの数を後から変更することはできません(リインデックスなどの操作が必要)。

レプリカ (Replica)

レプリカは、プライマリシャードのコピーです。各プライマリシャードに対して、1つまたは複数のレプリカシャードを作成できます。レプリカシャードもプライマリシャードと同様に、独立したLuceneインデックスとして機能します。

レプリカシャードの主な目的は以下の2つです。

  • 高可用性: プライマリシャードを保持するノードが障害で停止した場合でも、レプリカシャードが引き継ぐことでデータの損失を防ぎ、検索サービスを継続できます。
  • 検索パフォーマンス向上: 検索リクエストはプライマリシャードとレプリカシャードの両方で処理できるため、同時に処理できるリクエスト数が増加し、検索スループットが向上します。

インデックス作成時に、各プライマリシャードに対するレプリカシャードの数を指定します。レプリカシャードの数は、インデックス作成後に変更可能です。

インデックスは、プライマリシャードとレプリカシャードから構成されます。デフォルトでは、1つのインデックスは1つのプライマリシャードと1つのレプリカシャードを持ちます。これは、合計で2つのシャードコピーが存在することを意味します。

Mapping

Mappingは、インデックス内のドキュメントがどのように構造化されているか、各フィールドがどのようなデータ型を持つか、そしてどのようにインデックス化されるか(例えば、文字列フィールドが全文検索可能になるように分析されるかどうか)を定義するスキーマです。

Mappingは、ドキュメントを初めてインデックスに追加する際にElasticsearchが自動的に推測することも多いですが(Dynamic Mapping)、意図した検索や分析を行うためには、多くの場合明示的にMappingを定義する必要があります。例えば、日付フィールドを正しく扱うためや、文字列フィールドをキーワードとして扱うか全文検索対象として扱うかを制御するためにMappingを定義します。

Analyzer

Analyzerは、テキストフィールドがインデックス化される際や検索クエリが処理される際に、テキストをどのように処理するかを定義するコンポーネントです。Analyzerは、キャラクターフィルター、トークナイザー、トークンフィルターという3つの要素から構成されます。

  • キャラクターフィルター: インデックス化または検索前に元の文字列を処理します(例: HTMLタグの除去)。
  • トークナイザー: 文字列を個々の「トークン」(単語)に分割します(例: スペースや句読点で区切る)。
  • トークンフィルター: トークナイザーによって生成されたトークンを加工します(例: 小文字化、ステミング(語幹処理)、ストップワード(a, theなど)の除去、同義語処理)。

適切なAnalyzerを選択またはカスタマイズすることは、検索精度に大きく影響します。特に日本語のような言語を扱う場合は、日本語用のAnalyzer(kuromojiなど)の使用が必須となります。

これらの基本概念を理解しておくことで、Elasticsearchの挙動や設定の意図がより明確になります。

Dockerの準備

ElasticsearchをDockerで実行するためには、まずご自身のマシンにDocker環境をセットアップする必要があります。

Docker Desktopのインストール

Docker Desktopは、Mac、Windows、Linux(WSL2が必要な場合あり)で動作する、Docker環境を簡単に構築・管理できるアプリケーションです。以下の公式サイトからダウンロードしてインストールしてください。

インストール手順はOSによって異なりますので、詳細は公式サイトのドキュメントを参照してください。インストール後、Docker Desktopを起動し、Docker Engineが正常に動作していることを確認してください。

ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行して、Dockerが正しくインストールされ、実行可能であることを確認します。

bash
docker --version
docker compose version # Docker Compose V2 の場合
docker-compose --version # Docker Compose V1 の場合

それぞれのバージョン情報が表示されれば準備完了です。

Dockerコマンドの基本

Dockerを使ってコンテナを操作する基本的なコマンドをいくつか紹介します。これらはElasticsearchコンテナを扱う際にも使用します。

  • docker run [OPTIONS] IMAGE [COMMAND] [ARG...]: 指定したイメージから新しいコンテナを作成して実行します。
  • docker ps [-a]: 実行中のコンテナ一覧を表示します。-a オプションを付けると、停止中のコンテナも含めてすべて表示します。
  • docker images: ローカルにダウンロードされているDockerイメージ一覧を表示します。
  • docker stop CONTAINER [CONTAINER...]: 実行中のコンテナを停止します。コンテナ名はIDの一部または名前で指定できます。
  • docker rm CONTAINER [CONTAINER...]: 停止中のコンテナを削除します。
  • docker logs CONTAINER: コンテナの標準出力ログを表示します。
  • docker exec [OPTIONS] CONTAINER COMMAND [ARG...]: 実行中のコンテナ内でコマンドを実行します。

Docker Composeのインストールと基本

複数のコンテナ(例えばElasticsearchとKibana)を連携させて一度に管理する場合、Docker Composeが非常に便利です。Docker Composeは、YAMLファイルにサービス構成を定義し、その定義に基づいてコンテナ群を一括で操作(起動、停止、削除など)できるツールです。

Docker Desktopをインストールした場合、多くの場合はDocker Composeも一緒にインストールされます。Docker Compose V2はdocker composeコマンド、V1はdocker-composeコマンドで実行します。今後の開発ではV2が推奨されています。

Docker Composeの基本的なコマンドは以下の通りです。

  • docker compose build: docker-compose.yml ファイルで定義されたサービス(カスタムイメージを使用する場合など)のイメージをビルドします。
  • docker compose up [-d]: docker-compose.yml ファイルで定義されたサービスを起動します。-d オプションを付けると、バックグラウンドで実行します。
  • docker compose down: docker-compose.yml ファイルで定義されたサービスを停止し、コンテナやネットワーク、ボリュームなどを削除します。
  • docker compose ps: docker-compose.yml ファイルで定義されたサービスのコンテナの状態を表示します。
  • docker compose logs [SERVICE...]: サービス(コンテナ)のログを表示します。

この記事では、複数のコンテナ(ElasticsearchとKibana)を連携させるため、主にDocker Composeを使用します。

Dockerを使ったElasticsearchのセットアップ

いよいよDockerを使ってElasticsearch環境をセットアップします。ここでは、まず基本的な単一ノードでのセットアップ方法を示し、次に本記事で推奨するDocker Composeを使ったセットアップ方法を詳細に解説します。

単一ノードでのセットアップ (基本)

まずは、最もシンプルな方法として、docker run コマンドを使って単一のElasticsearchノードを起動してみましょう。この方法は、Dockerの理解を深めるのに役立ちますが、設定の管理や複数のコンテナ連携には向いていません。

ElasticsearchはDocker Hubで公式イメージを提供しています。デフォルトでは最新バージョンが取得されますが、特定のバージョンを指定することも可能です(例: elasticsearch:7.17.0)。入門としては最新版で問題ありません。

コマンド例:

bash
docker run \
--rm \
--name elasticsearch \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
elasticsearch:8.10.2 # 使用したいバージョンを指定

解説:

  • docker run: 新しいコンテナを作成して実行します。
  • --rm: コンテナ停止時に自動的にコンテナを削除します。一時的な実行に便利です。
  • --name elasticsearch: コンテナに elasticsearch という名前を付けます。
  • -p 9200:9200: ホストマシン(ローカルPC)のポート9200を、コンテナのポート9200にマッピングします。ElasticsearchのREST APIは通常9200ポートで公開されます。
  • -p 9300:9300: ホストマシンのポート9300を、コンテナのポート9300にマッピングします。ノード間の通信(クラスター内部通信)は通常9300ポートで行われます。単一ノードでもこのポートを開けておくと、Kibanaなど他のサービスが接続する際に便利です。
  • -e "discovery.type=single-node": 環境変数 discovery.typesingle-node に設定します。これは、このノードがクラスター内の唯一のノードであることをElasticsearchに伝え、ノード探索(Discovery)プロセスをスキップして単一ノードモードで起動するために必要です。この設定がないと、デフォルトではクラスターを形成しようとして起動に失敗することがあります。
  • elasticsearch:8.10.2: 使用するDockerイメージの名前とタグ(バージョン)です。Docker Hubから自動的にダウンロードされます。

このコマンドを実行すると、Elasticsearchコンテナが起動します。起動には少し時間がかかります。ログを監視するには、-d オプションを付けずに実行するか、別のターミナルで docker logs elasticsearch コマンドを実行してください。

Elasticsearchが正常に起動すると、ホストマシンのブラウザから http://localhost:9200 にアクセスできるようになります。ただし、バージョン8.x以降のElasticsearchはデフォルトでセキュリティ(X-Pack Basic)が有効になっているため、認証情報なしではアクセスできません。この後のDocker Composeのセクションで、セキュリティ有効時の対応についても触れます。

データの永続化について:

上記の docker run コマンドでは、データの永続化を設定していません。このままでは、コンテナを削除(docker rm)すると、Elasticsearchに格納したデータも失われます。開発用途でもデータを保持したい場合は、Docker Volumeやバインドマウントを使って、コンテナ内のデータをホストマシンのディレクトリやDocker管理の領域に保存する必要があります。

例(バインドマウント):

bash
docker run \
--rm \
--name elasticsearch \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-v elasticsearch-data:/usr/share/elasticsearch/data \ # データ永続化用のVolumeをマウント
elasticsearch:8.10.2

-v elasticsearch-data:/usr/share/elasticsearch/data の部分は、elasticsearch-data という名前のDocker Volume(Dockerが管理するストレージ領域)を、コンテナ内の /usr/share/elasticsearch/data ディレクトリにマウントするという設定です。これにより、Elasticsearchがデータ(インデックスファイルなど)をこのディレクトリに書き込むと、そのデータはDocker Volumeに保存され、コンテナが削除されてもデータは残ります。

Docker Volumeを使うのが、権限管理なども含めて推奨される方法です。

Docker Composeを使ったセットアップ (推奨)

複数のサービス(ElasticsearchとKibana)を連携させて管理する場合や、より複雑な設定を管理する場合、Docker Composeを使うのが最も簡単で効果的です。ここでは、ElasticsearchとKibanaを同時に起動する docker-compose.yml ファイルを作成し、セットアップを行います。

docker-compose.yml ファイルの作成

以下の内容で docker-compose.yml という名前のファイルを作成します。プロジェクトのルートディレクトリなどに配置するのが一般的です。

“`yaml

docker-compose.yml

version: ‘3.8’

services:
elasticsearch:
image: elasticsearch:8.10.2 # 使用したいバージョンを指定。Kibanaと合わせること!
container_name: elasticsearch
environment:
# discovery.typeをsingle-nodeに設定(開発・学習用)
– discovery.type=single-node
# メモリ設定(重要!)
# ElasticsearchのJavaヒープサイズ。物理メモリの半分以下が推奨。
# 開発用なので小さめに設定することも可能だが、最低限の確保が必要。
# XmsとXmxは同じ値に設定するのがベストプラクティス。
– ES_JAVA_OPTS=”-Xms512m -Xmx512m”
# X-Pack Basic Security を無効化する設定 (入門・学習用としては便利)
# デフォルトは有効。無効化しない場合はセキュリティ設定と認証が必要になる。
# – xpack.security.enabled=false # 無効化する場合コメントアウトを外す
# X-Pack Basic Security を有効化する場合の環境変数
# Elasticsearch起動時に初期パスワードなどが表示される
# – ELASTIC_PASSWORD=your_password # 推奨されない方法だが一時的に設定することも可能
ports:
– “9200:9200” # REST API
– “9300:9300” # Node-to-node communication
volumes:
# データ永続化のためにDocker Volumeをマウント
– elasticsearch-data:/usr/share/elasticsearch/data
# メモリ制限 (Dockerレベル)
# コンテナが使用できる合計メモリ量。ES_JAVA_OPTSよりも大きい値にする必要あり。
mem_limit: 1g # 例:1GB
# Swappingを無効にする設定 (重要!)
# ElasticsearchはSwappingが発生するとパフォーマンスが著しく低下するため、無効化が必要。
# ホストマシン側でもswappingが無効になっているか確認推奨。
ulimits:
memlock:
soft: -1
hard: -1

kibana:
image: kibana:8.10.2 # 使用したいバージョンを指定。Elasticsearchと合わせること!
container_name: kibana
environment:
# ElasticsearchのURLを指定
# 同じdocker-composeネットワーク内なので、サービス名でアクセス可能
– ELASTICSEARCH_HOSTS=[“http://elasticsearch:9200”]
# X-Pack Basic Security を有効化している場合、Kibanaからも認証情報を設定する必要がある
# – ELASTICSEARCH_USERNAME=elastic # 例: elasticユーザーで接続
# – ELASTICSEARCH_PASSWORD=your_password # 例: パスワード
ports:
– “5601:5601” # Kibana UI
depends_on:
# Elasticsearchコンテナが起動してからKibanaコンテナを起動するように依存関係を設定
– elasticsearch
# メモリ制限 (Dockerレベル)
mem_limit: 1g # 例:1GB

データ永続化用のDocker Volumeを定義

volumes:
elasticsearch-data:
driver: local # ローカルディスクに保存
“`

docker-compose.yml の解説:

  • version: '3.8': 使用するDocker Composeファイルのバージョンを指定します。
  • services:: 定義するサービス(コンテナ)群をリストします。
    • elasticsearch:: elasticsearch という名前のサービス定義です。
      • image: elasticsearch:8.10.2: 使用するDockerイメージを指定します。Elasticsearchのバージョン8.10.2を使用します。KibanaとElasticsearchのバージョンは一致させる必要があります。
      • container_name: elasticsearch: コンテナに elasticsearch という名前を付けます。
      • environment:: コンテナ内で利用可能な環境変数を設定します。
        • discovery.type=single-node: 単一ノードモードで起動します。
        • ES_JAVA_OPTS="-Xms512m -Xmx512m": ElasticsearchのJavaヒープサイズを512MBに設定します。これは非常に重要な設定です。 ElasticsearchはJVM上で動作するため、十分なメモリが必要です。しかし、ホストマシンの物理メモリの半分以上をヒープに割り当てると、Swappingが発生しやすくなりパフォーマンスが著しく低下するため、残りの半分はOSやLuceneのファイルシステムキャッシュのために空けておくのがベストプラクティスです。開発環境でリソースが限られている場合は、より小さな値(例: 256m)でも起動できる場合がありますが、安定稼働やある程度のデータ投入には512MB以上が推奨されます。
        • xpack.security.enabled=false: (コメントアウトされています) Elasticsearch 8.x以降はデフォルトでセキュリティが有効になっています。入門・学習目的で認証なしで簡単に試したい場合は、この行のコメントアウトを外してセキュリティを無効化してください。ただし、本番環境やインターネットに公開する環境では絶対に無効化しないでください。 セキュリティを有効化する手順は後述します。
        • ELASTIC_PASSWORD=your_password: (コメントアウトされています) セキュリティ有効時に、elastic ユーザーのパスワードを環境変数で指定できます。ただし、これはセキュリティ上推奨されない方法です。通常は起動後にパスワードを設定します。
      • ports:: ホストマシンとコンテナ間のポートマッピングを設定します。
        • "9200:9200": ホストの9200ポートをコンテナの9200ポートにマッピング(REST API)。
        • "9300:9300": ホストの9300ポートをコンテナの9300ポートにマッピング(ノード間通信)。
      • volumes:: データの永続化のためにボリュームをマウントします。
        • - elasticsearch-data:/usr/share/elasticsearch/data: 後述する elasticsearch-data という名前のDocker Volumeを、コンテナ内のElasticsearchデータディレクトリ(/usr/share/elasticsearch/data)にマウントします。これにより、コンテナが停止・削除されてもデータは保持されます。
      • mem_limit: 1g: Dockerレベルでのコンテナのメモリ使用上限を1GBに設定します。これはJVMヒープサイズ(ES_JAVA_OPTS)よりも大きな値である必要があります。OSやLuceneのファイルシステムキャッシュなどが使用するメモリを考慮して設定します。
      • ulimits:: コンテナのリソース制限を設定します。
        • memlock:: メモリロックに関する設定です。
          • soft: -1, hard: -1: メモリのスワッピングを無効化するために、コンテナがメモリをロックできるように設定します。memlock:-1 は無制限を意味します。Elasticsearchはスワッピングがパフォーマンスに深刻な影響を与えるため、この設定は非常に重要です。 ホストOS側でもユーザーに対するメモリロック制限(ulimit -l)を解除する必要がある場合があります(特にLinux)。Docker Desktopを使用している場合は、通常はDocker Desktop側で設定が管理されます。
    • kibana:: kibana という名前のサービス定義です。
      • image: kibana:8.10.2: 使用するKibanaのDockerイメージを指定します。Elasticsearchのバージョンと合わせます。
      • container_name: kibana: コンテナに kibana という名前を付けます。
      • environment:: 環境変数を設定します。
        • ELASTICSEARCH_HOSTS=["http://elasticsearch:9200"]: Kibanaが接続するElasticsearchのURLを指定します。Docker Composeのデフォルトネットワークでは、サービス名をホスト名として使用できるため、elasticsearch というサービス名でElasticsearchコンテナにアクセスできます。
        • ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD: (コメントアウトされています) Elasticsearchでセキュリティを有効化している場合、KibanaがElasticsearchに接続するための認証情報を設定する必要があります。
      • ports:: ホストマシンとコンテナ間のポートマッピングを設定します。
        • "5601:5601": ホストの5601ポートをコンテナの5601ポートにマッピング(Kibana UI)。
      • depends_on:: サービスの依存関係を設定します。
        • - elasticsearch: Kibanaサービスは elasticsearch サービスに依存しているため、Elasticsearchが起動するまでKibanaは起動を待ちます。
      • mem_limit: 1g: Kibanaコンテナのメモリ使用上限を設定します。
  • volumes:: Docker Volumeを定義します。
    • elasticsearch-data:: elasticsearch-data という名前のDocker Volumeを定義します。
      • driver: local: ローカルファイルシステムにデータを保存します。

セットアップの手順

  1. 上記の docker-compose.yml ファイルを作成し、任意のディレクトリに保存します(例: ~/elasticsearch-docker/docker-compose.yml)。
  2. ターミナルまたはコマンドプロンプトで、そのディレクトリに移動します。
  3. 以下のコマンドを実行して、ElasticsearchとKibanaコンテナを起動します。

    bash
    docker compose up -d

    または Docker Compose V1 の場合:

    bash
    docker-compose up -d

    このコマンドは、必要なDockerイメージ(ElasticsearchとKibana)をDocker Hubからダウンロードし、docker-compose.yml の定義に基づいてコンテナ、ネットワーク、ボリュームを作成・起動します。-d オプションにより、コンテナはバックグラウンドで実行されます。

  4. コンテナが正常に起動したか確認します。

    bash
    docker compose ps

    StateUp になっていることを確認してください。起動には数分かかる場合があります。ログを確認したい場合は docker compose logs または docker compose logs elasticsearchdocker compose logs kibana を実行してください。

  5. X-Pack Basic Security が有効な場合(デフォルト)

    Elasticsearch 8.x以降では、デフォルトでセキュリティが有効になっています。docker compose up を初めて実行した際、Elasticsearchコンテナのログに、デフォルトユーザー(elastic, kibanaなど)の初期パスワードと、KibanaをElasticsearchに登録するためのエンロールメントトークンが表示されます。これらの情報は非常に重要なので、必ず控えておいてください。

    ログの確認方法:

    bash
    docker compose logs elasticsearch

    出力の中に以下のような情報が含まれています。

    “`

    To get started with security, build on the following information:

    Authentication and authorization

    Built-in user

    id: elastic

    password: <– これが初期パスワード

    Built-in user

    id: kibana_system

    password:

    Configure Kibana to use this cluster:

    -> Run ‘elasticsearch-create-enrollment-token –scope kibana’ on Elasticsearch node

    -> Paste result into Kibana ‘Enrollment token’ field on first launch

    Alternatively, configure Kibana manually:

    Edit the Kibana configuration file [] to set:

    elasticsearch.hosts: [“http://elasticsearch:9200”]

    elasticsearch.username: “kibana_system”

    elasticsearch.password: “

    Read the docs at https://www.elastic.co/guide/en/elasticsearch/reference/8.x/security-minimal-setup.html


    “`

    初期パスワードは毎回起動時に生成されるわけではなく、データディレクトリが空の状態で起動された場合にのみ生成されます。データが永続化されている(elasticsearch-data Volumeが存在する)場合は生成されません。その場合は、以前のパスワードを使用するか、パスワードリセットの手順を実行する必要があります。

    Kibanaにアクセスすると、エンロールメントトークンまたはElasticsearchのユーザー名/パスワード(elasticユーザーなど)を求められます。ログに出力されたエンロールメントトークンを入力するか、elasticユーザーの初期パスワードを入力してログインしてください。ログイン後、パスワードの変更を促される場合があります。

    X-Pack Basic Security を無効化した場合

    docker-compose.ymlxpack.security.enabled=false を設定した場合は、認証なしでElasticsearch REST API (http://localhost:9200) および Kibana (http://localhost:5601) にアクセスできます。入門・学習目的ではこちらの設定の方が手軽です。ただし、前述の通り、本番環境やインターネットに公開する環境では絶対に無効化しないでください。

これで、Docker Composeを使ったElasticsearchとKibanaの環境セットアップは完了です。

Kibanaのセットアップ

前章でDocker Composeを使ってElasticsearchと同時にKibanaもセットアップしました。ここでは、Kibanaの役割と基本的な使い方について説明します。

Kibanaの役割

Kibanaは、Elasticsearchのデータを探索、可視化、管理するためのオープンソースのユーザーインターフェースです。主な機能は以下の通りです。

  • Discover: Elasticsearchに格納されたドキュメントを検索し、表示する機能。
  • Visualize: 棒グラフ、円グラフ、マップなど、様々な形式でデータを可視化する機能。
  • Dashboard: 複数の可視化を組み合わせて、データを俯瞰できるダッシュボードを作成する機能。
  • Dev Tools: Elasticsearch REST APIに直接リクエストを送信し、応答を確認できる開発者ツール。インデックス作成、データ投入、検索クエリの実行などに非常に便利です。

本記事では、主にDev Toolsを使ってElasticsearchの基本的な操作を行います。

Elasticsearchとの連携設定

Docker Composeファイルで ELASTICSEARCH_HOSTS=["http://elasticsearch:9200"] という環境変数を設定したことにより、Kibanaは起動時に同じDockerネットワーク内の elasticsearch というホスト名(サービス名)でElasticsearchコンテナを探し、ポート9200で接続を試みます。

セキュリティが有効な場合、Kibanaはさらに認証情報を要求します。前述の通り、初回起動時にログに出力されたエンロールメントトークンを使用するか、ユーザー名とパスワードを設定します。

Kibanaへのアクセス

Docker ComposeでKibanaを起動し、ホストマシンのポート5601にマッピングした場合、ブラウザから以下のURLにアクセスできます。

http://localhost:5601

セキュリティが有効な場合は、ログイン画面が表示されます。認証情報を入力してログインしてください。

ログイン後、Kibanaのホーム画面が表示されます。左側のナビゲーションメニューから各機能にアクセスできます。

Elasticsearchの基本的な操作 (Kibana Dev Toolsを使用)

Kibana Dev Toolsは、ElasticsearchのREST APIを簡単に操作できる強力なツールです。GET, POST, PUT, DELETEなどのHTTPメソッドを使って、Elasticsearchに対して各種リクエストを送信し、その応答を確認できます。

Dev Toolsにアクセスするには、Kibanaの左側のナビゲーションメニューで「Management」(または「Management」配下の「Dev Tools」)を選択し、「Dev Tools」をクリックします。

Dev Toolsの画面は、左側にリクエストを入力するエディタ、右側にレスポンスが表示されるコンソールに分かれています。


(画像はイメージです。KibanaのバージョンによってUIは異なる場合があります。)

左側のエディタにElasticsearch APIへのリクエストを記述し、右側の実行ボタン(三角形の再生ボタン)をクリックして実行します。

インデックスの作成

データを格納するためには、まずインデックスを作成する必要があります。インデックス作成時には、Mappingを定義することもできますが、ここではMappingを指定しない基本的な作成方法を行います。Mappingを指定しない場合、最初のドキュメントが追加されたときにDynamic MappingによってMappingが自動的に推測されます。

リクエスト:

json
PUT /my_first_index

  • PUT: HTTPメソッド。新しいリソースを作成または既存のリソースを更新する際に使用します。
  • /my_first_index: 作成するインデックスの名前です。/_cat/indices など、_ で始まるパスは特殊なAPIエンドポイントです。

エディタに上記のコマンドを入力し、実行ボタンをクリックします。成功すると、右側のコンソールに以下のようなレスポンスが表示されます。

json
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "my_first_index"
}

これで my_first_index という名前のインデックスが作成されました。

インデックスが作成されたか確認するには、以下のリクエストを実行します。

json
GET /_cat/indices?v

  • GET: HTTPメソッド。リソースを取得する際に使用します。
  • /_cat/indices: ElasticsearchのCat APIと呼ばれるAPI群の一つで、クラスタやインデックスの状態を簡潔なテキスト形式で表示します。
  • ?v: 詳細なヘッダー情報(カラム名)を表示するパラメータです。

レスポンスには、作成されたインデックスを含む、クラスター内のインデックス一覧が表示されます。

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open my_first_index r_xxxxxxxxxxxxxxxxxxxx 1 1 0 0 225b 225b
green open .kibana_N y_yyyyyyyyyyyyyyyyyyyy 1 1 24 0 500.1kb 250.0kb
... (他の内部インデックスも表示されます)

my_first_index が表示され、docs.count0 であることを確認できます。

ドキュメントの追加 (Indexing)

インデックスを作成したら、そこにドキュメントを追加できます。ドキュメントの追加(インデックス作成)は、POST または PUT メソッドを使って行います。

自動生成IDで追加:

Elasticsearchに自動でユニークなIDを生成させてドキュメントを追加するには、POST メソッドを使います。

リクエスト:

json
POST /my_first_index/_doc
{
"title": "Dockerを使ったElasticsearch入門",
"author": "Alice",
"publish_date": "2023-10-28T09:00:00Z",
"content": "これはElasticsearchに投入する最初のドキュメントです。"
}

  • POST: HTTPメソッド。新しいリソースを作成する際に使用します。
  • /my_first_index/_doc: インデックス名 (my_first_index) とタイプ (_doc) を指定します。前述の通り、7.x以降はタイプとして _doc を使用するのが一般的です。
  • リクエストボディには、追加したいドキュメントのJSONデータを記述します。

実行すると、Elasticsearchはドキュメントを受け付け、ユニークなIDを自動生成して割り当てます。レスポンスには生成されたIDなどが含まれます。

json
{
"_index": "my_first_index",
"_id": "abcdefg...", // 自動生成されたID
"_version": 1,
"result": "created",
"_shards": {
"shard": 0,
"total": 2,
"successful": 1
},
"_seq_no": 0,
"_primary_term": 1
}

_id フィールドに自動生成されたドキュメントIDが表示されます。

明示的なIDで追加/更新:

独自のIDを指定してドキュメントを追加または更新するには、PUT メソッドを使います。指定したIDのドキュメントが既に存在する場合は更新、存在しない場合は新規作成されます。

リクエスト:

json
PUT /my_first_index/_doc/my_document_id_1
{
"title": "Kibana Dev Toolsの使い方",
"author": "Bob",
"publish_date": "2023-10-28T10:00:00Z",
"content": "KibanaのDev Toolsを使ってElasticsearchを操作する方法を説明します。"
}

  • PUT: HTTPメソッド。
  • /my_first_index/_doc/my_document_id_1: インデックス名、タイプに続けて、明示的に指定するドキュメントID (my_document_id_1) をパスに含めます。

実行すると、指定したIDでドキュメントが格納されます。レスポンスには指定したIDが含まれます。

json
{
"_index": "my_first_index",
"_id": "my_document_id_1", // 指定したID
"_version": 1,
"result": "created", // または "updated"
"_shards": {
"shard": 0,
"total": 2,
"successful": 1
},
"_seq_no": 1, // シーケンス番号
"_primary_term": 1
}

さらにいくつかドキュメントを追加して、後の検索に備えましょう。

json
POST /my_first_index/_doc
{
"title": "Elasticsearchのデータ永続化",
"author": "Alice",
"publish_date": "2023-10-28T11:00:00Z",
"content": "Dockerを使ったElasticsearchでデータを永続化する方法は重要です。"
}

json
POST /my_first_index/_doc
{
"title": "Docker Composeで始めるElastic Stack",
"author": "Charlie",
"publish_date": "2023-10-28T12:00:00Z",
"content": "Docker Composeを使えば、ElasticsearchとKibanaだけでなく、LogstashやBeatsも一緒に管理できます。"
}

ドキュメントを追加した後、インデックスの状態を再度確認してみましょう。

json
GET /_cat/indices?v

my_first_indexdocs.count が追加したドキュメントの数だけ増えているはずです。

ドキュメントの取得 (Getting)

特定のIDを持つドキュメントを取得するには、GET メソッドを使います。

リクエスト:

json
GET /my_first_index/_doc/my_document_id_1

  • GET: HTTPメソッド。
  • /my_first_index/_doc/my_document_id_1: 取得したいインデックス名、タイプ、ドキュメントIDをパスに含めます。

実行すると、指定したIDのドキュメントがレスポンスの _source フィールドに含まれて返されます。

json
{
"_index": "my_first_index",
"_id": "my_document_id_1",
"_version": 1,
"_seq_no": 1,
"_primary_term": 1,
"found": true, // ドキュメントが見つかったか
"_source": { // ドキュメントの元データ
"title": "Kibana Dev Toolsの使い方",
"author": "Bob",
"publish_date": "2023-10-28T10:00:00Z",
"content": "KibanaのDev Toolsを使ってElasticsearchを操作する方法を説明します。"
}
}

もし指定したIDのドキュメントが見つからない場合は、"found": false となり、_source フィールドは含まれません(または {})。

ドキュメントの更新 (Updating)

既存のドキュメントを更新するには、いくつかの方法があります。最も一般的なのは、POST メソッドと _update エンドポイントを使う方法です。この方法は、ドキュメント全体を送信し直すことなく、一部のフィールドだけを更新したり、既存のフィールドを削除したり、スクリプトを使って複雑な更新を行ったりできます。

リクエスト(部分更新):

例えば、IDが my_document_id_1 のドキュメントに新しいタグを追加したい場合。

json
POST /my_first_index/_update/my_document_id_1
{
"doc": {
"tags": ["kibana", "dev tools", "elasticsearch"]
}
}

  • POST: HTTPメソッド。
  • /my_first_index/_update/my_document_id_1: 更新したいインデックス名、タイプ、ドキュメントIDに続けて _update を指定します。
  • リクエストボディの doc フィールド内に、更新したいフィールドとその新しい値を記述します。

実行すると、指定したフィールドがドキュメントにマージされます。

json
{
"_index": "my_first_index",
"_id": "my_document_id_1",
"_version": 2, // バージョン番号が増加
"result": "updated",
"_shards": {
"shard": 0,
"total": 2,
"successful": 1
},
"_seq_no": 2,
"_primary_term": 1
}

再度 GET /my_first_index/_doc/my_document_id_1 を実行して、ドキュメントが更新されたことを確認してください。

ドキュメントの削除 (Deleting)

特定のIDを持つドキュメントを削除するには、DELETE メソッドを使います。

リクエスト:

json
DELETE /my_first_index/_doc/my_document_id_1

  • DELETE: HTTPメソッド。リソースを削除する際に使用します。
  • /my_first_index/_doc/my_document_id_1: 削除したいインデックス名、タイプ、ドキュメントIDをパスに含めます。

実行すると、指定したIDのドキュメントが削除されます。

json
{
"_index": "my_first_index",
"_id": "my_document_id_1",
"_version": 3,
"result": "deleted",
"_shards": {
"shard": 0,
"total": 2,
"successful": 1
},
"_seq_no": 3,
"_primary_term": 1
}

再度 GET /my_first_index/_doc/my_document_id_1 を実行すると、"found": false という結果が返されるはずです。

基本的な検索 (Searching)

Elasticsearchの最も強力な機能は検索です。ここでは、基本的な検索クエリをいくつか試します。検索は通常 GET または POST メソッドを使って _search エンドポイントにリクエストを送信することで行います。複雑なクエリはリクエストボディにJSON形式で記述するため、POST メソッドがよく使われます。

全件検索:

インデックス内のすべてのドキュメントを検索するには、match_all クエリを使います。

リクエスト:

json
POST /my_first_index/_search
{
"query": {
"match_all": {}
}
}

  • POST /my_first_index/_search: my_first_index インデックスに対して検索リクエストを送信します。
  • リクエストボディの query フィールドに検索クエリを記述します。
  • "match_all": {}: すべてのドキュメントにマッチするクエリです。

レスポンスには、検索結果が hits フィールドに含まれて返されます。

json
{
"took": 12, // 検索にかかった時間 (ミリ秒)
"timed_out": false,
"_shards": { ... },
"hits": {
"total": { // 合計ヒット数
"value": 3,
"relation": "eq"
},
"max_score": 1.0, // 最大スコア (関連度)
"hits": [ // 検索結果のドキュメントリスト
{
"_index": "my_first_index",
"_id": "...",
"_score": 1.0,
"_source": { ... } // ドキュメントの元データ
},
{
"_index": "my_first_index",
"_id": "...",
"_score": 1.0,
"_source": { ... }
},
{
"_index": "my_first_index",
"_id": "...",
"_score": 1.0,
"_source": { ... }
}
]
}
}

削除したドキュメントを除く、現在インデックスに存在するすべてのドキュメントが返されます。

キーワード検索 (match クエリ):

特定のフィールドに含まれるキーワードで検索するには、match クエリを使います。match クエリは、指定されたフィールドのAnalyzerを使って検索語を分析し、インデックスされた単語とマッチさせます。

リクエスト:

例えば、content フィールドに「Docker」という単語が含まれるドキュメントを検索したい場合。

json
POST /my_first_index/_search
{
"query": {
"match": {
"content": "Docker"
}
}
}

実行すると、content フィールドに「Docker」という単語(または、Analyzerによって処理された同義語など)が含まれるドキュメントが返されます。

複数の単語で検索する場合、match クエリはデフォルトではOR検索になります(いずれかの単語を含むドキュメントがヒット)。AND検索にしたい場合は、operator オプションを and に設定します。

json
POST /my_first_index/_search
{
"query": {
"match": {
"content": {
"query": "Docker Kibana",
"operator": "and"
}
}
}
}

完全一致検索 (term クエリ):

Analyzerによる単語分割や正規化を行わず、指定した単語(term)と完全に一致するドキュメントを検索するには、term クエリを使います。term クエリは、通常、Analyzerが適用されないフィールド(キーワードフィールドなど)や、正確な単語一致が求められる場合に使用します。

リクエスト:

例えば、author フィールドが正確に「Alice」であるドキュメントを検索したい場合。

json
POST /my_first_index/_search
{
"query": {
"term": {
"author.keyword": "Alice"
}
}
}

  • "author.keyword": フィールド名に .keyword を付けています。文字列フィールドは、デフォルトで全文検索用のテキストフィールド(分析される)と、完全一致検索用のキーワードフィールド(分析されない)の両方としてインデックス化されることが多いです。キーワードフィールドはフィールド名に .keyword が付加されます。
  • "Alice": 検索したい正確な単語(term)です。

実行すると、author.keyword フィールドの値が正確に「Alice」であるドキュメントが返されます。

複合条件検索 (Bool クエリ):

複数の検索条件を組み合わせるには、bool クエリを使います。bool クエリは以下の句(clause)を組み合わせて検索条件を構築します。

  • must: 指定されたクエリがすべて真である必要がある(AND条件)。スコア計算に影響します。
  • filter: 指定されたクエリがすべて真である必要がある(AND条件)。スコア計算には影響しません(高速です)。
  • should: 指定されたクエリのいずれかが真であればよい(OR条件)。スコア計算に影響します。mustfilter がない場合、少なくとも1つの should がマッチする必要があります。
  • must_not: 指定されたクエリがすべて偽である必要がある(NOT条件)。スコア計算には影響しません。

リクエスト:

例えば、「Docker」を含むドキュメントの中から、author が「Alice」であるものだけを検索したい場合。

json
POST /my_first_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "content": "Docker" } }
],
"filter": [
{ "term": { "author.keyword": "Alice" } }
]
}
}
}

  • "must": [ { "match": { "content": "Docker" } } ]: content フィールドに「Docker」を含むという条件(スコア計算あり)。
  • "filter": [ { "term": { "author.keyword": "Alice" } } ]: author.keyword フィールドが「Alice」であるという条件(スコア計算なし、高速)。

filter を使うことで、単に条件を絞り込むだけでスコアを重視しない場合にパフォーマンスを向上させることができます。

範囲検索 (Range クエリ):

数値や日付のフィールドに対して範囲で検索するには、range クエリを使います。

リクエスト:

例えば、2023年10月28日以降に公開されたドキュメントを検索したい場合。

json
POST /my_first_index/_search
{
"query": {
"range": {
"publish_date": {
"gte": "2023-10-28T00:00:00Z" # Greater Than or Equal (以上)
// "gt": "...", # Greater Than (より大きい)
// "lte": "...", # Less Than or Equal (以下)
// "lt": "...", # Less Than (より小さい)
}
}
}
}

  • "publish_date": 範囲検索を適用するフィールド名。日付フィールドは適切にMappingされている必要があります。
  • "gte": "2023-10-28T00:00:00Z": 2023年10月28日午前0時以降という条件です。

これらの基本的なクエリを組み合わせることで、様々な検索ニーズに対応できます。Elasticsearchの検索クエリは非常に豊富で強力です。詳細については、Elasticsearchの公式ドキュメントを参照してください。

インデックスの削除

作成したインデックスが不要になったら、削除できます。

リクエスト:

json
DELETE /my_first_index

  • DELETE: HTTPメソッド。
  • /my_first_index: 削除したいインデックスの名前をパスに含めます。

実行すると、指定したインデックスとその中のすべてのドキュメントが削除されます。

json
{
"acknowledged": true
}

acknowledged: true となれば削除成功です。

GET /_cat/indices?v でインデックス一覧を確認し、my_first_index が表示されなくなったことを確認してください。

DockerとElasticsearchを使う上での注意点

Dockerを使うことでElasticsearchのセットアップは容易になりますが、運用上または開発上で注意すべき点がいくつかあります。

メモリ設定の重要性 (Swap無効化)

ElasticsearchはJavaで記述されており、JVM上で動作します。JVMはガーベージコレクション(GC)のために大きなメモリ領域(ヒープ)を必要とします。Elasticsearchは大量のデータをメモリ(ファイルシステムキャッシュやLuceneの内部構造)に保持しようとするため、十分な物理メモリが必要です。

Elasticsearchにとって最もパフォーマンスを低下させる要因の一つがSwappingです。Swappingとは、物理メモリが不足した際にOSがメモリの一部をディスクに退避させる仕組みです。ディスクへのアクセスはメモリへのアクセスに比べて非常に遅いため、ElasticsearchでSwappingが発生すると、検索やインデックス作成の応答時間が劇的に悪化します。

この問題を避けるため、以下の設定が推奨されます。

  1. Javaヒープサイズの設定 (ES_JAVA_OPTS): Elasticsearchコンテナの環境変数 ES_JAVA_OPTS でJVMのヒープサイズ(-Xms-Xmx)を設定します。通常、-Xms-Xmx は同じ値に設定し、割り当てるメモリ量は物理メモリの半分以下にするのがベストプラクティスです。残りのメモリはOSやLuceneのファイルシステムキャッシュのために使用されます。
  2. Dockerコンテナのメモリ制限 (mem_limit): Docker Composeファイルの mem_limit で、そのコンテナが使用できる合計メモリ量に上限を設定します。この値は、Javaヒープサイズよりも大きな値にする必要があります(OSやその他のプロセスが使用するメモリ分)。
  3. Swappingの無効化 (ulimits.memlock): docker-compose.ymlulimits.memlock 設定で、Elasticsearchプロセスがメモリをロックし、OSによるSwappingを防ぐようにします。この設定を有効にするためには、ホストOS側でユーザーに対するメモリロックの制限が解除されている必要があります(ulimit -l unlimited など)。Docker Desktop for Mac/Windows/Linux(WSL2) を使用している場合は、Docker Desktop側の設定が適用されます。

これらの設定が適切に行われていないと、Elasticsearchの起動に失敗したり、起動してもすぐに不安定になったり、性能が出なかったりする原因となります。特に開発環境で小さなメモリしか割り当てられない場合は、データ量が増えるとすぐに問題が発生する可能性があります。

永続化ストレージの設定 (Docker Volume推奨)

Dockerコンテナはデフォルトでは一時的なストレージを使用します。コンテナを削除すると、コンテナ内に保存されていたデータ(Elasticsearchのインデックスデータなど)は失われます。開発用途であっても、データを保持したい場合は永続化の設定が必須です。

docker-compose.ymlvolumes 設定で、Elasticsearchコンテナのデータディレクトリ(通常 /usr/share/elasticsearch/data)をDocker Volumeにマウントするのが推奨される方法です。

“`yaml
services:
elasticsearch:

volumes:
– elasticsearch-data:/usr/share/elasticsearch/data # Volumeをマウント

volumes:
elasticsearch-data: # Volume定義
driver: local
“`

これにより、データはDockerが管理するストレージ領域に保存され、コンテナを停止・削除してもデータは失われません。次に同じVolumeを使ってコンテナを起動すると、以前のデータがロードされます。

バージョン管理

ElasticsearchとKibanaは密接に連携するため、バージョンを一致させる必要があります。Dockerイメージを取得する際には、elasticsearch:<version> および kibana:<version> のように、必ず同じバージョンタグを指定するようにしてください。異なるバージョンを使用すると、互いに接続できなかったり、予期しないエラーが発生したりする可能性があります。

Docker Composeファイルでバージョンを管理しておけば、常に同じバージョンのElasticsearchとKibana環境を再現できて便利です。

本番環境での考慮事項

この記事で紹介したDocker Compose設定は、あくまでローカルでの開発・学習環境向けです。本番環境でElasticsearchを運用する際には、さらに以下の点を考慮する必要があります。

  • クラスター構成: 単一ノードではなく、複数のノードでクラスターを構成し、データの分散と高可用性を実現します。
  • メモリとディスクI/O: 大量のデータを扱うため、十分なメモリと高速なディスクI/O(SSDなど)を備えたサーバーが必要です。
  • ネットワーク: ノード間の通信やクライアントからのアクセスを考慮したネットワーク設計が必要です。
  • セキュリティ: X-Pack Basic 以上のセキュリティ機能を有効化し、認証、認可、TLS/SSL通信などを設定します。インターネットに公開する場合は、ファイアウォールなどでアクセス制限を厳重に行う必要があります。
  • 監視とアラート: Elasticsearchクラスターの状態(ノードの状態、ディスク使用量、リクエストレイテンシなど)を監視し、問題発生時にアラートを通知する仕組み(Metricbeat, Heartbeat, Watcherなど)が必要です。
  • バックアップ: 定期的にSnapshotを作成し、異なるストレージにバックアップする仕組みが必要です。
  • 設定ファイルの管理: 環境変数だけでなく、より詳細な設定は elasticsearch.yml ファイルで行い、それをDockerコンテナにマウントして使用するのが一般的です。

Dockerは本番環境でのデプロイにも利用できますが、Docker SwarmやKubernetesといったコンテナオーケストレーションツールと組み合わせて使用することが多いです。

セキュリティ (X-Pack Basic)

Elasticsearch 8.x以降では、デフォルトでX-Pack Basicセキュリティ機能が有効になっています。これにより、ユーザー認証やノード間の暗号化通信などがデフォルトで提供されます。

開発・学習目的で認証なしで手軽に利用したい場合は、xpack.security.enabled=false 環境変数を設定してセキュリティを無効化することも可能ですが、これはあくまで一時的なローカル環境でのみ行うべきです。

セキュリティを有効にしたまま使用する場合、起動時にElasticsearchコンテナのログに出力される初期パスワードやエンロールメントトークンを使用してKibanaにログインします。ログイン後、elastic ユーザーなどのデフォルトユーザーのパスワードを変更したり、必要に応じて新しいユーザーを作成したりする必要があります。

KibanaのDev Toolsを使って、ユーザーやロールを管理するAPIを呼び出すことができます。例えば、ユーザーを追加するAPIは以下のようになります(要適切な権限と認証)。

json
POST /_security/user/my_new_user
{
"password" : "secure_password",
"roles" : [ "kibana_user", "data_reader" ],
"full_name" : "My New User"
}

セキュリティ機能の詳細は複雑ですが、入門段階でも「デフォルトでセキュリティが有効になっていること」「開発環境で一時的に無効化できること」「本番環境では必須の設定であること」を認識しておくことが重要です。

少し進んだトピック (概要)

入門ガイドとしてはここまでで十分ですが、Elasticsearchの世界はさらに広がっています。ここでは、次の一歩として学ぶべき、少し進んだトピックを簡単に紹介します。

  • Ingest Node: ドキュメントがインデックスに追加される前に、そのデータを変換・加工するためのノードです。データの正規化、エンリッチメント、特定のフィールドの抽出などを行えます。Logstashを使う代わりに、Ingest Nodeで簡単な前処理を行うことも可能です。
  • Analyzer (カスタマイズ): 前述のAnalyzerは、検索精度に大きく影響します。特に日本語など、英語以外の言語を扱う場合は、その言語に特化したAnalyzer(例: Kuromoji for Japanese)を適切に設定する必要があります。独自のAnalyzerを作成して、特定のビジネス要件に合わせたテキスト処理を行うことも可能です。
  • Aggregation (集計): Elasticsearchは強力な集計機能を持っています。検索結果に対して、統計情報の計算(平均、合計、最小値、最大値など)、グルーピング(SQLのGROUP BYに相当)、バケット化(範囲や間隔でデータを分割)などを行うことができます。これにより、データの分析やBI(ビジネスインテリジェンス)レポートの作成が容易になります。KibanaのVisualize機能は、ElasticsearchのAggregationを利用してグラフなどを描画します。
  • Snapshot and Restore: Elasticsearchクラスターのデータをバックアップし、必要に応じてリストアする機能です。リモートリポジトリ(S3、HDFS、共有ファイルシステムなど)にSnapshotを保存できます。定期的なバックアップは、障害発生時のデータ復旧や、新しいクラスター環境へのデータ移行に不可欠です。
  • Elastic Stack (Logstash, Beats): Elasticsearchはしばしば他のElastic製品群と組み合わせて利用されます。
    • Logstash: 様々なソース(ログファイル、データベース、メッセージキューなど)からデータを収集、変換、そしてElasticsearchに送信するためのサーバーサイドデータ処理パイプラインです。
    • Beats: Lightweight data shippers. サーバー、コンテナ、ネットワークなどから特定の種類のデータ(システムメトリクス、ログファイル、ネットワークパケットなど)を収集し、ElasticsearchまたはLogstashに送信するための軽量エージェント群です。
      これらを組み合わせることで、複雑なデータ収集・分析パイプラインを構築できます。例えば、Filebeatでログファイルを収集し、Logstashでログをパースして構造化し、Elasticsearchに投入し、Kibanaで可視化するといった典型的なログ分析のワークフローが実現できます。

これらのトピックは、Elasticsearchをより深く使いこなすために非常に重要です。入門後、ご自身の興味やニーズに合わせて学習を進めてみてください。

まとめ

この記事では、Dockerを使ってElasticsearchのローカル開発・学習環境を構築し、基本的な操作を行う方法を詳細に解説しました。

  • まず、Elasticsearchの基本的な概念(ドキュメント、インデックス、クラスター、ノード、シャード、レプリカなど)を理解しました。
  • 次に、DockerとDocker Composeの準備を行い、docker-compose.yml ファイルを使ってElasticsearchとKibanaのサービスを定義・起動する手順を学びました。特に、メモリ設定やデータ永続化、セキュリティ設定といった重要な考慮事項についても触れました。
  • Kibanaの役割と、Dev Toolsを使ったElasticsearchの基本的なCRUD操作(インデックス作成、ドキュメント追加、取得、更新、削除)および基本的な検索(match_all, match, term, bool, range クエリ)の方法を実践しました。
  • 最後に、DockerとElasticsearchを運用する上での注意点や、次ステップとして学ぶべき少し進んだトピックについて概説しました。

Dockerを使うことで、複雑な依存関係や設定に悩まされることなく、迅速にElasticsearch環境を立ち上げて試すことができることを実感いただけたかと思います。これは、Elasticsearchの学習を始める上での大きなアドバンテージとなります。

Elasticsearchは非常に多機能で奥深いプロダクトです。この記事はあくまでその入り口に過ぎません。ぜひ、この記事で得た知識を基に、さらに複雑な検索クエリ、Aggregationを使った分析、他のElastic Stack製品との連携、そして本番環境での運用など、Elasticsearchの様々な可能性を探求してみてください。

付録:よくあるエラーとその対処法

Docker環境でElasticsearchを起動・利用する際によく遭遇するエラーとその対処法をいくつか紹介します。

1. メモリ不足またはSwappingに関連するエラー

Elasticsearchはメモリ要求の高いアプリケーションです。Javaヒープサイズや物理メモリが不足している場合、あるいはSwappingが発生している場合に起動に失敗したり、不安定になったりします。

エラー例:

  • コンテナ起動中に停止する、またはステータスが unhealthy になる。
  • ログに OutOfMemoryError が出力される。
  • ログに max virtual memory areas vm.max_map_count [xxxx] is too low, increase to at least [262144] のようなメッセージが出力される。
  • 検索やインデックス作成のパフォーマンスが非常に遅い。

対処法:

  1. vm.max_map_count の設定: Linuxホストの場合、デフォルトの仮想メモリマップの最大数がElasticsearchの要件を満たさないことがあります。ホストOSで以下のコマンドを実行して設定を変更する必要があります。

    bash
    sudo sysctl -w vm.max_map_count=262144

    この設定は永続的ではないため、システム再起動後も有効にするには /etc/sysctl.conf ファイルに vm.max_map_count=262144 を追記してください。Docker Desktop for Mac/Windows/Linux(WSL2) の場合は、通常この設定はDocker Desktopが管理するため不要です。

  2. Javaヒープサイズ (ES_JAVA_OPTS) の調整: docker-compose.yml で設定した ES_JAVA_OPTS の値を増やしてみてください。ただし、ホストマシンの物理メモリの半分を超えないように注意してください。例えば物理メモリが4GBなら最大で2GB程度までです。開発環境であれば、最低でも512MB〜1GB程度を割り当てるのが望ましいです。

  3. Dockerメモリ制限 (mem_limit) の調整: docker-compose.ymlmem_limit の値を増やしてみてください。これは ES_JAVA_OPTS の値よりも大きくする必要があります。
  4. ulimits.memlock の確認: docker-compose.ymlulimits.memlock が正しく設定されていることを確認してください。また、ホストOS側でElasticsearchプロセスがメモリをロックできる権限があるか確認してください(Linuxの場合、ulimit -l unlimited コマンドや /etc/security/limits.conf ファイルの設定を確認)。
  5. ホストマシンの物理メモリ増設: 根本的な解決策は、Elasticsearchに十分なメモリを割り当てられるように、ホストマシンの物理メモリを増設することです。

2. ポート競合エラー

ElasticsearchやKibanaが使用するポート(デフォルトで9200, 9300, 5601)が、ホストマシンの他のプロセスによって既に使われている場合に発生します。

エラー例:

  • コンテナ起動時に Bind for 0.0.0.0:9200 failed: port is already allocated のようなエラーメッセージが出力される。

対処法:

  1. ポート使用状況の確認: ホストマシンで問題のポートが使用されているか確認します。
    • Linux/macOS: sudo lsof -i :<port_number> または netstat -tulnp | grep <port_number>
    • Windows: netstat -ano | findstr :<port_number>
      使用しているプロセスがあれば、そのプロセスを停止するか、Elasticsearch/Kibanaで使用するポート番号を変更してください。
  2. Docker Composeファイルでのポート変更: docker-compose.yml ファイルの ports マッピング設定で、ホスト側のポート番号を変更します。

    yaml
    services:
    elasticsearch:
    ...
    ports:
    - "9201:9200" # ホストの9201ポートをコンテナの9200ポートにマッピング
    - "9301:9300" # ホストの9301ポートをコンテナの9300ポートにマッピング
    ...
    kibana:
    ...
    ports:
    - "5602:5601" # ホストの5602ポートをコンテナの5601ポートにマッピング
    ...

    ポートを変更した場合、Elasticsearch/KibanaへのアクセスURLも変更後のポート番号(例: http://localhost:9201, http://localhost:5602)を使用する必要があります。また、Kibanaの ELASTICSEARCH_HOSTS 設定はコンテナ内部のポート(9200)を指定するため変更不要です。

3. Discovering failed / クラスター参加エラー

単一ノードモード (discovery.type=single-node) の設定がされていない場合や、ネットワーク設定に問題がある場合に、Elasticsearchが他のノードを見つけようとして起動に失敗することがあります。

エラー例:

  • ログに Likely encountering a host firewall or an AWS security group configuration issue.timed out while waiting for initial discovery のようなメッセージが出力される。

対処法:

  1. 単一ノード設定の確認: docker-compose.yml の Elasticsearch サービス定義に - discovery.type=single-node という環境変数が正しく設定されているか確認してください。
  2. ネットワーク設定の確認: Docker Composeのデフォルトネットワークが正しく動作しているか確認してください。もしカスタムネットワークを使用している場合は、ElasticsearchとKibanaが同じネットワーク上にあり、名前解決できる設定になっているか確認してください。
  3. ファイアウォールの確認: ホストマシンやネットワークのファイアウォールが、Dockerコンテナ間の通信やホストからコンテナへのポートアクセスをブロックしていないか確認してください。

4. KibanaからElasticsearchへの接続エラー

KibanaがElasticsearchに接続できない場合に発生します。

エラー例:

  • KibanaのUIで「Kibana server is not ready yet」と表示される。
  • Kibanaコンテナのログに [elasticsearch] Retrying connect to ElasticsearchAuthentication required のようなメッセージが出力される。

対処法:

  1. Elasticsearchコンテナの状態確認: まず、Elasticsearchコンテナが正常に起動しているか docker compose psdocker compose logs elasticsearch で確認します。
  2. KibanaのElasticsearchホスト設定: docker-compose.yml の Kibana サービス定義の ELASTICSEARCH_HOSTS 環境変数が、ElasticsearchコンテナにアクセスできるURL(Docker Composeネットワーク内のサービス名 http://elasticsearch:9200 など)を正しく指定しているか確認します。
  3. セキュリティ設定の確認: Elasticsearchでセキュリティ(X-Pack Basic)が有効になっている場合、Kibanaも認証情報が必要です。
    • Kibanaコンテナの ELASTICSEARCH_USERNAME および ELASTICSEARCH_PASSWORD 環境変数に正しい認証情報(例: elastic ユーザーとそのパスワード)を設定しているか確認してください。
    • 初回起動時は、Elasticsearchコンテナのログに出力されたエンロールメントトークンを使ってKibanaを登録する必要があります。Kibanaにアクセスした際に表示される指示に従ってください。
    • もし xpack.security.enabled=false でセキュリティを無効化している場合は、認証情報は不要です。設定が docker-compose.yml で有効になっているか確認してください。
  4. バージョンの一致: ElasticsearchとKibanaのバージョンが一致しているか再度確認してください。

これらの一般的なエラーと対処法を把握しておくと、トラブルシューティングがスムーズに行えます。

参考資料

これらの公式ドキュメントは、ElasticsearchとDockerをさらに深く理解するために非常に役立ちます。特にElasticsearchのドキュメントには、検索クエリ、Mapping、Aggregationなど、この記事で触れられなかった多くの機能に関する詳細な情報が記載されています。

これで、Dockerを使ってElasticsearchの基本的な環境構築から操作までを行うための入門ガイドは終わりです。Elasticsearchを使った開発やデータ分析を楽しんでください!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール