「Elasticsearch をクラスター構成で動かしたいけど、どこから手をつければいいか分からない」という方は多いはずです。結論から言うと、Docker Compose を使えば、Ubuntu 24.04 上に 3 ノード構成の Elasticsearch クラスターを 30 分以内に構築できます。
本記事では実際に docker.elastic.co/elasticsearch/elasticsearch:8.19.16(2026-06-14 時点の最新安定版)で 3 ノードクラスターを起動し、クラスターヘルス API で status: green / number_of_nodes: 3 を確認した実測結果を掲載しています。インデックスを作成してシャードが 3 ノードへ分散される様子(実測の _cat/shards 出力)まで載せました。
この記事のポイント
- Elasticsearch 8.19.16 の 3 ノードクラスターを Ubuntu 24.04 + Docker で構築する手順を実測済み(約 54 秒で green になりました)
cluster.initial_master_nodesとdiscovery.seed_hostsの設定が鍵——ここを間違えるとクラスターが形成されない- クラスターヘルス API(
/_cluster/health)で green / yellow / red を確認する方法を解説 - シャード数 3・レプリカ数 1 のインデックスを作ると 6 枚のシャードが 3 ノードへ分散される様子を実測
- VPS 3 台で本番構成を組む場合の最小スペックと Vultr/DigitalOcean のコスト試算
動作確認済み環境
Ubuntu 24.04.4 LTS(Docker 公式イメージ ubuntu:24.04 / arm64)/Docker Engine + Docker Compose v2/Elasticsearch・Kibana 8.19.16(docker.elastic.co 公式イメージ)/2026-06-14 実測
目次
- Elasticsearch クラスターとは何か
- 前提条件と必要スペック
- Elastic 公式リポジトリでバージョンを確認する
- Docker Compose でクラスターを構成する
- クラスターヘルスを確認する(実測)
- 本番向けインデックス設定とシャード分散(実測)
- Kibana で GUI から確認する
- CPU・ディスク性能の実測ベンチ
- VPS 3 台で本番構成を組む場合
- よくあるエラーと解決策
- まとめ
Elasticsearch クラスターとは何か
Elasticsearch(以下 ES)はシングルノードでも動きますが、本番環境では必ずクラスター構成にします。クラスターとは、複数の ES ノードが連携して一つのデータストアとして振る舞う仕組みです。ノードとは ES のプロセス 1 つ(≒コンテナ 1 つ)を指します。

3 ノード構成の主なメリットは次の 3 つです。
- 可用性:1 台が落ちても残り 2 台で継続稼働できる(過半数 = 2 台がいれば master 選出が可能)
- スループット:検索クエリが複数ノードに分散される
- データ保護:レプリカシャードが別ノードに配置されるため、1 台の SSD 障害でデータを失わない
正直、シングルノードで ES を動かしている記事はたくさんありますが、ノード間の discovery.seed_hosts 設定や split-brain 対策まで書いているものは少ないです。本記事ではそこを丁寧に解説します。
前提条件と必要スペック
手順1:OS とコンテナ実行環境を確認する
本記事は ES を apt で直接インストールせず、Docker 公式イメージで 3 ノードを起動します。まず OS が Ubuntu 24.04 系であること、Docker Engine と Docker Compose v2 が入っていることを確認します。下記は実際に ubuntu:24.04 コンテナで /etc/os-release を確認した実測出力です。
PRETTY_NAME=”Ubuntu 24.04.4 LTS”
$ dpkg –print-architecture
arm64
# Docker / Docker Compose v2 が入っているか確認
$ docker –version && docker compose version
Docker version 27.x, build …
Docker Compose version v2.x
Ubuntu 24.04 で Docker と Compose プラグインをまとめて入れるなら sudo apt install docker.io docker-compose-v2 が手軽です。docker compose version(ハイフンなし)が動けば v2 系が入っています。
ノードあたりの必要スペック
下表は用途別の目安です。本記事の学習用構成は 1 台の Docker ホストに 3 コンテナを同居させるため、ホスト全体で 4 GB 程度の RAM があると安定します。
| 用途 | vCPU | RAM | ストレージ | 備考 |
|---|---|---|---|---|
| 開発・学習用(本記事) | 2 | 4 GB | 20 GB | 1 ホストに 3 コンテナ/各ノード JVM ヒープ 512 MB |
| 小規模本番(数 GB インデックス) | 4 | 8 GB | 100 GB SSD | VPS 3 台に分散/JVM ヒープ = RAM の 50% が推奨上限 |
| 中規模本番(数十 GB〜) | 8+ | 32 GB | 500 GB SSD | ヒープは 30 GB 超えると GC 問題が出やすい |
vm.max_map_count の設定(本番では必須)
ES は大量の mmap を使うため、Docker ホストで sudo sysctl -w vm.max_map_count=262144 を設定しないと起動に失敗します。Docker Desktop(Mac/Windows)の内部 VM では既定で 262144 になっていますが、本番の Linux VPS では手動設定が必要です。永続化するには /etc/sysctl.d/99-elasticsearch.conf に vm.max_map_count=262144 を追記してください。
Elastic 公式リポジトリでバージョンを確認する
Docker イメージのタグは Elastic 公式 APT リポジトリのバージョンと一致します。今どのバージョンが最新安定版かを確認するため、実際に ubuntu:24.04 コンテナで Elastic 公式リポジトリを追加し apt-cache policy を叩いた結果が以下です。

| gpg –dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
$ echo “deb [signed-by=…] https://artifacts.elastic.co/packages/8.x/apt stable main” \
| sudo tee /etc/apt/sources.list.d/elastic-8.x.list
$ sudo apt-get update && apt-cache policy elasticsearch
elasticsearch:
Installed: (none)
Candidate: 8.19.16
Version table:
8.19.16 500
500 …/packages/8.x/apt stable/main arm64 Packages
8.19.15 500 …
(8.0.0 まで一覧が続く)
2026 年 6 月 14 日時点で、Elastic 公式 8.x リポジトリの最新候補は Elasticsearch・Kibana ともに 8.19.16 でした。本記事ではこのバージョンの Docker イメージ(docker.elastic.co/elasticsearch/elasticsearch:8.19.16)を使います。
Docker Compose でクラスターを構成する
手順2:プロジェクトディレクトリを作る
手順3:docker-compose.yml を作る
以下が 3 ノード構成の Compose ファイルです。xpack.security.enabled=false はローカル検証用の設定で、本番では認証を必ず有効化してください(後述)。JVM ヒープは学習用に各ノード 512 MB に抑えています。
es-node1:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node1
environment:
– node.name=es-node1
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
– “9200:9200”
networks: [es-net]
es-node2:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node2
environment:
– node.name=es-node2
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
networks: [es-net]
es-node3:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node3
environment:
– node.name=es-node3
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
networks: [es-net]
networks:
es-net:
driver: bridge
cluster.initial_master_nodes は初回起動時のみ必要
cluster.initial_master_nodes はクラスターが初期化される最初の 1 回だけ必要な設定(cluster bootstrapping)です。一度クラスターが形成されたら、この設定は削除することが推奨されています(再起動時に古いクラスター情報と競合する可能性があるため)。一方 discovery.seed_hosts はノード同士がお互いを見つけるための設定なので、常に残しておきます。
手順4:クラスターを起動する
[+] Running 4/4
✔ Network es-cluster_es-net Created
✔ Container es-node1 Started
✔ Container es-node2 Started
✔ Container es-node3 Started
$ docker compose ps –format “table {{.Name}}\t{{.Status}}”
NAME STATUS
es-node1 Up About a minute
es-node2 Up About a minute
es-node3 Up About a minute
ここだけは順番を間違えると動きません。3 ノードはほぼ同時に起動することが重要です(docker compose up -d はこれを自動でやってくれます)。1 台だけ起動して放置すると master 選出のクォーラム(過半数 = 2 台)が得られず、master not discovered yet のままクラスターが形成されません。
クラスターヘルスを確認する(実測)
3 ノードを起動してから、私の環境では 約 54 秒でクラスターが形成されました。ヘルス API で状態を確認しましょう。
手順5:クラスターヘルス API を叩く

{
“cluster_name” : “linuxlab-cluster”,
“status” : “green”,
“timed_out” : false,
“number_of_nodes” : 3,
“number_of_data_nodes” : 3,
“active_primary_shards” : 0,
“active_shards” : 0,
“unassigned_shards” : 0,
“active_shards_percent_as_number” : 100.0
}
"status" : "green" かつ "number_of_nodes" : 3 が表示されれば、3 ノードがクラスターを組めています。まだインデックスを作っていないので active_shards は 0 ですが、それで正常です。ブラウザで http://localhost:9200/_cluster/health?pretty を開いても同じ JSON が確認できます。

ステータスの意味は次のとおりです。
| ステータス | 意味 | 対処 |
|---|---|---|
| green | 全シャード(プライマリ+レプリカ)が正常稼働 | 問題なし |
| yellow | プライマリは正常だがレプリカが未割り当て(シングルノードに多い) | ノードを増やすか、レプリカ数を 0 に設定 |
| red | プライマリシャードが 1 つ以上割り当て不能 | ノード障害・設定ミスを確認 |
手順6:ノード一覧を確認する
name ip cpu node.role master
es-node1 192.168.160.2 99 cdfhilmrstw *
es-node2 192.168.160.3 99 cdfhilmrstw –
es-node3 192.168.160.4 99 cdfhilmrstw –
master 列の * が付いているノードが現在のマスターノードです。今回の実測では es-node1 が選出されました。node.role の m は master 適格、d は data ノードを意味し、3 ノードとも全ロールを兼ねています。マスターは es-node1 とは限らず、起動のタイミングで変わります。CPU が 99% に張り付いているのは、検証マシンで多数のコンテナを同時に動かしていたためで、専用ホストならもっと低い値になります。
本番向けインデックス設定とシャード分散(実測)
手順7:シャード数・レプリカ数を指定してインデックスを作る
3 ノード構成では、シャード数 3・レプリカ数 1 が分かりやすい基本設定です。実際にインデックスを作成し、シャードがどう配置されたかを実測しました。

-H “Content-Type: application/json” \
-d ‘{“settings”: {“number_of_shards”: 3, “number_of_replicas”: 1}}’
{“acknowledged”:true,”shards_acknowledged”:true,”index”:”my-index”}
$ curl -s http://localhost:9200/_cluster/health | python3 -c \
“import json,sys; h=json.load(sys.stdin); print(h[‘status’], h[‘active_shards’], ‘shards’)”
green 6 shards
シャード数 3 × レプリカ 1 = アクティブシャード 6 枚(プライマリ 3 + レプリカ 3)になります。_cat/shards で配置を見ると、各プライマリのレプリカが必ず別ノードに置かれていることが分かります。
index shard prirep state node
my-index 0 p STARTED es-node1
my-index 0 r STARTED es-node2
my-index 1 p STARTED es-node2
my-index 1 r STARTED es-node3
my-index 2 p STARTED es-node3
my-index 2 r STARTED es-node1
シャード 0 のプライマリ(p)は es-node1、レプリカ(r)は es-node2 にあります。プライマリとレプリカが必ず別ノードに分かれているので、どれか 1 台が落ちても残りのノードのレプリカがプライマリに昇格し、データを失いません。これが 3 ノード構成の最大の利点です。全シャードが STARTED でステータスが green なら成功です。

Kibana で GUI から確認する
Elasticsearch の状態をブラウザの GUI で確認したい場合は Kibana を追加します。クラスターヘルスやインデックスを画面から操作でき、API も Dev Tools コンソールから実行できます。Compose に以下のサービスを足すだけです。
image: docker.elastic.co/kibana/kibana:8.19.16
container_name: kibana
environment:
– ELASTICSEARCH_HOSTS=http://es-node1:9200
ports:
– “5601:5601”
networks: [es-net]
depends_on: [es-node1]
起動後、http://localhost:5601 にアクセスすると Kibana のホーム画面(「Welcome to Elastic」)が表示されます。実際に Kibana 8.19.16 を上記の 3 ノードクラスターに接続して撮影した画面が以下です。

左メニューの「Dev Tools」を開くと、Console から ES の API を直接実行できます。GET /_cluster/health や GET /_cat/nodes?v をここから叩けば、curl を打たなくてもクラスターの状態を確認できます。

CPU・ディスク性能の実測ベンチ
ES のノードとして使う Ubuntu 24.04 ホストのベースライン性能を sysbench と dd で実測しました。本番 VPS を選ぶ際の参考にしてください。

今回の実測では sysbench CPU が平均 4,019 events/sec(3 回・最小 2,340〜最大 6,590)、dd によるディスクは書き込み 1.2 GB/s・読み込み 3.1 GB/s でした。CPU の変動幅が大きいのは、多数のコンテナを並列実行している検証環境のためです。Elasticsearch はディスク I/O が検索・インデックス性能を大きく左右しますので、本番 VPS は NVMe SSD を備えたプランを選ぶと効果的です。
VPS 3 台で本番構成を組む場合
実際の本番では Docker の同一ホストではなく、VPS 3 台それぞれに ES を配置して可用性を確保します。おすすめの VPS と最小プランを比較します(価格は各社公式の 2026 年 6 月時点の目安)。
| VPS | 推奨プラン | vCPU / RAM | 月額(1 台) | 3 台合計/月 | 東京リージョン |
|---|---|---|---|---|---|
| Vultr | Cloud Compute 4GB | 2 / 4 GB | $20 | $60 | あり(東京) |
| DigitalOcean | Droplet 4GB | 2 / 4 GB | $24 | $72 | なし(最寄:シンガポール) |
| Linode (Akamai) | Shared 4GB | 2 / 4 GB | $24 | $72 | あり(東京) |
| ConoHa VPS | 4GB プラン | 4 / 4 GB | 約 ¥3,000 | 約 ¥9,000 | あり(東京/大阪) |
東京に本番サーバーを置くなら Vultr(東京リージョン)が 3 台 $60/月で使えるのでコスパが良いです。日本語サポートや円建て決済が必要なら ConoHa VPS も選択肢になります。
VPS での elasticsearch.yml 設定例
VPS 3 台に直接インストールする場合は、各ノードの /etc/elasticsearch/elasticsearch.yml を次のように設定します。
node.name: es-node1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.seed_hosts:
– “10.0.0.1:9300” # node1 の実IPに変更
– “10.0.0.2:9300” # node2
– “10.0.0.3:9300” # node3
cluster.initial_master_nodes:
– “es-node1”
– “es-node2”
– “es-node3”
本番では xpack.security を必ず有効化する
VPS 間の通信には TLS を設定し、xpack.security.enabled: true にしてください。8.x では既定でセキュリティが有効です。セキュリティなしの ES を Internet に露出すると、データ漏洩やランサムウェア被害のリスクがあります。ノード間通信は VPS のプライベートネットワーク(東京リージョン内)に閉じ、9200/9300 ポートを外部公開しないことも重要です。
よくあるエラーと解決策
①「max virtual memory areas vm.max_map_count [65530] is too low」
起動直後にこのエラーで ES が落ちる場合は、ホストの vm.max_map_count が足りていません。
vm.max_map_count = 262144
# 永続化(再起動後も有効)
$ echo “vm.max_map_count=262144” | sudo tee /etc/sysctl.d/99-elasticsearch.conf
$ sudo sysctl –system
②「master not discovered yet」でクラスターが形成されない
3 ノードが同時に起動していないか、discovery.seed_hosts の設定が間違っているケースです。まず docker compose logs -f でログを確認し、各ノードが互いに到達できるか確認してください。cluster.name が 3 ノードで一致していないと、別クラスター扱いになって永遠に master が決まりません。
… elected-as-master ([2] nodes joined)…
… master node changed {previous [], current [{es-node1}…]}
③「yellow」のまま green にならない
シングルノードでレプリカ付きインデックスを作ったり、ノード数よりレプリカ数が多い場合に yellow になります(レプリカを置く先のノードが足りない)。3 ノードでレプリカ数 1 にしていれば green になるはずですが、念のため _cat/shards で UNASSIGNED が残っていないか確認します。
index shard prirep state node
my-index 0 p STARTED es-node1
my-index 0 r STARTED es-node2
my-index 1 r UNASSIGNED
↑ UNASSIGNED が残っていると yellow。レプリカ数を見直す
レプリカ数を一時的に 0 にして green に戻すには curl -X PUT http://localhost:9200/my-index/_settings -H "Content-Type: application/json" -d '{"index":{"number_of_replicas":0}}' を実行します。ノードを増やせるなら、レプリカ数は 1 のままノードを足すのが正攻法です。
まとめ
- Ubuntu 24.04 + Docker Compose で Elasticsearch 8.19.16 の 3 ノードクラスターを構築し、約 54 秒で status green / number_of_nodes 3 を実測できました
- cluster.initial_master_nodes と discovery.seed_hosts の設定が最重要——3 ノードを同時起動すれば自動でマスターが選出される
- クラスターヘルス API(/_cluster/health)で green を確認するまでが「構築完了」の基準
- shards 3・replicas 1 のインデックスはプライマリ 3 + レプリカ 3 の計 6 枚が別ノードへ分散配置され、1 台障害でもデータを失わない
- 本番 VPS では vm.max_map_count=262144 と xpack.security.enabled: true が必須。VPS 3 台なら Vultr 東京リージョン($60/月〜)がコスパ面でおすすめ
さらに本格的な運用を目指すなら、Logstash・Kibana を加えた ELK スタック全体の構築や、Filebeat によるログ収集にも挑戦してみてください。



コメント