文章目录
- 容器化应用实战:ElasticSearch + Kibana
-
- 一、ElasticSearch 部署
-
- 1. 下载 ES 镜像
- 2. 准备目录与配置文件
- 3. 启动容器
- 二、Kibana 部署
-
- 1. 下载 Kibana 镜像
- 2. 启动容器,指向 ES 位置
- 三、自定义网络方案(推荐)
-
- 1. 创建自定义网络
- 2. 启动 ElasticSearch,加入自定义网络 es-net
- 3. 启动 Kibana,同样加入 es-net 网络
- 4. 两种方案对比
- 5. 调试小技巧
- 四、报错复盘:单文件挂载坑
-
- 1. 现象
- 2. 故障根因
- 3. 本次排障里的错误操作
- 4. 完整正确处理流程
- 5. 经验教训
- 6. 可选规避方案
容器化应用实战:ElasticSearch + Kibana
[!note] 核心摘要
- ES 单节点:必须加 discovery.type=single-node,低配机器用 ES_JAVA_OPTS 限制 JVM 堆内存
- 版本一致:ES 与 Kibana 版本必须完全一致(本例均为 7.17.0)
- 容器互联:ES 与 Kibana 加入同一自定义网络,ELASTICSEARCH_HOSTS 直接写容器名,不依赖宿主机 IP
- 高频坑:bind-mount 挂载单个文件前必须提前手动创建文件,否则 docker 会生成同名目录导致启动失败
一、ElasticSearch 部署
1. 下载 ES 镜像
[root@localhost ~]# docker pull elasticsearch:7.17.0
7.17.0: Pulling from library/elasticsearch
ea362f368469: Pull complete
49618e7bd315: Pull complete
ef2c6f195245: Pull complete
c32ac7edc3c3: Pull complete
85e392fc2cc0: Pull complete
4aff618a9264: Pull complete
795bd33f4eb3: Pull complete
ab1c10cef766: Pull complete
1cf47933dd34: Pull complete
Digest: sha256:332c6d416808f6e9a2cbcbe0170d9a9bb14bfe772180d37de5084c223dd8948b
Status: Downloaded newer image for elasticsearch:7.17.0
docker.io/library/elasticsearch:7.17.0
2. 准备目录与配置文件
创建配置文件目录、数据文件目录:
[root@localhost ~]# mkdir -p /opt/es/config
[root@localhost ~]# mkdir -p /opt/es/data
创建监听端口资源(写入 ES 配置文件):
[root@localhost ~]# echo "http.host: 0.0.0.0" >> /opt/es/config/elasticsearch.yml
开启权限(ES 容器内用户 uid=1000,防止权限拒绝):
[root@localhost ~]# chmod -R 777 /opt/es/
3. 启动容器
[root@localhost ~]# docker run –name elasticsearch -p 9200:9200 -p 9300:9300 \\
> -e "discovery.type=single-node" \\
> -e ES_JAVA_OPTS="-Xms512m -Xmx512m" \\
> -v /opt/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \\
> -v /opt/es/data:/usr/share/elasticsearch/data \\
> -v /opt/es/plugins:/usr/share/elasticsearch/plugins \\
> -d elasticsearch:7.17.0
e6d5b38f691861cc39c7ec944e29c01ff758aeb8e423e7a4936a2419f4ebb58a
查看容器:
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e6d5b38f6918 elasticsearch:7.17.0 "/bin/tini — /usr/l…" 4 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 0.0.0.0:9300->9300/tcp, :::9300->9300/tcp elasticsearch
参数简单说明
验证访问:curl http://127.0.0.1:9200,返回 json 代表启动成功。
二、Kibana 部署
1. 下载 Kibana 镜像
[root@localhost ~]# docker pull kibana:7.17.0
7.17.0: Pulling from library/kibana
ea362f368469: Already exists
94aca20bb05b: Pull complete
65ae9e597e86: Pull complete
d29743d928b1: Pull complete
23891b890413: Pull complete
8bf7af96af27: Pull complete
014dfb291cad: Pull complete
8bf3742fc390: Pull complete
7b0e9c8dbcb7: Pull complete
4dab17aa5385: Pull complete
807090e8d21f: Pull complete
87d0ac3cb26e: Pull complete
ed92e0cf24d4: Pull complete
Digest: sha256:a98b0797fd5357ba8a64c32df0e2e24dc7ad2df3320891b090a1f713124f1c95
Status: Downloaded newer image for kibana:7.17.0
docker.io/library/kibana:7.17.0
2. 启动容器,指向 ES 位置
[root@localhost ~]# docker run –name kibana -e ELASTICSEARCH_HOSTS=http://192.168.100.152:9200 -p 5601:5601 -d kibana:7.17.0
8cd2108ffe49cd6dd7eac21b93b4204beb1ca0ab6b45a2bedd1a7d980e7ea4b1
参数说明:
- ELASTICSEARCH_HOSTS:指定 Kibana 连接 ES 的地址,这里要填宿主机真实 IP,不要写 127.0.0.1(容器内部 127.0.0.1 代表容器自己)
- 5601:Kibana 网页访问端口,浏览器访问 http://宿主机IP:5601
[!warning] 版本一致性 ES 和 Kibana 版本必须完全一致,这里都是 7.17.0。
三、自定义网络方案(推荐)
上面脚本里的方式 ELASTICSEARCH_HOSTS=http://192.168.100.152:9200,是 Kibana 容器走宿主机物理 IP 访问 ES。
缺点:要写死宿主机 IP,换机器、IP 一变就要改启动命令;还要防火墙放行 9200 端口。
[!note] 更推荐的方案 自定义 docker 网络:两个容器接入同一个自定义网络,直接用容器名字当域名互相访问,不用写宿主机 IP。
1. 创建自定义网络
# 创建 es-net 网络
docker network create es-net
2. 启动 ElasticSearch,加入自定义网络 es-net
把原来的 run 命令加上 –network es-net:
docker run –name elasticsearch \\
–network es-net \\
-p 9200:9200 -p 9300:9300 \\
-e "discovery.type=single-node" \\
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \\
-v /opt/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \\
-v /opt/es/data:/usr/share/elasticsearch/data \\
-v /opt/es/plugins:/usr/share/elasticsearch/plugins \\
-d elasticsearch:7.17.0
3. 启动 Kibana,同样加入 es-net 网络
ELASTICSEARCH_HOSTS 直接写容器名 elasticsearch 作为域名,docker 内部 DNS 自动解析,不用写宿主机 IP:
docker run –name kibana \\
–network es-net \\
-e ELASTICSEARCH_HOSTS=http://elasticsearch:9200 \\
-p 5601:5601 \\
-d kibana:7.17.0
关键点:
- 同一个自定义网络内,容器名就是主机名,kibana 内部访问 http://elasticsearch:9200 就能连通 ES
- 不再依赖宿主机局域网 IP,宿主机 IP 怎么变,容器之间通信不受影响
- 不需要宿主机防火墙开放 9200 端口给外部,9200 只需要宿主机本地访问调试用,kibana 走 docker 内部网络
4. 两种方案对比
| 宿主机 IP 访问 | http://192.168.100.152:9200 | 简单,不用新建网络 | IP 写死,IP 变更要改配置,需要防火墙放行 9200 |
| 自定义 docker 网络 | http://elasticsearch:9200 | 容器名做域名,不依赖宿主机 IP,网络隔离,生产推荐 | 需要提前创建网络 |
5. 调试小技巧
进入 kibana 容器内部测试连通性:
docker exec -it kibana curl http://elasticsearch:9200
能返回 ES 的 json 信息,代表网络通信正常。
[!warning] 容易踩坑 bridge 默认网络不支持容器名 DNS 解析,必须自己 create 的自定义网络才支持容器名域名解析,这点很容易踩坑。
四、报错复盘:单文件挂载坑
1. 现象
执行 docker run 启动 elasticsearch,命令返回一串 OCI runtime 报错,容器创建出来但启动失败,docker ps -a 看到状态为 Created,无法 up 运行。
报错核心提示:
Are you trying to mount a directory onto a file (or vice-versa)?
not a directory
2. 故障根因
使用 bind-mount 挂载单个文件:
-v /opt/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
宿主机上 /opt/es/config/elasticsearch.yml 文件没有提前手动创建。
Docker bind-mount 底层限制:mount –bind 只能绑定已经存在的对象,不能凭空生成文件。 👉 宿主机该路径不存在时,Docker 会自动 mkdir,生成一个名字叫 elasticsearch.yml 的文件夹,并不是 yml 配置文件。
于是冲突出现:
- 宿主机:elasticsearch.yml → 文件夹(docker 自动创建)
- 容器内部目标:elasticsearch.yml → 普通配置文件
试图把宿主机目录挂载覆盖容器内文件,直接抛出挂载异常。
[!warning] 迷惑点 ls /opt/es/config/ 能看到这个名字,肉眼分不清是文件还是文件夹,必须 ls -l 看第一位,d 代表目录,- 代表普通文件。
3. 本次排障里的错误操作
看到挂载报错后,去删除 /opt/es/data/nodes/ 数据目录。
- 这个报错发生在容器初始化挂载阶段,ES 程序还没有启动,根本还没访问 data 数据目录
- 删除 nodes 属于无效操作,解决不了本次挂载问题
- 同时残留了状态为 Created 的失败容器,如果不删除,下次 run 会报容器名称已存在
4. 完整正确处理流程
ls -l /opt/es/config/elasticsearch.yml
rm -rf /opt/es/config/elasticsearch.yml
echo "http.host: 0.0.0.0" > /opt/es/config/elasticsearch.yml
chmod -R 777 /opt/es
docker rm -f elasticsearch
5. 经验教训
6. 可选规避方案
学习环境,不挂载单个 yml,改为挂载整个 config 目录,规避该坑:
-v /opt/es/config:/usr/share/elasticsearch/config
[!warning] 注意 该方式要求宿主机 config 目录内要有 ES 完整配置文件,不能只放一个 yml。



