ES 是 Docker 里最容易「起来就挂」的镜像:默认堆内存 2GB 起步,小内存服务器直接被 OOM 杀掉;8.x 又默认开启安全认证,不加参数连都连不上。这篇按小服务器视角(4GB 内存机器也能跑)把流程走完。
一、先改系统参数(不做必挂)
# vm.max_map_count 至少 262144,ES 的 mmapfs 硬性要求
sudo sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-es.conf
少了这行,日志里会看到 max virtual memory areas vm.max_map_count [65530] is too low,容器启动即退。
二、启动单节点(开发/小生产)
mkdir -p /data/es/{data,plugins,config}
docker run -d \
--name es8 \
--restart unless-stopped \
-p 9200:9200 \
-m 1g \
-v /data/es/data:/usr/share/elasticsearch/data \
-v /data/es/plugins:/usr/share/elasticsearch/plugins \
-e discovery.type=single-node \
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
-e xpack.security.enabled=true \
-e xpack.security.http.ssl.enabled=false \
-e ELASTIC_PASSWORD='你的强密码' \
-e TZ=Asia/Shanghai \
docker.elastic.co/elasticsearch/elasticsearch:8.15.0
关键参数逐个说:
ES_JAVA_OPTS:堆内存给容器限额的一半以内。-m 1g限容器 1GB,堆 512MB。ES 堆外还要内存(Lucene 的 mmap),堆设成容器上限一样大就会 OOM。discovery.type=single-node:单节点免选主流程,多节点集群不要这么写。xpack.security.http.ssl.enabled=false:8.x 默认 HTTPS + 自签证书,开发环境先关掉 HTTP 层 TLS 省事;对外的生产集群建议保留并配正规证书。ELASTIC_PASSWORD:elastic 用户的密码,8.x 没有它没法连。
验证:
curl -u elastic:'你的强密码' http://localhost:9200
# 看到 "tagline" : "You Know, for Search" 即成功
三、装 IK 中文分词
默认分词器把中文切成单字,搜「冰箱」连「冰柜」都搜不出来。IK 装法:
# 版本号必须和 ES 完全一致
docker exec -it es8 elasticsearch-plugin install \
https://get.infini.cloud/elasticsearch/analysis-ik/8.15.0
docker restart es8
验证:
curl -u elastic:'你的强密码' -X POST 'http://localhost:9200/_analyze' \
-H 'Content-Type: application/json' \
-d '{"analyzer":"ik_max_word","text":"车辆租赁管理系统"}'
返回的 tokens 里有「车辆」「租赁」「管理系统」等分词即成功。
四、Kibana 联动(可选)
docker run -d --name kibana --restart unless-stopped \
-p 5601:5601 \
-e ELASTICSEARCH_HOSTS='["http://es8:9200"]' \
-e ELASTICSEARCH_USERNAME=elastic \
-e ELASTICSEARCH_PASSWORD='你的强密码' \
-e I18N_LOCALE=zh-CN \
--link es8 \
docker.elastic.co/kibana/kibana:8.15.0
Kibana 自己也要 1GB 内存,4GB 小机器想跑全套(ES + Kibana + MySQL)就都压到 512MB 堆。
五、常见问题
| 现象 | 原因 | 解法 |
|---|---|---|
启动几秒就退出,日志 max_map_count too low |
系统参数没改 | 第一节 |
| 容器被杀(exit 137) | 堆内存 ≥ 容器限额 | 堆设为 -m 的一半左右 |
curl 返回 401 |
8.x 默认认证 | 带上 -u elastic:密码 |
| data 目录权限报错 | 宿主机目录属主不对 | chown -R 1000:1000 /data/es/data |
| 插件装完起不来 | 插件版本和 ES 不一致 | docker logs es8 看版本冲突,删掉重装对应版本 |
| 磁盘水位告警,索引变只读 | 磁盘用量超 95% | 清磁盘后 PUT _all/_settings 解除 read_only_allow_delete |
六、内存预算参考(估算)
| 服务器内存 | ES 容器 -m |
堆 ES_JAVA_OPTS |
适合 |
|---|---|---|---|
| 2GB | 1g | 512m | 单服务轻量检索 |
| 4GB | 1.5g | 768m | ES + 小型应用 |
| 8GB | 4g | 2g | ES + Kibana + 业务 |
以上为经验估算,实际以监控为准;堆永远不要超过 31GB(指针压缩失效)。
相关工具:Docker 命令速查 · JSON 格式化 · Linux 命令速查