【DOCKER容器实战】-3 ElasticSearch + Kibana

文章目录

  • [容器化应用实战:ElasticSearch + Kibana](#容器化应用实战:ElasticSearch + Kibana)
    • [一、ElasticSearch 部署](#一、ElasticSearch 部署)
      • [1. 下载 ES 镜像](#1. 下载 ES 镜像)
      • [2. 准备目录与配置文件](#2. 准备目录与配置文件)
      • [3. 启动容器](#3. 启动容器)
    • [二、Kibana 部署](#二、Kibana 部署)
      • [1. 下载 Kibana 镜像](#1. 下载 Kibana 镜像)
      • [2. 启动容器,指向 ES 位置](#2. 启动容器,指向 ES 位置)
    • 三、自定义网络方案(推荐)
      • [1. 创建自定义网络](#1. 创建自定义网络)
      • [2. 启动 ElasticSearch,加入自定义网络 es-net](#2. 启动 ElasticSearch,加入自定义网络 es-net)
      • [3. 启动 Kibana,同样加入 es-net 网络](#3. 启动 Kibana,同样加入 es-net 网络)
      • [4. 两种方案对比](#4. 两种方案对比)
      • [5. 调试小技巧](#5. 调试小技巧)
    • 四、报错复盘:单文件挂载坑
      • [1. 现象](#1. 现象)
      • [2. 故障根因](#2. 故障根因)
      • [3. 本次排障里的错误操作](#3. 本次排障里的错误操作)
      • [4. 完整正确处理流程](#4. 完整正确处理流程)
      • [5. 经验教训](#5. 经验教训)
      • [6. 可选规避方案](#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 镜像

bash 复制代码
[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. 准备目录与配置文件

创建配置文件目录、数据文件目录:

bash 复制代码
[root@localhost ~]# mkdir -p /opt/es/config
[root@localhost ~]# mkdir -p /opt/es/data

创建监听端口资源(写入 ES 配置文件):

bash 复制代码
[root@localhost ~]# echo "http.host: 0.0.0.0" >> /opt/es/config/elasticsearch.yml

开启权限(ES 容器内用户 uid=1000,防止权限拒绝):

bash 复制代码
[root@localhost ~]# chmod -R 777 /opt/es/

3. 启动容器

bash 复制代码
[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

查看容器:

bash 复制代码
[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

参数简单说明

  1. discovery.type=single-node单节点模式,不需要集群,本地测试必加
  2. ES_JAVA_OPTS="-Xms512m -Xmx512m":JVM 堆内存,最小最大都设 512M,低配机器防止占满内存
  3. -v:挂载配置、数据、插件目录到宿主机
  4. 9200:ES HTTP 访问端口;9300:ES 集群内部通信端口

验证访问:curl http://127.0.0.1:9200,返回 json 代表启动成功。

二、Kibana 部署

1. 下载 Kibana 镜像

bash 复制代码
[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 位置

bash 复制代码
[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. 创建自定义网络

bash 复制代码
# 创建 es-net 网络
docker network create es-net

2. 启动 ElasticSearch,加入自定义网络 es-net

把原来的 run 命令加上 --network es-net

bash 复制代码
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:

bash 复制代码
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 容器内部测试连通性:

bash 复制代码
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 运行。

报错核心提示:

text 复制代码
Are you trying to mount a directory onto a file (or vice-versa)?
not a directory

2. 故障根因

使用 bind-mount 挂载单个文件

bash 复制代码
-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. 完整正确处理流程

  1. 校验对象真实类型:
bash 复制代码
ls -l /opt/es/config/elasticsearch.yml
  1. 如果它是目录(d 开头),删除这个错误目录:
bash 复制代码
rm -rf /opt/es/config/elasticsearch.yml
  1. 手动真正生成 yml 配置文件:
bash 复制代码
echo "http.host: 0.0.0.0" > /opt/es/config/elasticsearch.yml
  1. 给目录权限(ES 内部用户 uid=1000,防止后续权限拒绝):
bash 复制代码
chmod -R 777 /opt/es
  1. 清理残留的 Created 状态旧容器:
bash 复制代码
docker rm -f elasticsearch
  1. 重新执行 docker run 启动容器。

5. 经验教训

  1. -v 绑定宿主机单个文件 时,文件必须提前手动创建;宿主机不存在,docker 会错误生成目录,这是高频坑。
  2. -v 绑定目录时,宿主机不存在,docker 自动创建目录,行为正常。
  3. Created 容器状态:代表容器对象创建成功,但启动失败,不会自动删除,需要手动 rm 清理。
  4. 看类型不要只看文件名,用 ls -l 分辨是文件还是文件夹。
  5. 报错要看准报错栈:报错信息写哪个路径,问题就出在哪个路径,不要去操作无关目录。

6. 可选规避方案

学习环境,不挂载单个 yml,改为挂载整个 config 目录,规避该坑:

bash 复制代码
-v /opt/es/config:/usr/share/elasticsearch/config

!warning 注意

该方式要求宿主机 config 目录内要有 ES 完整配置文件,不能只放一个 yml。

相关推荐
海兰1 小时前
【 Kafka进阶5】使用 Docker 部署 Apache Kafka 集群完全指南
docker·kafka·apache
sel_92 小时前
【Docker】Docker 安装与使用详解:从零搭建到日常实战
人工智能·深度学习·算法·docker
卷无止境12 小时前
Windows 上丝滑开发 Python,并稳定构建 Docker 镜像
后端·python·docker
吕海洋17 小时前
目前可用的docker源2026.08
运维·docker·容器
gsls20080819 小时前
Penpot Docker 部署与 MCP 服务配置文档
运维·docker·容器·原型·penpot
xrlfreedom20 小时前
大厂 MCP 面试实录:本地 Server 远程化改造中的技术选型与落地实践
docker·json schema·mcp
艾伦_耶格宇1 天前
【DOCKER容器实战】-2MySQL
运维·docker·容器
Sayai1 天前
Elasticsearch 日志索引设计:按小时切分 + 小时内 Rollover 兜底(ILM 实战,附完整脚本)
大数据·elasticsearch·搜索引擎
Elasticsearch1 天前
生产环境向量搜索的一个设置:vectordb_document 模式如何自动调优 Elasticsearch
elasticsearch