用 Docker Compose 搭建 Elasticsearch 三节点集群

Elasticsearch(简称 ES)是一个分布式搜索与分析引擎。它以 JSON 文档为基本存储单位,通过倒排索引支持快速全文检索,也可以完成聚合、排序和条件过滤。

如果你准备开始使用 ES,建议先掌握这些基础操作:

  • 索引的创建、查询、更新和删除(CRUD)
  • Mapping 的设计与调整
  • JSON 文档的增删改查、排序和聚合

本文使用 Elasticsearch 7.6.2、Kibana 7.6.2 和 Docker Compose,在本机搭建一个三节点集群,并安装 IK 中文分词插件。

这是本地学习环境示例。生产环境还需要补充安全认证、TLS、资源规划、备份策略和监控配置。

一、准备镜像和目录

先确保 Docker Desktop 已启动,然后拉取官方镜像:

docker pull docker.elastic.co/elasticsearch/elasticsearch:7.6.2
docker pull docker.elastic.co/kibana/kibana:7.6.2

在项目根目录创建数据和配置目录:

mkdir -p data/kibana data/node1/data data/node2/data data/node3/data

Windows PowerShell 也可以执行:

New-Item -ItemType Directory -Force data/kibana, data/node1/data, data/node2/data, data/node3/data

将数据目录映射到宿主机,可以避免容器被删除后数据一起丢失。本文使用三个节点,是为了形成更适合选主和故障演练的本地集群;节点数量并不是 ES 的硬性最低要求,单节点也可以运行开发环境。

最终目录可以整理为:

es/
├─ data/
│  ├─ kibana/kibana.yml
│  ├─ node1/elasticsearch.yml
│  ├─ node1/Dockerfile
│  ├─ node1/ik/                 # IK 插件目录
│  ├─ node2/elasticsearch.yml
│  └─ node3/elasticsearch.yml
├─ docker-compose.yml
└─ .env

二、配置 Kibana

data/kibana/kibana.yml 中写入:

server.name: kibana
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://es01:9200", "http://es02:9200", "http://es03:9200"]
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: zh-CN

elasticsearch.hosts 使用的是 Docker Compose 网络中的服务名。Kibana 会通过这三个服务名访问集群,不需要使用宿主机的 localhost

三、配置三个 Elasticsearch 节点

1. node1:主节点

data/node1/elasticsearch.yml 中写入:

cluster.name: es-cluster
node.name: es01
node.master: true
node.data: false
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["es01", "es02", "es03"]
cluster.initial_master_nodes: ["es01", "es02", "es03"]
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type

2. node2 和 node3:数据节点

data/node2/elasticsearch.yml 的内容如下,node3 只需要把 node.name 改成 es03

cluster.name: es-cluster
node.name: es02
node.master: false
node.data: true
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["es01", "es02", "es03"]
cluster.initial_master_nodes: ["es01", "es02", "es03"]
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type

这里将 es01 配置为主节点,将 es02 和 es03 配置为数据节点。ES 7.x 支持通过 node.masternode.data 指定节点角色;在更新版本中,建议改用 node.roles 配置角色。

四、安装 IK 中文分词插件

elasticsearch-analysis-ik Releases 下载与 ES 版本匹配的 IK 插件。解压后,将插件目录命名为 ik,放到 data/node1/ik

然后在 data/node1/Dockerfile 中写入:

FROM docker.elastic.co/elasticsearch/elasticsearch:7.6.2

COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/elasticsearch.yml
COPY --chown=elasticsearch:elasticsearch ik /usr/share/elasticsearch/plugins/ik

如果需要自定义 IK 词典,再把词典文件复制到镜像内的插件配置目录。目录应与 IKAnalyzer.cfg.xml 中的配置保持一致,不要直接照抄其他机器的绝对路径。

五、编排集群容器

在根目录创建 docker-compose.yml

version: "3.8"

services:
  es01:
    image: ${image}
    container_name: es01
    environment:
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./data/node1/data:/usr/share/elasticsearch/data
      - ./data/node1/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./data/node1/ik:/usr/share/elasticsearch/plugins/ik
    ports:
      - "9200:9200"
    networks: [elastic]

  es02:
    image: ${image}
    container_name: es02
    environment:
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./data/node2/data:/usr/share/elasticsearch/data
      - ./data/node2/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - "9201:9200"
    networks: [elastic]

  es03:
    image: ${image}
    container_name: es03
    environment:
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./data/node3/data:/usr/share/elasticsearch/data
      - ./data/node3/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    ports:
      - "9202:9200"
    networks: [elastic]

  kibana:
    image: ${image_kibana}
    container_name: kibana
    depends_on: [es01]
    environment:
      ELASTICSEARCH_HOSTS: http://es01:9200
    volumes:
      - ./data/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml
    ports:
      - "5601:5601"
    networks: [elastic]

networks:
  elastic:
    driver: bridge

注意:三个容器内部都监听 9200,所以 es02 和 es03 的宿主机端口要分别映射为 9201:92009202:9200。容器之间通信仍然使用服务名和容器端口 9200

在根目录创建 .env,为 Compose 中的占位符提供值:

image=m/es:7.6.2
image_kibana=docker.elastic.co/kibana/kibana:7.6.2

六、构建并启动

进入 data/node1 构建包含 IK 插件的 ES 镜像:

docker build -t m/es:7.6.2 .

回到项目根目录启动集群:

docker compose up -d

如果需要观察启动日志,可以去掉 -d,或执行:

docker compose logs -f es01 es02 es03 kibana

首次启动可能需要一些时间。若 Linux 宿主机提示挂载目录权限不足,请先为 data/node*/data 调整目录权限;Docker Desktop 通常会自动处理 Windows 和 macOS 的文件共享权限。

七、验证集群

先检查节点接口:

curl http://localhost:9200
curl http://localhost:9201
curl http://localhost:9202

再查看集群健康状态和节点列表:

curl "http://localhost:9200/_cluster/health?pretty"
curl "http://localhost:9200/_cat/nodes?v"

返回节点信息且集群状态正常后,浏览器打开 http://localhost:5601/,进入 Kibana 的 Dev Tools,执行:

GET _cluster/health
GET _cat/nodes?v

至此,Elasticsearch 三节点集群和 Kibana 控制台就搭建完成了。

八、停止和清理

停止并删除容器,但保留宿主机数据:

docker compose down

本地实验结束后,如果确定不再需要数据,再手动删除 data/node*/data。ES 和 Kibana 都比较消耗内存,尝试在服务器上部署时,建议先使用独立机器进行验证,不要直接修改生产环境。

更多推荐