Elasticsearch docker volume permission issue

Elasticsearch之docker安装

最近由于工作原因,需要倒腾下Elasticsearch ,虽然本人的工作中,大部分情况下使用的都是Solr,但是这并不能挡住我学习Elasticsearch的激情,这里我并不做这两个工具的好坏,只要用的顺手用的舒服就是好工具。这里我以docker安装为例子。

环境准备

笔者使用的环境为华为云上的一台虚拟机,这里简单的描述下dockerdocker-compose的安装

1
2
yum -y install docker docker-compose 
#具体的版本为: docker-compose-1.18.0-4.el7.noarch , docker-1.13.1-103.git7f2769b.el7.centos.x86_64

docker 安装elasticsearch 还是比较简单的,我们直接参考官方文档,这里我们使用的版本号码是7.4.1。大部分情况下,如果你是为了体验elasticsearch,或者搭建一个简单的测试环境,那么elasticsearch的官方文档应该就能解决这个问题,但是由于笔者需要存储大概几十万的数据进去,而且由于使用的是云上的环境,一般来说系统盘的小大都很小(常见的值为8GB),所以必须将elasticsearch的data目录挂载到数据盘上。而问题就出现在docker的目录映射上。

AccessDeniedException

上面提过,笔者大部分情况下使用的是Solr,也自定了Solr的docker,在Solr中(目前使用的版本是6.5.1),如果需要将索引数据挂载出来,只要在docker-compose文件中直接做volume映射就行了,例如

1
2
3
4
...
volumes:
- system_data_path:inside_docker_solr_index_data_path
..

同样的道理,我直接修改了docker-compose文件,将instance上的另外一块磁盘上的某个目录映射到docker中的/usr/share/elasticsearch/data/,这里直接上笔者的docker-compose文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## docker-compose.yml
version: '3'
services:
elasticsearch:
image: 'docker.elastic.co/elasticsearch/elasticsearch:7.4.1'
ports:
- 6200:9200
- 6300:9300
env_file: elasticsearch_env
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65535
hard: 65535
volumes:
- ./tmp:/usr/share/elasticsearch/data/
privileged: true
## elasticsearch_env
discovery.type=single-node
cluster.name=test
node.name=node-01
bootstrap.memory_lock=true

但是当我直接docker-compose up -d之后,缺发现container无法启动,查下了日志具体的错误为org.elasticsearch.bootstrap.StartupException: ElasticsearchException[failed to bind service]; nested: AccessDeniedException,貌似是没有权限???
完整的错误为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
{"type": "server", "timestamp": "2019-10-27T03:27:37,816Z", "level": "WARN", "component": "o.e.b.ElasticsearchUncaughtExceptionHandler", "cluster.name": "test", "node.name": "node-01", "message": "uncaught exception in thread [main]",
"stacktrace": ["org.elasticsearch.bootstrap.StartupException: ElasticsearchException[failed to bind service]; nested: AccessDeniedException[/usr/share/elasticsearch/data/nodes];",
"at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:163) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:125) ~[elasticsearch-cli-7.4.1.jar:7.4.1]",
"at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[elasticsearch-7.4.1.jar:7.4.1]",
"Caused by: org.elasticsearch.ElasticsearchException: failed to bind service",
"at org.elasticsearch.node.Node.<init>(Node.java:614) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.node.Node.<init>(Node.java:255) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:221) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:221) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:349) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159) ~[elasticsearch-7.4.1.jar:7.4.1]",
"... 6 more",
"Caused by: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/nodes",
"at sun.nio.fs.UnixException.translateToIOException(UnixException.java:90) ~[?:?]",
"at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[?:?]",
"at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) ~[?:?]",
"at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:389) ~[?:?]",
"at java.nio.file.Files.createDirectory(Files.java:693) ~[?:?]",
"at java.nio.file.Files.createAndCheckIsDirectory(Files.java:800) ~[?:?]",
"at java.nio.file.Files.createDirectories(Files.java:786) ~[?:?]",
"at org.elasticsearch.env.NodeEnvironment.lambda$new$0(NodeEnvironment.java:272) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.env.NodeEnvironment$NodeLock.<init>(NodeEnvironment.java:209) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:269) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.node.Node.<init>(Node.java:275) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.node.Node.<init>(Node.java:255) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:221) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:221) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:349) ~[elasticsearch-7.4.1.jar:7.4.1]",
"at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159) ~[elasticsearch-7.4.1.jar:7.4.1]",
"... 6 more"] }

这里想到之前在没有使用docker安装elasticsearch的时候elasticsearch默认是不使用root用户进行启动的,这应该就是root cause,一顿google之后发现解决方案大致有两种

  • 将elasticsearch用户加入到root组
    因为需要重新打docker,比较蛋疼,这里直接放上解决方案的链接https://github.com/elastic/elasticsearch-docker/issues/49
  • 使用docker volume来解决权限的问题
    在官方的给出的docker-compose中有个 driver: local,使用这个确实elasticsearch就可以启动了,是应为这里的local是指docker安装的磁盘,如果docker安装所有的磁盘空间足够大,那么确实没啥问题,但是一般来说各种云的虚拟主机的系统盘默认也就8GB,确实不太够用。这里也是经过一番google之后直接找到了解决方案(直接上docker-compose的内容)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    version: '3'
    services:
    elasticsearch:
    image: 'docker.elastic.co/elasticsearch/elasticsearch:7.4.1'
    ports:
    - 9200:9200
    - 9300:9300
    env_file: elasticsearch_env
    ulimits:
    memlock:
    soft: -1
    hard: -1
    nofile:
    soft: 65535
    hard: 65535
    volumes:
    - esdata:/usr/share/elasticsearch/data/
    - eslog:/usr/share/elasticsearch/logs/
    privileged: true

    volumes:
    esdata:
    driver: local
    driver_opts:
    device: /data/elastic_search/index_data/ # 挂载日志目录到/data下(/data是数据盘)
    o: bind
    eslog:
    driver: local
    driver_opts:
    device: /data/elastic_search/logs/ # 挂载日志目录到/data下(/data是数据盘)
    o: bind

修改完之后就启动成功了。如果想看docker中有哪些volume可以通过docker volume list来查看

1
2
3
4
# docker volume list
DRIVER VOLUME NAME
local elasticsearch_esdata
local elasticsearch_eslog

关于docker的小技巧

  • 如何加快国内docker pull的速度

由于docker hub的服务器在海外,所以直接从docker hub上拉取一些docker大家会发现巨慢无比,往往拉取一些镜像需要等好久,这里给大家推荐Daocloud,配置起来也非常简单:

1
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

如果执行失败的话直接修改/etc/docker/daemon.json,加入

1
{"registry-mirrors": ["http://f1361db2.m.daocloud.io"]}

重启docker服务之后再拉取即可,笔者尝试了之后,发现速度确实比之前快很多

  • 如何使用非root用户玩转docker

很多时候我们在服务器或者个人的开发电脑上,都不是root用户(个人的测试机器除外),而且有的时候公司的运维由于安全问题也不愿意给开发root权限,那么是不是玩转docker一定要root权限呢?答案是不用,具体的原理也很简单,就是把某个非root用户加入到docker对应的用户组中,这里以centos 7 为例子:

1
2
3
# 例如当前的xxx user用户没有指定docker命令的权限
[xxx user]$ docker ps -a
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/containers/json?all=1: dial unix /var/run/docker.sock: connect: permission denied

1)在root在执行下列命令,将当前用户加入到docker对应的用户组中
(可以通过cat /etc/group | grep docker命令查看具体的docker对应的用户组)

1
usermod -aG dockerroot <user_name>

2)添加dockerroot用户组信息到/etc/docker/daemon.json中(root在执行)

1
2
3
{
"group": "dockerroot"
}

3)重启docker服务(在root下执行)

1
2
root#service docker restart 
Redirecting to /bin/systemctl restart docker.service

4) 在下重新执行docker命令后,就会发现非root用户也可以执行docker了

1
2
3
<user_name>$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
595d4fc7057b local-dtr.zhihuiya.com/base/ant-maven:latest "bash" 4 weeks ago Exited (0)

参考文章

http://www.softpanorama.org/VM/Docker/Installation/rhel7_docker_package_dockerroot_problem.shtml
https://ywnz.com/linuxjc/4487.html