ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker搭建Elasticsearch与IK分词器:从零到Kibana可视化

Docker搭建Elasticsearch与IK分词器:从零到Kibana可视化 第一次在Windows上接触Elasticsearch我直接奔着压缩包去了。结果那一晚上全耗在环境上JDK版本不对、启动闪退、ik分词器插件装不上。后来把所有相关内容换成Docker之后从ES、ik分词器到Kibana可视化面板二十分钟内全部跑通想重置环境就删容器干净利落。这篇就把这套流程最完整地走一遍Docker如何准备、ES容器怎么启动、ik分词器怎么装才能不随容器丢失、Kibana怎么连上ES每一步的命令和预期输出我都会写清楚。不管你是刚入门的ES新手还是想快速搭一套本地开发环境的同学都可以直接照抄。1. 为什么我坚持用Docker装 Elasticsearch 而不是直接下载压缩包1.1 本地环境一人一坑Docker把环境差异全隔离直接安装ES的流程看着不复杂官网下载压缩包、解压、双击启动脚本但实际踩坑时你会发现每个人都陷在不同的泥潭里。旧教程会叫你先装JDK可ES从7.x开始就已经内置了OpenJDK多装一个反而版本冲突Windows解压版、macOS brew版、Linux deb/rpm版的配置文件和目录结构各有差异网上一个命令抄过来经常因为平台不同直接报错。Docker方案的好处在于官方镜像已经把运行时、配置文件、依赖环境全部固化在一个容器里宿主机不需要装任何Java环境也不会在系统里留下卸载不干净的残留。容器删了镜像还在镜像删了重新拉一遍就行。对做技术学习、本地开发、甚至快速验证生产配置的人来说这种“毁掉重建”的成本几乎为零我认为这才是Docker在Elasticsearch场景里最大的价值。1.2 版本选型7.17 是教学与实践的最佳平衡点Elasticsearch目前主要有7.x和8.x两大系列。8.x默认开启安全认证首次启动会生成一堆证书和密码Kibana连接时还要处理账号、加密密钥这对只想要一个本地搜索环境的新手来说多了一层不必要的负担。7.17是7.x系列的最后一个大版本不仅稳定而且大量教程、博客、ik分词器资料都围绕7.x展开遇到问题一搜基本都有答案。本文统一使用7.17.18作为示例版本。这个版本号你最好原样保留不要用latest否则ik分词器的版本很容易对不上ES启动时会直接报插件不兼容。提示整个流程里凡是出现 7.17.18 的地方意味着必须保证 ES、ik 分词器、Kibana 三个组件的版本完全一致。1.3 这套方案最终长什么样整条链路涉及三个部分其中ik分词器不是独立容器而是跑在ES进程里的一个插件Elasticsearch容器负责数据存储和检索HTTP端口9200节点间通信端口9300。ik分词器ES的插件解决中文分词问题没有它ES对中文基本只能按单字切。Kibana容器可视化面板端口5601通过容器的服务名es去访问ES而不是localhost。可以这样理解ES是搜索引擎的引擎本体ik分词器是中文词典Kibana是仪表盘和管理台。三者用同一个Docker网络串联起来容器之间通过名字互相访问这是这套架构最核心的运行逻辑。2. 开始前的环境准备Docker Desktop 和那些绕不开的启动问题2.1 装 Docker Desktop后端选WSL2Windows用户第一步是安装 Docker Desktop。安装包在官网直接下载安装过程中有一个关键选项会让你选择使用WSL 2还是Hyper-V后端。我建议勾选WSL 2它比Hyper-V更轻量启动速度更快而且和Windows Terminal、VS Code的集成体验更好。装完后用管理员身份打开PowerShell执行一次wsl --install这个命令会把WSL2内核和默认发行版装好然后重启电脑。重启后打开 Docker Desktop看到右下角托盘的鲸鱼图标变正常状态说明Docker已经跑起来了。如果这一步就卡住了看下一节。2.2 最常见的启动失败virtualisation support wasnt detected很多人在这一步会卡住双击Docker Desktop后弹窗报错Docker Desktop failed to start because virtualisation support wasnt detected这个错误的核心原因是Windows的虚拟化能力没开全。按下面顺序排查命中率很高打开控制面板 - 程序 - 启用或关闭Windows功能确认“适用于Linux的Windows子系统”和“虚拟机平台”这两项都勾选了。重启电脑进BIOS确认虚拟化开关已开启。Intel CPU找Intel Virtualization Technology (VT-x)AMD CPU找SVM Mode不同主板位置不一样但关键词都是Virtualization。在PowerShell里执行systeminfo看最后面的虚拟化相关行。如果显示“已在固件中启用虚拟化”说明BIOS没问题。执行wsl --update更新WSL2内核然后重新启动Docker Desktop。我遇到过的情况是BIOS里虚拟化被关了开了之后重启就好了。还有一次是Windows功能里的“虚拟机平台”没勾选Docker Desktop一直起不来勾完重启后一切正常。这个步骤不用着急Docker能正常启动后面所有容器的操作才能继续。2.3 配置镜像加速拉镜像别再干等Docker启动后先做一步优化镜像拉取速度的操作。打开 Docker Desktop - Settings - Docker Engine你会看到一段JSON格式的引擎配置默认只有一行。把它改成这样{ registry-mirrors: [ https://docker.m.daocloud.io, https://docker.1ms.run ] }改完点击 Apply RestartDocker会用新的镜像加速配置重启。这里的镜像加速主要对Docker Hub上的镜像生效后面拉ES官方镜像时如果还是慢就耐心等一会儿或者换个时间再试。千万别因为拉镜像慢就随意下载来路不明的所谓“精简镜像”安全和稳定比省几分钟更重要。2.4 验证环境跑一个 hello-world 确认 Docker 正常在命令行里执行docker run hello-world首次运行会先拉取镜像然后输出一段 “Hello from Docker!” 的欢迎信息说明客户端、服务端、镜像拉取链路全部正常。接着再看一眼版本信息执行docker versionOutput里Server部分显示版本号而不是报错就说明Docker服务真正可用了。到这一步环境准备才算彻底结束下面开始进入ES的正式安装。3. 启动Elasticsearch容器一条命令逐段拆给你看3.1 拉取镜像tag一定要锁定不要用 latest先执行docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.18为什么不用docker pull elasticsearch:latest因为latest会随时间漂移你今天拉的和下个月拉的可能不是同一个版本后面安装ik分词器时根本没法保证版本匹配。ES启动时如果发现ik插件版本不匹配会直接拒绝启动日志里报插件兼容性错误排查起来相当麻烦。所以所有组件都用固定版本号这是省事的前提。如果你所在网络拉官方源比较慢可以在确认镜像加速配置没问题后多等一会儿ES镜像的体积比较大一次拉取传输几百MB是正常的。3.2 单节点命令每个参数都在干什么镜像拉下来之后用下面这条命令启动ES容器docker run -d \ --name es \ -p 9200:9200 \ -p 9300:9300 \ -e discovery.typesingle-node \ -e ES_JAVA_OPTS-Xms512m -Xmx512m \ -e TZAsia/Shanghai \ -v es-data:/usr/share/elasticsearch/data \ docker.elastic.co/elasticsearch/elasticsearch:7.17.18逐个参数说-d后台运行不加的话日志会一直刷屏终端一关容器就停了。--name es给容器起名叫es后面Kibana连接、命令行操作都靠这个名字。-p 9200:9200把容器的9200端口映射到宿主机浏览器访问localhost:9200就能打到ES。-p 9300:9300ES节点间通信端口单机学习时其实用不上但一起映射出来最省心。-e discovery.typesingle-node单节点模式。不加这个ES会认为自己在集群环境里做节点发现启动后一直报找不到其他节点状态会变成红色。-e ES_JAVA_OPTS-Xms512m -Xmx512mJVM堆内存限制。ES默认给1GB在Docker Desktop默认2GB内存的机器上很容易导致容器OOM调到512MB对本地学习完全够用。-e TZAsia/Shanghai时区避免日志时间差8小时。-v es-data:/usr/share/elasticsearch/data使用一个名为es-data的具名卷做数据持久化。容器删掉重建后数据都还在。3.3 数据卷与权限ES容器里那个uid 1000的坑很多教程会教你把数据目录挂载到宿主机比如-v /data/es:/usr/share/elasticsearch/data。这本身没问题但如果你直接挂一个新建的宿主机目录大概率会启动失败日志里出现java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data原因在于ES官方镜像内部使用一个uid为1000的普通用户运行而宿主机新建的/data/es目录默认属于rootES没有权限读写。解决办法是给目录授权mkdir -p /data/es chown -R 1000:1000 /data/esWindows用户用bind mount还会遇到更多权限取舍问题所以我建议新手直接用具名卷也就是-v es-data:/usr/share/elasticsearch/data这种写法。具名卷由Docker管理权限在创建时就处理好了省掉一个最大的坑。3.4 验证启动curl一下就知道有没起来容器启动后等十几秒然后在浏览器访问http://localhost:9200或者命令行执行curl http://localhost:9200正常情况下会返回一段JSON{ name : xxx, cluster_name : docker-cluster, cluster_uuid : xxx, version : { number : 7.17.18, build_flavor : default, ... }, tagline : You Know, for Search }看到tagline那行说明ES已经健康启动。如果访问不了优先执行docker logs es看日志。最常见的情况是容器启动后一直重启日志里出现内存相关错误那就回到Docker Desktop的Settings里把内存调到4GB以上或者把ES_JAVA_OPTS里的512MB再调小一点。4. 给ES装上ik分词器版本、路径和三种安装方式4.1 为什么推荐自定义镜像而不是直接装进容器ik分词器安装其实不复杂但很多人栽在版本匹配和容器重建的问题上。ES启动后直接执行插件安装命令也可以但插件装在一个可写容器层里一旦你把容器删了重建插件就没了一切重新来过。我推荐的方案是构建一个带ik插件的自定义镜像这样镜像本身自带分词器以后无论怎么删除、重建容器插件都还在。三种方式各有适用场景先用表格对比一下方式操作位置容器删掉后插件是否保留适用场景容器内在线安装运行的容器否临时测试快速验证Dockerfile构建镜像宿主机构建是长期使用推荐离线包 docker cp运行的容器否内网环境无法访问外网4.2 方式一容器内在线安装适合临时测试如果只是临时装一下进容器执行docker exec -it es bin/elasticsearch-plugin install --batch \ https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.18/elasticsearch-analysis-ik-7.17.18.zip这里有两个细节。一个是URL里的版本号必须和ES完全一致ES是7.17.18ik也必须是v7.17.18。另一个是--batch参数容器内没有交互式确认环境不加的话命令会卡在确认提示上。看到Installed analysis-ik就说明装好了然后重启ES让插件生效docker restart es这种方式的优点是快缺点是容器重建即失效。适合你刚启动一个ES、想快速试验一下中文分词效果的场景。4.3 方式二Dockerfile 构建自定义镜像推荐长期使用我平时用得最多的是构建自定义镜像。步骤如下先在宿主机建一个目录比如es-docker把对应版本的ik压缩包下载到这个目录文件名改成elasticsearch-analysis-ik-7.17.18.zip。然后在同一目录创建DockerfileFROM docker.elastic.co/elasticsearch/elasticsearch:7.17.18 ADD elasticsearch-analysis-ik-7.17.18.zip /tmp/ik.zip RUN bin/elasticsearch-plugin install --batch file:///tmp/ik.zip rm /tmp/ik.zip构建docker build -t es-ik:7.17.18 .然后用新镜像启动容器docker run -d \ --name es \ -p 9200:9200 \ -p 9300:9300 \ -e discovery.typesingle-node \ -e ES_JAVA_OPTS-Xms512m -Xmx512m \ -e TZAsia/Shanghai \ -v es-data:/usr/share/elasticsearch/data \ es-ik:7.17.18和刚才唯一的不同是镜像名从官方镜像变成了es-ik:7.17.18。以后你删掉这个容器再重新跑这条命令ik分词器都在不需要重新安装。4.4 方式三离线安装包 docker cp适合内网服务器在内网、无法访问GitHub时可以在能联网的机器上下载好ik压缩包上传到服务器然后用docker cp复制进容器docker cp elasticsearch-analysis-ik-7.17.18.zip es:/tmp/ docker exec -it es bin/elasticsearch-plugin install --batch file:///tmp/elasticsearch-analysis-ik-7.17.18.zip docker restart es注意file:///tmp/elasticsearch-analysis-ik-7.17.18.zip是容器内路径不是宿主机路径千万别写错。这种方式在功能上类似于方式一容器删除后插件同样会丢失但适合没法直接访问外网的环境。4.5 验证ik分词器_analyze接口的预期返回安装完成后验证一下分词效果。在命令行或者Git Bash里执行curl -X POST http://localhost:9200/_analyze?pretty -H Content-Type: application/json -d {analyzer:ik_max_word,text:中华人民共和国国歌}预期返回的分词结果大概是{ tokens : [ {token : 中华人民共和国, ...}, {token : 中华人民, ...}, {token : 中华, ...}, {token : 华人, ...}, {token : 人民共和国, ...}, {token : 人民, ...}, {token : 共和国, ...}, {token : 共和, ...}, {token : 国, ...}, {token : 国歌, ...} ] }能看到这些中文词组而不是单字就说明ik分词器生效了。注意Windows的PowerShell里自带一个curl别名直接执行会走Invoke-WebRequestJSON里的引号经常被吃掉。建议用Git Bash、WSL或者强制写curl.exe。当然如果不想折腾命令行等Kibana配好后直接用Dev Tools发请求验证更方便。4.6 ik_smart 和 ik_max_word 选哪个以及自定义词典ik分词器提供两种analyzer很多新手第一次接触会很困惑Analyzer分词粒度典型结果适合场景ik_max_word最细切分穷尽所有可能词组中华人民共和国、中华人民、中华、华人、人民共和国索引阶段宁可多切召回率优先ik_smart粗粒度切分按最合理方式切中华人民共和国、国歌搜索阶段精确匹配优先实际使用中我习惯在建立索引时用ik_max_word搜索时用ik_smart这样既保证召回又减少不相关的结果。另外ik还支持自定义词典。比如人名、品牌名不在默认词典里可以通过修改插件配置文件加入。插件安装后的配置目录在/usr/share/elasticsearch/plugins/analysis-ik/config/打开IKAnalyzer.cfg.xml把这一行取消注释并指向自定义词典?xml version1.0 encodingUTF-8? !DOCTYPE properties SYSTEM http://java.sun.com/dtd/properties.dtd properties commentIK Analyzer 扩展配置/comment entry keyext_dictcustom/mydict.dic/entry /properties然后在同级目录建custom/mydict.dic每行写一个词UTF-8编码保存后重启ES即可生效。我在实际项目中遇到过很多生僻人名靠这套自定义词典几乎都能解决。5. 接上Kibana可视化面板的配置与验证5.1 一个Kibana解决什么问题Kibana在这套环境里的价值主要体现在三块一是可视化查看ES中的索引和数据二是Dev Tools控制台可以直接写DSL语句去查询三是能看到集群的健康状态。其中Dev Tools是最常用的比在命令行一个个敲curl方便得多写查询语句时还有自动补全提示对学习者来说非常友好。5.2 让ES和Kibana住在同一个Docker网络里很多人启动Kibana后配置ELASTICSEARCH_HOSTShttp://localhost:9200结果Kibana一直报连不上ES。原因很简单在Kibana容器里localhost指是Kibana自己并不是宿主机更不是ES容器。解决办法是让两个容器处于同一个Docker自定义网络里。先创建一个网络docker network create es-net如果ES容器已经启动了把它接入这个网络docker network connect es-net es如果你还没启动ES那更好启动时直接加上--network es-net。后面Kibana也加入这个网络两个容器就能通过服务名互相访问了。5.3 启动Kibana容器关键环境变量Kibana启动命令如下docker run -d \ --name kibana \ --network es-net \ -p 5601:5601 \ -e ELASTICSEARCH_HOSTShttp://es:9200 \ -e I18N_LOCALEzh-CN \ docker.elastic.co/kibana/kibana:7.17.18看到ELASTICSEARCH_HOSTShttp://es:9200重点就是es这个主机名。在同一个Docker网络里Docker自带的DNS解析会把es解析到ES容器的IP所以这里千万不要写localhost或127.0.0.1。I18N_LOCALEzh-CN表示把Kibana界面切换成中文7.17以上的版本都支持。5.4 启动慢是常态Kibana server is not ready yet 怎么排查启动Kibana后浏览器访问http://localhost:5601可能看到Kibana server is not ready yet这个提示新手很容易慌实际上大概率是Kibana还没等到ES就绪。Kibana启动时会去连ES如果ES没完全就绪它会在一定时间内自动重试。所以先等一分钟左右再刷新。如果等了很久还不行按这个顺序排查执行docker ps -a看es和kibana两个容器的状态ES有没有反复重启。执行docker logs kibana看有没有Unable to connect to Elasticsearch之类的错误。有就说明ELASTICSEARCH_HOSTS写错了或者网络不对。从宿主机执行curl http://localhost:5601/api/status如果返回的JSON中status.overall.state是green或yellow说明Kibana已经正常。如果页面还是没变化在Dev Tools还没出现之前直接看Kibana日志里有没有Kibana is now available这句话有就说明服务已经就绪清下浏览器缓存再刷新。大部分情况下Kibana不是装坏了而是启动没等够时间。5.5 轻量替代方案不用Kibana也能看数据虽然Kibana功能最全但它比较重。如果你只是临时看几个索引的数据或者想快速检查ES连接是否正常可以试试elasticvue这个浏览器插件安装后在扩展里填http://localhost:9200就能直接浏览索引、文档、映射信息。它比Kibana轻太多了适合日常快速调试。另一个工具是Cerebro主要是ES集群管理能看分片分布、节点状态。我用它的场景是定位分片分配不均衡的问题。表格对比一下工具主要功能安装方式轻量程度Kibana数据可视化、Dev Tools、索引管理Docker容器较重elasticvue快速浏览索引和文档浏览器插件很轻Cerebro集群监控与管理独立进程或Docker中等学习阶段我还是建议装Kibana因为Dev Tools的执行DSL体验是其他工具替代不了的。6. 收尾与排错Compose编排、自启动和一些重要的坑6.1 用 docker-compose.yml 一劳永逸手动敲了两三次docker run之后我强烈建议把你的整套环境写成一个docker-compose.yml。这样整个环境可以一键启动、一键停止配置还能提交到Git仓库里换机器也方便。假设你已经按4.3构建了es-ik:7.17.18镜像在项目目录下新建docker-compose.ymlservices: es: image: es-ik:7.17.18 container_name: es environment: - discovery.typesingle-node - ES_JAVA_OPTS-Xms512m -Xmx512m - TZAsia/Shanghai ports: - 9200:9200 - 9300:9300 volumes: - es-data:/usr/share/elasticsearch/data - ./ik/IKAnalyzer.cfg.xml:/usr/share/elasticsearch/plugins/analysis-ik/config/IKAnalyzer.cfg.xml - ./ik/custom:/usr/share/elasticsearch/plugins/analysis-ik/config/custom restart: always kibana: image: docker.elastic.co/kibana/kibana:7.17.18 container_name: kibana environment: - ELASTICSEARCH_HOSTShttp://es:9200 - I18N_LOCALEzh-CN ports: - 5601:5601 depends_on: - es restart: always volumes: es-data:注意我把IK的自定义配置也挂载出来了分别是./ik/IKAnalyzer.cfg.xml和./ik/custom目录。这样以后改自定义词典不用进容器直接在宿主机改文件然后重启ES即可。启动命令就两条docker compose up -d这个文件运行的前提是你已经构建了es-ik:7.17.18镜像如果还没构建先跑一遍4.3的步骤。6.2 开启自启动restart策略上面的Compose文件中两个服务都写了restart: always意思是Docker服务启动后容器会自动跟着启动。单条命令启动时也可以在docker run后面加--restart always。需要留意的是restart: always只能在Docker守护进程运行后生效。也就是说如果你电脑开机后Docker Desktop没启动容器一样不会跑。在Windows上记得在Docker Desktop的Settings里打开 “Start Docker Desktop when you sign in” 之类的选项。6.3 一套自用的排查命令清单我把自己平时排查这套环境常用的命令整理一下遇到问题按顺序敲就行docker ps -a # 看所有容器状态确认是否在重启 docker logs es -f # 看ES日志启动失败原因都在这里 docker logs kibana -f # 看Kibana日志 docker exec -it es bash # 进入ES容器内部排查 curl http://localhost:9200 # 宿主机直接访问ES curl http://localhost:5601/api/status # 看Kibana状态常见的症状和原因整理成表格症状可能原因处理方式ES容器反复重启内存不足、JVM堆过大调大Docker内存或调小ES_JAVA_OPTS9200端口返回连接拒绝ES未启动或启动失败docker logs es 看具体报错挂载目录启动报AccessDenied目录权限不是uid1000chown -R 1000:1000 数据目录Kibana一直not readyELASTICSEARCH_HOSTS写错确保写 http://es:9200端口9200/5601被占用本机其他程序占用换端口或关掉占用程序6.4 ES 8.x 用户怎么办如果你下载的是8.x版本的镜像跟本文流程最大的差异就是安全认证。ES 8.x默认xpack.security.enabledtrue启动后会在日志里打印elastic用户的初始密码Kibana连接时也需要一套账号密码。如果你只是想本地学习不涉及生产需求最简单的办法是启动ES时加上环境变量-e xpack.security.enabledfalseKibana就不需要账号密码回到和7.x一样的体验。生产环境千万不能这么干安全认证必须开着。ik分词器在8.x里同样有对应版本去GitHub Releases页面找和你的ES版本号一致的zip就行。6.5 最后说点实在的内存、生产环境与数据备份学习环境里ES_JAVA_OPTS设512MB完全够了但要是你拿这套配置直接上生产大概率会出问题。生产环境我建议单个节点至少给4GB堆内存同时要考虑集群模式下节点发现、分片副本、数据冷热分层这些复杂问题。具名卷虽然方便但别忘了备份。一条简单的tar命令就能把es-data卷打包到当前目录docker run --rm -v es-data:/data -v $(pwd):/backup alpine \ tar czf /backup/es-backup.tar.gz -C /data .我个人的习惯是学习阶段一定用Docker磁盘空间不够就清理旧镜像重来等到要上生产的时候再结合团队现有的运维体系决定容器编排方式。这套ES、ik分词器、Kibana的Docker组合拳最大的意义是让你把精力花在搜索和分词本身而不是浪费在一遍遍解压安装包、配置JDK、修启动报错上。照着上面的步骤走一遍把这套环境跑起来后面学习ES的索引、查询、聚合都会顺手很多。
返回列表