Docker Compose 部署 Elasticsearch(单节点)
前言
Elasticsearch 用来做全文检索、日志检索、以及聚合分析时非常方便。
为了让本地开发、测试环境一键可复现,最省心的方式通常是用 docker-compose 管起来。
本文以单节点为目标,给出一份可直接运行的 docker-compose.yml,并补齐持久化与常见报错的处理方式。
准备
你需要先确认本机已经安装 Docker Desktop,并且 docker-compose 可用。
下面命令用于确认 Docker 与 Compose 插件可正常工作。
1 | docker version |
如果你在 Windows 上使用 Docker Desktop,推荐使用 WSL2 后端。
后面涉及的内核参数调整,在 WSL2 与 Linux 主机上写法不同,我会分别给出。
实现
创建目录
先准备一个独立目录,用于存放 docker-compose.yml 与持久化数据目录。
下面给出一个示例目录结构,你也可以按自己习惯调整。
1 | mkdir -p compose-es |
编写 Dockerfile.elasticsearch
官方 Elasticsearch 镜像不包含 IK 分词器,需要在镜像构建阶段执行 elasticsearch-plugin install。
下面 Dockerfile 基于与 STACK_VERSION 相同的官方镜像,安装 Infinilabs 发布的 analysis-ik(原 IK 分词插件),安装地址与官方说明一致。
插件版本必须与 ES 版本一致;若构建失败,可到 analysis-ik 稳定包目录 核对是否已有对应 elasticsearch-analysis-ik-{版本}.zip,必要时把 STACK_VERSION 调整为已有包的小版本号。
1 | FROM docker.elastic.co/elasticsearch/elasticsearch:8.13.4 |
编写 docker-compose.yml
下面这份 Compose 会拉起一个单节点 Elasticsearch,并把数据目录持久化到宿主机。
Elasticsearch 服务通过上一节的 Dockerfile 构建带 IK 的镜像;Kibana 仍使用官方镜像。
你只需要把 STACK_VERSION 改成你要的 ES 版本即可,建议用同一个大版本在团队内统一。
如果你希望开启安全认证,并且让 elastic 用户的默认密码来自 .env,可以使用 ELASTIC_PASSWORD。
需要注意的是,这个密码通常只在数据目录为空的首次初始化时生效。
1 | services: |
上面配置里我开启了安全认证,并关闭了 HTTPS,方便开发环境直接访问。
默认用户名是 elastic,密码就是 ELASTIC_PASSWORD 的值。
如果你要用于公网或准生产环境,建议开启 HTTPS,并配合反向代理与访问控制。
这里也补充一下端口的作用,方便你按需暴露端口与做防火墙策略。9200 是 Elasticsearch 的 HTTP 接口端口,curl 调用、Kibana 访问、以及业务服务的 REST 客户端通常都连这个端口。
9300 是 Elasticsearch 节点之间的传输端口,集群内部通信、节点加入集群等会用到它,单节点模式下通常不需要对外网暴露。
5601 是 Kibana 的 Web UI 端口,用浏览器访问 Kibana 控制台时会用到它,如果你不部署 Kibana 就不需要暴露。
如果你希望把数据目录挂载到宿主机目录(例如 ./data:/usr/share/elasticsearch/data),需要确保宿主机目录对容器内的 elasticsearch 用户可写。
在官方镜像里通常是以 uid 1000 运行,所以你可以在启动前执行下面命令修正权限。
1 | mkdir -p ./data |
Docker Compose 会为你创建一个名为 esdata 的持久化存储空间。当你执行 docker-compose down 命令时,默认行为是:
- 停止并移除容器。
- 移除为服务创建的网络。
- 保留所有由
volumes声明的命名卷。
因此,你的数据会安全地保存在 esdata 这个卷中。
当你再次执行 docker-compose up -d 时,Docker 会创建新的容器,并重新将这个包含旧数据的 esdata 卷挂载进去,你的数据自然就回来了。
如果要删除命名卷
1 | docker-compose down --volumes |
或者只删除某个命名卷
1 | docker volume rm compose-es_esdata |
注意创建的命名卷的名称不是esdata。
编写 .env(推荐)
为了避免在 compose 文件里写死版本,你可以用 .env 来管理变量。
下面给一个示例,版本号与默认密码按你项目实际需要调整。
开启安全认证后,默认用户名是 elastic,密码就是 ELASTIC_PASSWORD。
Kibana 连接 Elasticsearch 建议使用内置用户 kibana_system,并在 .env 中配置 KIBANA_PASSWORD。
1 | STACK_VERSION=8.13.4 |
如果你开启了安全认证,并且想在已初始化后修改密码,可以进入容器执行交互式重置。
默认只创建了elastic的密码,是没有设置kibana_system的密码的。
下面命令把 kibana_system 用户的密码重置为你输入的新值,然后把同样的值写到 .env 的 KIBANA_PASSWORD 中即可。
1 | docker exec -it es-server /usr/share/elasticsearch/bin/elasticsearch-reset-password -u kibana_system -i |
如果要修改elastic的密码。
1 | docker exec -it es-server /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -i |
调整内核参数 vm.max_map_count
Elasticsearch 在 Linux 内核上通常要求 vm.max_map_count 至少为 262144。
下面给出在 Linux 主机上一次性生效与持久化生效两种写法。
1 | sudo sysctl -w vm.max_map_count=262144 |
如果你在 Windows 的 WSL2 里跑 Docker 后端,可以先在 WSL 发行版里执行同样命令。
如果你发现重启后失效,可以考虑在 WSL 的启动脚本或 wsl.conf 方案里做持久化,这部分不同发行版可能略有差异。
启动
下面命令会在后台启动 Elasticsearch 与 Kibana。
首次启动会拉取镜像,速度取决于网络情况。
先构建 Elasticsearch 镜像
1 | DOCKER_BUILDKIT=0 COMPOSE_DOCKER_CLI_BUILD=0 docker-compose build elasticsearch |
再启动容器。
1 | docker-compose up -d |
验证
查看日志
1 | docker logs -f es |
你可以先用 curl 验证 ES 是否能返回基本信息。
下面命令会请求 ES 根路径与集群健康状态。
1 | curl -u elastic:${ELASTIC_PASSWORD} -s http://localhost:9200 |
下面请求使用 _analyze 接口,确认 IK 插件已加载且 ik_max_word 能正常分词。
返回里应出现若干 token 条目;若报 Unknown analyzer [ik_max_word],说明当前运行的镜像未安装插件或版本不匹配。
1 | curl -u elastic:${ELASTIC_PASSWORD} -s "http://localhost:9200/_analyze?pretty" \ |
如果你也启动了 Kibana,可以用浏览器访问 http://localhost:5601。
如果 Kibana 一直转圈或报错,优先看它自己的日志。
1 | docker logs -f kibana |
如果 Elasticsearch 开启了安全认证,而 Kibana 没有配置连接 Elasticsearch 的用户名密码,Kibana 通常无法正常启动或会持续重试。
你可以先用下面命令确认 Kibana 端口是否在监听,以及容器是否处于运行状态。
1 | docker-compose ps |
常见问题
vm.max_map_count 太小
如果日志里出现 vm.max_map_count [xxx] is too low,说明你的宿主机内核参数没调到位。
你可以按本文前面 vm.max_map_count 的步骤调整,然后重启容器。
1 | docker-compose restart elasticsearch |
文件描述符 nofile 太小
如果日志里出现 max file descriptors [xxxx] for elasticsearch process is too low,说明 nofile 不够。
本文的 compose 已经通过 ulimits.nofile 做了常见修正,但某些环境可能仍需要在宿主机层面提高限制。
你可以先确认容器内当前限制值,再决定是否需要改宿主机配置。
1 | docker exec -it es /bin/bash -lc "ulimit -n && ulimit -l" |
内存不足或启动很慢
如果你机器内存比较小,ES_JAVA_OPTS 的 -Xms/-Xmx 建议下调。
例如改成 -Xms512m -Xmx512m,更适合轻量 demo。
扩展
只启动 Elasticsearch
如果你只需要 ES,不需要 Kibana,可以把 kibana 服务从 compose 里删掉。
或者启动时只拉起指定服务。
1 | docker-compose up -d elasticsearch |
清理与重置数据
如果你需要完全重置数据,先停服务,再删除本地 data 目录。
这会导致索引与数据全部丢失,请确认是你想要的效果。
1 | docker-compose down |
总结
用 Docker Compose 部署 Elasticsearch 的最小落地流程可以概括为几步。
- 需要 IK 时准备
Dockerfile.elasticsearch,在构建阶段安装与STACK_VERSION一致的插件包。 - 写好
docker-compose.yml,Elasticsearch 用build生成带 IK 的镜像,并用volumes做持久化。 - 调整
vm.max_map_count与nofile,解决 ES 启动最常见的系统限制问题。 - 用
curl、_cluster/health与_analyze验证服务与分词,必要时查看docker logs定位问题。