在之前的文章 “如何在Linux,Mac OS及 Windows 上进行安装 Elasticsearch”,我介绍了如何通过安装包或者下载的压缩文件来进行安装 Elasticsearch。在今天的文章里,我们来详细介绍如何使用 docker 来进行安装 Elastic 栈。
安装
因为我们需要使用 docker 来进行安装,我们必须安装:
- docker:根据不同的操作系统,请按照要求安装docker。可以到网站 Docker Documentation | Docker Documentation 去安装
- docker-compose。这个可以到网站 Install Docker Compose | Docker Documentation 去安装
用 docker 来安装 Elasticsearch
有关所有已发布的 Docker 镜像和标记的列表,请访问 www.docker.elastic.co。 源文件在 Github 中。
下载 docker image
获取 Docker 的 Elasticsearch 就像对 Elastic Docker 注册表发出 docker pull 命令一样简单。
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.3.2
$ docker pull docker.elastic.co/elasticsearch/elasticsearch:7.3.2
7.3.2: Pulling from elasticsearch/elasticsearch
b38629870fdb: Pull complete
fef623057bdf: Pull complete
9da6442ac1cb: Pull complete
7454a4abbddf: Pull complete
90891ccd8757: Pull complete
bc977ac5791a: Pull complete
b83a21daf050: Pull complete
Digest: sha256:9dd701842833e902c0ba2b5682e0b7b3cd32f08e94a637d87ebdcb730e0a101a
Status: Downloaded newer image for docker.elastic.co/elasticsearch/elasticsearch:7.3.2
docker.elastic.co/elasticsearch/elasticsearch:7.3.2
上面是以 Elasticsearch 7.3.2 为例来示范的。在实际的使用中,可以替换它用自己喜欢的版本。最新的版本信息可以在地址 Download Elastic Products | Elastic 找到。 关于已经发布的 Elasticsearch 版本信息可以在地址 Past Releases of Elastic Stack Software | Elastic 找到
开发或测试环境
从命令行运行 Elasticsearch。使用以下命令可以快速启动 Elasticsearch 以进行开发或测试:
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.3.2
请注意 single-node discovery,该发现允许绕过单节点开发集群中的 bootstrap checks 检查。
我们也可以对这个 container 取去一个名字,并运行于 detatch 模式:
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.3.2
如果我们想让其它的 Elastic Stack 组件访问 Elasticsearch,我们通常可以添加 network:
docker network create elastic
我们可以使用如下的命令来检查已经被创建的 network:
docker network ls
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
15f3324c856b elastic bridge local
如果我们想删除一个 network,我们可以使用如下的命令:
docker network rm elastic
在上面,我们删除已经被创建的 elastic network,尽管在我们的练习中并不需要这么做。
bridge netword 是 Docker 中的默认网络。我们可以使用以下命令检查默认 brodge network 的详细信息:
docker network inspect bridge
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f32a54d98ee6f32833a044085f86381972ecf44af55e9eb6a7fb65a6b450c0cd",
"Created": "2022-07-28T00:52:32.980968251Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
这里的 bridge 名称是 docker0。 当你添加一个容器时,它们每个都有自己的虚拟以太网接口连接到 docker bridge docker0,并且它会有一个分配给虚拟接口的 IP 地址。
该 bridge network 将自动在连接到它的任何其他网络接口之间转发数据包,并允许容器与主机以及同一主机上的容器进行通信。默认情况下,Docker 容器可以与外界建立连接,它们通过 docker0 接口连接,但外界无法连接到容器。外部连接由 IP 转发和 iptables 规则提供。 你可以使用端口映射来实现这一点。
运行 Elasticsearch 时,你需要确保它发布到可从容器外部访问的 IP 地址; 这可以通过设置 network.publish_host 进行配置。比如针对 Elastic Stack 8.3.2 的发布,我们可以使用如下的方法来定义它的 network.publish_host:
docker run -it --name es-node01 \
--net elastic -p 9200:9200 -p 9300:9300 \
--env network.publish_host=192.168.0.3 \
--env discovery.type=single-node \
--env xpack.security.authc.api_key.enabled=true \
docker.elastic.co/elasticsearch/elasticsearch:7.3.2
这里的 IP 地址 192.168.0.3 是 HOST 机器的私有地址。
docker run -d --name elasticsearch --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.3.2
在上面,我们定义了 network 为 elastic,当然我们也可以取其它的名字。
一旦 docker 启动后,我可以使用如下的命令来进行检查:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f242a796d69e docker.elastic.co/elasticsearch/elasticsearch:7.3.2 "/usr/local/bin/dock…" 6 seconds ago Up 5 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch
我们可以通过如下的命令来查看当前电脑 host 的 IP 地址:
$ ifconfig | grep 192
inet 192.168.0.11 netmask 0xffffff00 broadcast 192.168.0.255
我们尝试以如下的方式来访问 Elasticsearch:
也就是说我们不能以当前 host 电脑的私有地址来访问 Elasticsearch。
生产环境
m.max_map_count 内核设置需要设置为至少 262144 才能用于生产环境。 根据你的平台:
- Linux
vm.max_map_count设置应该在 /etc/sysctl.conf 中永久设置:
$ grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144
要在实时系统上应用该设置,请执行以下操作:
sysctl -w vm.max_map_count = 262144
- macOS (Docker for Mac)
必须在xhyve虚拟机中设置vm.max_map_count设置:
$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
只需按 Enter 键并配置 sysctl 设置,就像对待 Linux 一样:
sysctl -w vm.max_map_count=262144
- Windows and macOS (Docker Toolbox)
必须通过 docker-machine 设置 vm.max_map_count 设置:
docker-machine ssh
sudo sysctl -w vm.max_map_count=262144
在某些节点中可能无法直接访问外网进行docker 镜像的下载。修复方式:
- 开启外网访问
- (或者)在其他能够访问外网的节点中下载对应镜像 docker pull elasticsearch:7.3.2
- 把镜像导出为文件 docker save -o elasticsearch-7.3.2-image.tar docker.io/elasticsearch:7.3.2
- 把导出的文件拷贝到目标机器 scp elasticsearch-7.3.2-image.tar root@192.168.10.221:/tmp
- 登陆目标机器 ssh root@192.168.10.221
- 导入目标镜像 docker load < elasticsearch-7.3.2-image.tar
用 docker 来安装 Kibana
有关所有已发布的 Docker 镜像和标记的列表,请访问 www.docker.elastic.co。 源代码在 GitHub 中。
下载 docker image
docker pull docker.elastic.co/kibana/kibana:7.3.2
开发或测试环境
可以使用以下命令快速启动 Kibana 并将其连接到本地 Elasticsearch 容器以进行开发或测试:
docker run --link YOUR_ELASTICSEARCH_CONTAINER_NAME_OR_ID:elasticsearch -p 5601:5601 {docker-repo}:{version}
针对我们的情况,我们首先按照上面的步骤把 Elasticsearch 的 docker 运行起来,然后执行如下的命令:
docker ps
显示的结果如下:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3839f34c1d2d docker.elastic.co/elasticsearch/elasticsearch:7.3.2 "/usr/local/bin/dock…" 7 minutes ago Up 7 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp admiring_matsumoto
如果你想得到 container 的名称,我们也可以使用如下的命令:
docker ps -s
一旦得到 container 的名称,我们可以使用如下的命令来查看 docker 里的 container 的运行日志信息:
docker logs -f <container name>
上面的 docker 信息是已经安装好的的 Elasticsearch 的 docker 信息。我们然后执行如下的命令:
docker run --link 3839f34c1d2d:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana:7.3.2
这样我们的 Kibana docker 就跑起来了。
如果我们在 Elasticsearch 的 container 已经定义了 network,我们也可以使用如下的命令来启动:
docker run -d --name kibana --net elastic -p 5601:5601 -e "ELASTICSEARCH_HOSTS=http://elasticsearch:9200" docker.elastic.co/kibana/kibana:7.3.2
在上面的命令中 --net 里定义的 elastic 必须和 Elasticsearch 里的一致。另外 elasticsearch 也是在 Elasticsearch 容器里的名称。
使用 docker-compose 来启动 Elasticsearch 和 Kibana
在这一步,我们假定我们已经下载好 Elasticsearch 和 Kibana 的 docker image。如果你还没有这么做,可以执行如下的命令下载:
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.3.2
docker pull docker.elastic.co/kibana/kibana:7.3.2
紧接着下来,我们来创建一个叫做 docker 的目录,并在这个目录里创建一个叫做 docker-compose.yml 的文件。它的内容如下:
$ pwd
/Users/liuxg/elastic/docker
localhost:docker liuxg$ ls
docker-compose.yml
docker-compose.yml:
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
container_name: es01
environment:
- node.name=es01
- discovery.seed_hosts=es02
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- esnet
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
container_name: es02
environment:
- node.name=es02
- discovery.seed_hosts=es01
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata02:/usr/share/elasticsearch/data
networks:
- esnet
kibana:
image: docker.elastic.co/kibana/kibana:7.3.2
container_name: kibana
ports: ['5601:5601']
networks: ['esnet']
environment:
- SERVER_NAME=kibana.localhost
- ELASTICSEARCH_HOSTS=http://es01:9200
- I18N_LOCALE=zh-CN
- ELASTICSEARCH_USERNAME=elastic
- ELASTICSEARCH_PASSWORD=mypasword
depends_on: ['es01']
volumes:
esdata01:
driver: local
esdata02:
driver: local
networks:
esnet:
在这个配置中,我们创建了两个 Elasticsearch 的 node:es01 及 es02。节点 es01 侦听 localhost:9200,而 es02 通过 Docker 网络与 es01 对话。同时我们也创建了另外一个kibana 的 docker。我们可以在 environment 中配置它所需要的参数。具体的参数可以参照 Configuring Kibana。
等我们创建好这个 docker-compose.yml 文件后,我们在当前的目录下,打入如下的命令:
docker-compose up
或者:
docker-compose up -d
这里的 -d 选项表示在 detached 模式下,运行容器在后台。
运行的结果:
我们最终可以在浏览器中看见我们的 Kibana 被启动的样子:
如同我们之前的设置一样, 它运行起来的 Locale 设置的是中文。我们也可以同时看到两个被启动的 Elasticsearch 的节点:
一旦 docker 启动后,我们可以通过 docker 的命令来执行一些命令,比如
docker exec es01 ls /usr/share/elasticsearch
我们可以通过如下的命令进入到 docker 进行安装等:
docker exec -it es01 /bin/bash
$ docker exec -it es01 /bin/bash
[root@ec4d19f59a7d elasticsearch]# ls
LICENSE.txt README.textile config jdk logs plugins
NOTICE.txt bin data lib modules
[root@ec4d19f59a7d elasticsearch]#
这里的 es01 是我们的 Elasticsearch 实例的名称。
我们也可以通过如下的方式来配置 Kibana。我们可以在 docker-compose.yml 的目录下创建另外一个叫做 kibana.yml 的文件:
kibana.yml
#
# ** THIS IS AN AUTO-GENERATED FILE **
#
# Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
i18n.locale: "zh-CN"
xpack.monitoring.ui.container.elasticsearch.enabled: true
这里我们做了一些简单的设置,比如我们配置了 locale 为中文。我们可以修改我们的 docker-compose.yml 文件如下:
docker-compose.yml
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
container_name: es01
environment:
- node.name=es01
- discovery.seed_hosts=es02
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- esnet
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2
container_name: es02
environment:
- node.name=es02
- discovery.seed_hosts=es01
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata02:/usr/share/elasticsearch/data
networks:
- esnet
kibana:
image: docker.elastic.co/kibana/kibana:7.3.2
container_name: kibana
networks: ['esnet']
ports: ['5601:5601']
environment:
- ELASTICSEARCH_HOSTS=http://es01:9200
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
volumes:
esdata01:
driver: local
esdata02:
driver: local
networks:
esnet:
在这里,我们通过在 kibana 中的 volumes 来把本地的 kibana.yml 文件 bind mount 到我们的 docker 之中的 image 里。这样它代替 docker 里的 /usr/share/kibana/config/kibana.yml 文件从而使用我们在本地设置的 kibana.yml 文件。
当docker把所有的容器都跑起来后,我们可以通过如下的命令来查看:
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
es01 /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp,
9300/tcp
es02 /usr/local/bin/docker-entr ... Up 9200/tcp, 9300/tcp
kibana /usr/local/bin/dumb-init - ... Up 0.0.0.0:5601->5601/tcp
它显示了所有的端口的使用情况。
我们可以通过如下的办法把docker实例都停下来:
docker-compose down
这样我们很快地部署我们的 Elasticsearch 集群。
定制版本
从上面的 docker-compose.yml 中,我们可以看出来:所有的 Elastic Stack 的各个组件的版本都是一样的。如果我们想修改我们的版本的话,我们需要去修改每一个字符串。这样比较麻烦。为了方便 docker-compose 允许我们创建一个隐形的文件叫做 .env。 它的内容如下:
$ pwd
/Users/liuxg/elastic5/docker
liuxg:docker liuxg$ ls -al
total 16
drwxr-xr-x 4 liuxg staff 128 Mar 16 17:06 .
drwxr-xr-x 18 liuxg staff 576 Feb 6 14:08 ..
-rw-r--r-- 1 liuxg staff 28 Mar 16 17:06 .env
-rw-r--r--@ 1 liuxg staff 1473 Dec 17 11:02 docker-compose.yml
liuxg:docker liuxg$ cat .env
ELASTIC_STACK_VERSION=7.6.1
在这个文件中,我们可以定义 ELASTIC_STACK_VERSION=7.6.1。一旦这样定义后,我们可以把我们的 docker-compose.yml 修个为:
docker-compose.yml
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_STACK_VERSION}
container_name: es01
environment:
- node.name=es01
- discovery.seed_hosts=es02
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- esnet
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_STACK_VERSION}
container_name: es02
environment:
- node.name=es02
- discovery.seed_hosts=es01
- cluster.initial_master_nodes=es01,es02
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata02:/usr/share/elasticsearch/data
networks:
- esnet
kibana:
image: docker.elastic.co/kibana/kibana:${ELASTIC_STACK_VERSION}
container_name: kibana
ports: ['5601:5601']
networks: ['esnet']
environment:
- SERVER_NAME=kibana.localhost
- ELASTICSEARCH_HOSTS=http://es01:9200
- I18N_LOCALE=zh-CN
- ELASTICSEARCH_USERNAME=elastic
- ELASTICSEARCH_PASSWORD=mypassword
depends_on: ['es01']
volumes:
esdata01:
driver: local
esdata02:
driver: local
networks:
esnet:
这样以后如果我们想换一个版本的话,我们只需要修改 .env 文件的版本定义即可。
更进一步
如果你想了解如何为我们的由 docker 创建的 Elasticsearch 集群配置安全访问,请阅读我的另外一篇文章 “Elastic:为 Elastic Docker 部署设置安全”。
Elastic Stack docker 部署
参考:
【1】Running Kibana on Docker | Kibana Guide [7.3] | Elastic
【2】Installing Elasticsearch | Elasticsearch Guide [7.3] | Elastic
【3】elastic-training/docker-compose.yml at master · BigDataBoutique/elastic-training · GitHub