如何 Docker 安装 Elasticsearch ?

Viewed 25
  1. 使用 Docker 安装 Elasticsearch(右键打开原文链接)
    • 启动单节点集群
    • 运行 Kibana
  2. 使用 Docker Compose 启动多节点集群
  3. 在生产环境中使用 Docker 镜像 Elasticsearch
  4. 使用 Docker 配置 Elasticsearch
  5. 使用自定义 Docker 镜像
  6. 排查 Elasticsearch 的 Docker 错误
1 Answers

使用 Docker 安装 Elasticsearch

Elasticsearch 的 Docker 镜像

Elasticsearch 的 Docker 镜像可从 Elastic Docker 注册表获取。所有已发布 Docker 镜像和标签的列表可在 www.docker.elastic.co 获取。源代码位于 GitHub。

此软件包包含免费和订阅功能。开始 30 天试用以试用所有功能。

如果您只想在本地开发中测试 Elasticsearch,请参阅[本地运行 Elasticsearch](Run Elasticsearch locally)。请注意,此设置不适用于生产环境。

在 Docker 中运行 Elasticsearch

使用 Docker 命令启动单节点 Elasticsearch 集群以进行开发或测试。然后,您可以运行其他 Docker 命令将节点添加到测试集群或运行 Kibana。

默认情况下,此设置不会运行多个 Elasticsearch 节点或 Kibana。要使用 Kibana 创建多节点集群,请改用 Docker Compose。请参阅[使用 Docker Compose 启动多节点集群](Start a multi-node cluster with Docker Compose)。

强化 Docker 镜像

您还可以使用强化 Wolfi 镜像来提高安全性。使用 Wolfi 镜像需要 Docker 20.10.10 或更高版本。

要使用 Wolfi 镜像,请在 Docker 命令的镜像标签中附加 -wolfi。

例如:

docker pull docker.elastic.co/elasticsearch/elasticsearch-wolfi:8.17.0

启动单节点集群

  1. 安装 Docker。访问 [Get Docker](Get Docker) 为您的环境安装 Docker。

  2. 如果使用 Docker Desktop,请确保至少分配 4GB 内存。您可以通过转到设置 > 资源来调整 Docker Desktop 中的内存使用情况。

  3. 创建一个新的 docker 网络。

    docker network create elastic
    
  4. 拉取 Elasticsearch Docker 镜像。

    docker pull docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    
  5. (可选)为您的环境安装 Cosign。然后使用 Cosign 验证 Elasticsearch 镜像的签名。

    wget https://artifacts.elastic.co/cosign.pub
    cosign verify --key cosign.pub docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    

    cosign 命令以 JSON 格式打印检查结果和签名有效负载:

    Verification for docker.elastic.co/elasticsearch/elasticsearch:8.17.0 --
    The following checks were performed on each of these signatures:
      - The cosign claims were validated
      - Existence of the claims in the transparency log was verified offline
      - The signatures were verified against the specified public key
    
  6. 启动 Elasticsearch 容器。

    docker run --name es01 --net elastic -p 9200:9200 -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    

    使用 -m 标志设置容器的内存限制。这消除了手动设置 JVM 大小的需要。

    机器学习功能(例如使用 ELSER 的语义搜索)需要更大的容器,内存大于 1GB。如果您打算使用机器学习功能,请使用以下命令启动容器:

    docker run --name es01 --net elastic -p 9200:9200 -it -m 6GB -e "xpack.ml.use_auto_machine_memory_percent=true" docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    

    该命令打印 elastic 用户密码和 Kibana 的注册令牌。

  7. 复制生成的 elastic 密码和注册令牌。这些凭据仅在您首次启动 Elasticsearch 时显示。您可以使用以下命令重新生成凭据。

    docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
    docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana
    

    我们建议将 elastic 密码存储为 shell 中的环境变量。例如:

    export ELASTIC_PASSWORD="your_password"
    
  8. 将 http_ca.crt SSL 证书从容器复制到您的本地机器。

    docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
    
  9. 向 Elasticsearch 发出 REST API 调用以确保 Elasticsearch 容器正在运行。

    curl --cacert http_ca.crt -u elastic:$ELASTIC_PASSWORD https://localhost:9200
    

添加更多节点

  1. 使用现有节点为新节点生成注册令牌。

    docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
    

    注册令牌有效期为 30 分钟。

  2. 启动一个新的 Elasticsearch 容器。将注册令牌作为环境变量包含在内。

    docker run -e ENROLLMENT_TOKEN="<token>" --name es02 --net elastic -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.17.0
    
  3. 调用 cat nodes API 以验证节点是否已添加到集群中。

    curl --cacert http_ca.crt -u elastic:$ELASTIC_PASSWORD https://localhost:9200/_cat/nodes
    

运行 Kibana

  1. 拉取 Kibana Docker 镜像。

    docker pull docker.elastic.co/kibana/kibana:8.17.0
    
  2. (可选)验证 Kibana 镜像的签名。

    wget https://artifacts.elastic.co/cosign.pub
    cosign verify --key cosign.pub docker.elastic.co/kibana/kibana:8.17.0
    
  3. 启动 Kibana 容器。

    docker run --name kib01 --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.17.0
    

    Kibana 启动时,它会向终端输出一个唯一的生成链接。要访问 Kibana,请在 Web 浏览器中打开此链接。

  4. 在浏览器中,输入启动 Elasticsearch 时生成的注册令牌。

    要重新生成令牌,请运行:

    docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana
    
  5. 使用启动 Elasticsearch 时生成的密码以 elastic 用户身份登录 Kibana。

    要重新生成密码,请运行:

    docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
    

删除容器

要删除容器及其网络,请运行:

# 删除 Elastic 网络
docker network rm elastic

# 删除 Elasticsearch 容器
docker rm es01
docker rm es02

# 删除 Kibana 容器
docker rm kib01

后续步骤

您现在已经设置了 Elasticsearch 测试环境。在开始正式开发或将 Elasticsearch 用于生产环境之前,请查看在生产环境中使用 Docker 运行 Elasticsearch 时要应用的要求和建议。

使用 Docker Compose 启动多节点集群

使用 Docker Compose 启动一个包含 Kibana 的三节点 Elasticsearch 集群。Docker Compose 允许您使用单个命令启动多个容器。

配置和启动集群

  1. 安装 Docker Compose。访问 Docker Compose 文档为您的环境安装 Docker Compose。

    如果您使用的是 Docker Desktop,则会自动安装 Docker Compose。确保至少为 Docker Desktop 分配 4GB 内存。您可以通过转到设置 > 资源来调整 Docker Desktop 中的内存使用情况。

  2. 为项目创建或导航到一个空目录。

  3. 在项目目录中下载并保存以下文件:

    • .env
    • docker-compose.yml
  4. .env 文件中,为 ELASTIC_PASSWORDKIBANA_PASSWORD 变量指定密码。

    密码必须是字母数字,并且不能包含特殊字符,例如 ! 或 @。docker-compose.yml 文件中包含的 bash 脚本仅适用于字母数字字符。例如:

    # 'elastic' 用户的密码(至少 6 个字符)
    ELASTIC_PASSWORD=changeme
    
    # 'kibana_system' 用户的密码(至少 6 个字符)
    KIBANA_PASSWORD=changeme
    ...
    
  5. .env 文件中,将 STACK_VERSION 设置为当前 Elastic Stack 版本。

    ...
    # Elastic 产品的版本
    STACK_VERSION=8.17.0
    ...
    
  6. 默认情况下,Docker Compose 配置会公开所有网络接口上的端口 9200。

    为了避免将端口 9200 暴露给外部主机,请在 .env 文件中将 ES_PORT 设置为 127.0.0.1:9200。这可确保 Elasticsearch 只能从主机访问。

    ...
    # 将 Elasticsearch HTTP API 暴露给主机的端口
    #ES_PORT=9200
    ES_PORT=127.0.0.1:9200
    ...
    
  7. 要启动集群,请从项目目录运行以下命令。

    docker-compose up -d
    
  8. 集群启动后,在 Web 浏览器中打开 http://localhost:5601 以访问 Kibana。

  9. 使用您之前设置的 ELASTIC_PASSWORD 以 elastic 用户身份登录 Kibana。

停止和移除集群

要停止集群,请运行 docker-compose down。Docker 卷中的数据将被保留,并在您使用 docker-compose up 重新启动集群时加载。

docker-compose down

要在停止集群时删除网络、容器和卷,请指定 -v 选项:

docker-compose down -v

后续步骤

您现在已经设置了 Elasticsearch 测试环境。在开始正式开发或将 Elasticsearch 用于生产环境之前,请查看在生产环境中使用 Docker 运行 Elasticsearch 时要应用的要求和建议。

在生产环境中使用 Docker 镜像

以下要求和建议适用于在生产环境中使用 Docker 运行 Elasticsearch。

将 vm.max_map_count 设置为至少 262144

vm.max_map_count 内核设置必须设置为至少 262144 才能用于生产环境。

如何设置 vm.max_map_count 取决于您的平台。

Linux

要查看 vm.max_map_count 设置的当前值,请运行:

grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144

要在实时系统上应用该设置,请运行:

sysctl -w vm.max_map_count=262144

要永久更改 vm.max_map_count 设置的值,请更新 /etc/sysctl.conf 中的值。

使用 Docker for Mac 的 macOS

必须在 xhyve 虚拟机中设置 vm.max_map_count 设置:

  1. 从命令行运行:

    screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
    
  2. 按 Enter 键并使用 sysctl 配置 vm.max_map_count

    sysctl -w vm.max_map_count=262144
    
  3. 要退出 screen 会话,请键入 Ctrl a d。

使用 Docker Desktop 的 Windows 和 macOS

必须通过 docker-machine 设置 vm.max_map_count 设置:

docker-machine ssh
sudo sysctl -w vm.max_map_count=262144

使用 Docker Desktop WSL 2 后端的 Windows

必须在 Elasticsearch 容器正常启动之前在“docker-desktop”WSL 实例中设置 vm.max_map_count 设置。有多种方法可以做到这一点,具体取决于您的 Windows 版本和 WSL 版本。

如果您使用的是 22H2 之前的 Windows 10 版本,或者如果您在使用内置版本 WSL 的 Windows 10 版本 22H2 上,则必须在每次重新启动 Docker 后手动设置它,然后再启动 Elasticsearch 容器,或者(如果您不希望在每次重新启动时都这样做)您必须全局设置每个 WSL2 实例以更改 vm.max_map_count。这是因为这些版本的 WSL 不能正确处理 /etc/sysctl.conf 文件。

要在每次重新启动时手动设置它,您必须在每次重新启动 Docker 时在命令提示符或 PowerShell 窗口中运行以下命令:

wsl -d docker-desktop -u root
sysctl -w vm.max_map_count=262144

如果您使用的是这些版本的 WSL,并且您不想每次重新启动 Docker 时都必须运行这些命令,您可以通过如下修改 %USERPROFILE%\.wslconfig 来全局更改每个 WSL 发行版以及此设置:

[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"

这将导致所有 WSL2 VM 在启动时都分配该设置。

如果您使用的是 Windows 11 或 Windows 10 版本 22H2 并且安装了 Microsoft Store 版本的 WSL,您可以修改“docker-desktop”WSL 发行版中的 /etc/sysctl.conf,例如使用以下命令:

wsl -d docker-desktop -u root
vi /etc/sysctl.conf

并附加一行内容如下:

vm.max_map_count = 262144

配置文件必须可由 elasticsearch 用户读取

默认情况下,Elasticsearch 在容器内以用户 elasticsearch 的身份运行,使用 uid:gid 1000:0。

一个例外是 Openshift,它使用任意分配的用户 ID 运行容器。Openshift 提供的持久卷的 gid 设置为 0,无需任何调整即可工作。

如果您正在绑定挂载本地目录或文件,则 elasticsearch 用户必须能够读取它。此外,此用户必须对 config、data 和 log 目录具有写入权限(Elasticsearch 需要对 config 目录具有写入权限才能生成密钥库)。一个好的策略是授予对本地目录的 gid 0 的组访问权限。

例如,要准备一个本地目录以通过绑定挂载存储数据:

mkdir esdatadir
chmod g+rwx esdatadir
chgrp 0 esdatadir

您还可以使用自定义 UID 和 GID 运行 Elasticsearch 容器。您必须确保文件权限不会阻止 Elasticsearch 执行。您可以使用以下两个选项之一:

  • 绑定挂载 config、data 和 logs 目录。如果您打算安装插件并且不想创建自定义 Docker 镜像,则还必须绑定挂载 plugins 目录。
  • --group-add 0 命令行选项传递给 docker run。这可确保 Elasticsearch 运行所使用的用户也是容器内 root (GID 0) 组的成员。

增加 nofile 和 nproc 的 ulimits

必须为 Elasticsearch 容器提供增加的 nofile 和 nproc 的 ulimits。验证 Docker 守护程序的 init 系统是否将它们设置为可接受的值。

要检查 Docker 守护程序的 ulimits 默认值,请运行:

docker run --rm docker.elastic.co/elasticsearch/elasticsearch:8.17.0 /bin/bash -c 'ulimit -Hn && ulimit -Sn && ulimit -Hu && ulimit -Su'

如果需要,请在守护程序中调整它们或为每个容器覆盖它们。例如,使用 docker run 时,设置:

--ulimit nofile=65535:65535

禁用交换

为了性能和节点稳定性,需要禁用交换。有关执行此操作的方法的信息,请参阅[禁用交换](Disable swapping)。

如果您选择 bootstrap.memory_lock: true 方法,您还需要在 Docker 守护程序中定义 memlock: true ulimit,或者如示例 compose 文件所示为容器显式设置。使用 docker run 时,您可以指定:

-e "bootstrap.memory_lock=true" --ulimit memlock=-1:-1

随机化已发布的端口

该镜像公开 TCP 端口 9200 和 9300。对于生产集群,建议使用 --publish-all 随机化已发布的端口,除非您将每个容器固定到一个主机。

手动设置堆大小

默认情况下,Elasticsearch 会根据节点的角色和节点容器可用的总内存自动调整 JVM 堆大小。对于大多数生产环境,我们建议使用此默认大小调整。如果需要,您可以通过手动设置 JVM 堆大小来覆盖默认大小调整。

要在生产环境中手动设置堆大小,请在 /usr/share/elasticsearch/config/jvm.options.d 下绑定挂载一个 JVM 选项文件,其中包含您所需的堆大小设置。

为了进行测试,您还可以使用 ES_JAVA_OPTS 环境变量手动设置堆大小。例如,要使用 1GB,请使用以下命令。

docker run -e ES_JAVA_OPTS="-Xms1g -Xmx1g" -e ENROLLMENT_TOKEN="<token>" --name es01 -p 9200:9200 --net elastic -it docker.elastic.co/elasticsearch/elasticsearch:8.17.0

ES_JAVA_OPTS 变量会覆盖所有其他 JVM 选项。我们不建议在生产环境中使用 ES_JAVA_OPTS

将部署固定到特定镜像版本

将您的部署固定到特定版本的 Elasticsearch Docker 镜像。例如 docker.elastic.co/elasticsearch/elasticsearch:8.17.0

始终绑定数据卷

您应该在 /usr/share/elasticsearch/data 上使用绑定卷,原因如下:

  • 如果容器被终止,您的 Elasticsearch 节点的数据不会丢失
  • Elasticsearch 对 I/O 敏感,而 Docker 存储驱动程序并不理想,无法实现快速 I/O
  • 它允许使用高级 Docker 卷插件

避免使用 loop-lvm 模式

如果您使用的是 devicemapper 存储驱动程序,请不要使用默认的 loop-lvm 模式。将 docker-engine 配置为使用 direct-lvm。

集中您的日志

考虑使用不同的日志驱动程序来集中您的日志。另请注意,默认的 json-file 日志驱动程序并不适合生产使用。

使用 Docker 配置 Elasticsearch

在 Docker 中运行时,Elasticsearch 配置文件从 /usr/share/elasticsearch/config/ 加载。

要使用自定义配置文件,您可以将文件绑定挂载到镜像中的配置文件上。

您可以使用 Docker 环境变量设置单个 Elasticsearch 配置参数。示例 compose 文件和单节点示例使用此方法。您可以直接使用设置名称作为环境变量名称。如果您不能这样做,例如因为您的编排平台禁止在环境变量名称中使用句点,那么您可以通过如下转换设置名称来使用替代样式。

  1. 将设置名称更改为大写
  2. 为其添加前缀 ES_SETTING_
  3. 通过复制来转义任何下划线 (_)
  4. 将所有句点 (.) 转换为下划线 (_)

例如,-e bootstrap.memory_lock=true 变为 -e ES_SETTING_BOOTSTRAP_MEMORY__LOCK=true

您可以使用文件的内容来设置 ELASTIC_PASSWORDKEYSTORE_PASSWORD 环境变量的值,方法是在环境变量名称后缀 _FILE。这对于将密码等机密信息传递给 Elasticsearch 而不直接指定它们非常有用。

例如,要从文件中设置 Elasticsearch 引导密码,您可以绑定挂载该文件并将 ELASTIC_PASSWORD_FILE 环境变量设置为挂载位置。如果您将密码文件挂载到 /run/secrets/bootstrapPassword.txt,请指定:

-e ELASTIC_PASSWORD_FILE=/run/secrets/bootstrapPassword.txt

您可以覆盖镜像的默认命令,以将 Elasticsearch 配置参数作为命令行选项传递。例如:

docker run <各种参数> bin/elasticsearch -Ecluster.name=mynewclustername

虽然绑定挂载配置文件通常是生产环境中的首选方法,但您也可以创建一个包含配置的自定义 Docker 镜像。

挂载 Elasticsearch 配置文件

创建自定义配置文件并将它们绑定挂载到 Docker 镜像中的相应文件上。例如,要使用 docker run 绑定挂载 custom_elasticsearch.yml,请指定:

-v full_path_to/custom_elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml

如果您绑定挂载自定义 elasticsearch.yml 文件,请确保它包含 network.host: 0.0.0.0 设置。此设置可确保节点可用于 HTTP 和传输流量,前提是其端口已公开。Docker 镜像的内置 elasticsearch.yml 文件默认包含此设置。

该容器以用户 elasticsearch 的身份运行 Elasticsearch,使用 uid:gid 1000:0。绑定挂载的主机目录和文件必须可由该用户访问,并且数据和日志目录必须可由该用户写入。

创建加密的 Elasticsearch 密钥库

默认情况下,Elasticsearch 将自动生成一个密钥库文件以用于安全设置。此文件已混淆但未加密。

要使用密码加密您的安全设置并将其持久化到容器之外,请使用 docker run 命令手动创建密钥库。该命令必须:

  • 绑定挂载 config 目录。该命令将在该目录中创建一个 elasticsearch.keystore 文件。为避免错误,请勿直接绑定挂载 elasticsearch.keystore 文件。
  • 使用带有 create -p 选项的 elasticsearch-keystore 工具。系统将提示您输入密钥库的密码。

例如:

docker run -it --rm \
-v full_path_to/config:/usr/share/elasticsearch/config \
docker.elastic.co/elasticsearch/elasticsearch:8.17.0 \
bin/elasticsearch-keystore create -p

您还可以使用 docker run 命令在密钥库中添加或更新安全设置。系统将提示您输入设置值。如果密钥库已加密,系统还会提示您输入密钥库密码。

docker run -it --rm \
-v full_path_to/config:/usr/share/elasticsearch/config \
docker.elastic.co/elasticsearch/elasticsearch:8.17.0 \
bin/elasticsearch-keystore \
add my.secure.setting \
my.other.secure.setting

如果您已经创建了密钥库并且不需要更新它,您可以直接绑定挂载 elasticsearch.keystore 文件。您可以使用 KEYSTORE_PASSWORD 环境变量在启动时向容器提供密钥库密码。例如,docker run 命令可能具有以下选项:

-v full_path_to/config/elasticsearch.keystore:/usr/share/elasticsearch/config/elasticsearch.keystore
-e KEYSTORE_PASSWORD=mypassword

使用自定义 Docker 镜像

在某些环境中,准备一个包含您的配置的自定义镜像可能更有意义。实现此目的的 Dockerfile 可能很简单,如下所示:

FROM docker.elastic.co/elasticsearch/elasticsearch:8.17.0
COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/

然后,您可以使用以下命令构建和运行镜像:

docker build --tag=elasticsearch-custom .
docker run -ti -v /usr/share/elasticsearch/data elasticsearch-custom

某些插件需要额外的安全权限。您必须通过以下任一方式显式接受它们:

  • 运行 Docker 镜像时附加 tty 并在出现提示时允许权限。
  • 检查安全权限并通过将 --batch 标志添加到插件安装命令来接受它们(如果适用)。

有关更多信息,请参阅[插件管理](Plugin management)。

排查 Elasticsearch 的 Docker 错误

以下是解决使用 Docker 运行 Elasticsearch 时出现的常见错误的方法。

elasticsearch.keystore 是一个目录

Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.io.IOException: Is a directory: SimpleFSIndexInput(path="/usr/share/elasticsearch/config/elasticsearch.keystore") Likely root cause: java.io.IOException: Is a directory

与密钥库相关的 docker run 命令尝试直接绑定挂载一个不存在的 elasticsearch.keystore 文件。如果您使用 -v--volume 标志挂载一个不存在的文件,Docker 将创建一个同名目录。

要解决此错误:

  1. 删除 config 目录中的 elasticsearch.keystore 目录。
  2. -v--volume 标志更新为指向 config 目录路径而不是密钥库文件的路径。有关示例,请参阅[创建加密的 Elasticsearch 密钥库](Create an encrypted Elasticsearch keystore)。
  3. 重试该命令。

elasticsearch.keystore:设备或资源繁忙

Exception in thread "main" java.nio.file.FileSystemException: /usr/share/elasticsearch/config/elasticsearch.keystore.tmp -> /usr/share/elasticsearch/config/elasticsearch.keystore: Device or resource busy

docker run 命令尝试在直接绑定挂载 elasticsearch.keystore 文件时更新密钥库。要更新密钥库,容器需要访问 config 目录中的其他文件,例如 keystore.tmp

要解决此错误:

  1. -v--volume 标志更新为指向 config 目录路径而不是密钥库文件的路径。有关示例,请参阅[创建加密的 Elasticsearch 密钥库](Create an encrypted Elasticsearch keystore)。
  2. 重试该命令。