如何挂载容器可写主机目录?

6
我要尝试使用Docker运行ELK堆栈。我发现docker-elk已经为我设置了配置,使用docker-compose
我希望将elasticsearch数据存储在主机上而不是容器中。根据docker-elk的README,我在docker-compose.yml文件中的elasticsearch部分添加了一个volumes行:
elasticsearch:
  image: elasticsearch:latest
  command: elasticsearch -Des.network.host=0.0.0.0
  ports:
    - "9200"
    - "9300"
  volumes:
    - ../../env/elasticsearch:/usr/share/elasticsearch/data

然而,当我运行docker-compose up时,出现以下情况:
$ docker-compose up
Starting dev_elasticsearch_1
Starting dev_logstash_1
Starting dev_kibana_1
Attaching to dev_elasticsearch_1, dev_logstash_1, dev_kibana_1
kibana_1        | Stalling for Elasticsearch
elasticsearch_1 | [2016-03-09 00:23:35,193][WARN ][bootstrap                ] unable to install syscall filter: seccomp unavailable: your kernel is buggy and you should upgrade
elasticsearch_1 | Exception in thread "main" java.lang.IllegalStateException: Unable to access 'path.data' (/usr/share/elasticsearch/data/elasticsearch)
elasticsearch_1 | Likely root cause: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/elasticsearch
elasticsearch_1 |   at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
elasticsearch_1 |   at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
elasticsearch_1 |   at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
... etc ...

在查看 ../../env 后,发现已经创建了 elasticsearch 目录,但是该目录为空。如果我创建 ../../env/elasticsearch/elasticsearch,则会出现访问错误 /usr/share/elasticsearch/data/elasticsearch/nodes。如果创建 /nodes,则会出现 /nodes/0 的错误,以此类推...

总之,容器似乎没有对该目录的写入权限。

我该如何获得写入权限? 我尝试过 chmod a+wx ../../env/elasticsearch,然后它就能够创建下一个目录,但是该目录的权限为 drwxr-xr-x,然后又卡住了。

我不喜欢以 root 身份运行此操作的想法。


docker-compose run --rm elasticsearch stat -c "%U %G" /usr/share/elasticsearch/data 的输出是什么? - kojiro
@kojiro:我收到了“未知员工”的信息。 - Claudiu
1个回答

2

Docker的基础镜像通常不会考虑这些问题,因为它希望您使用卷或卷容器。挂载到主机的支持较差。但只要拥有目录的UID不是零(根据我们的评论交流似乎不是),您应该能够以已拥有目录的用户身份运行elasticsearch。您可以尝试从容器中删除并重新添加elasticsearch用户,并指定其UID。

您需要在entrypoint时间执行此操作,因此最好的方法是构建自定义容器。创建一个名为my-entrypoint的文件,其中包含以下内容:

#!/bin/bash

# Allow running arbitrary one-off commands
[[ $1 && $1 != elasticsearch ]] && exec "$@"
# Otherwise, fix perms and then delegate the rest to vanilla
target_uid=$(stat -c %u /usr/share/elasticsearch/data)
userdel elasticsearch
useradd -u "$target_uid" elasticsearch
. /docker-entrypoint "$@"

请确保它是可执行的。然后创建一个包含以下内容的Dockerfile:

FROM elasticsearch
COPY my-entrypoint /
ENTRYPOINT ["/my-entrypoint"]

最后更新您的docker-compose.yml文件:
elasticsearch:
  build: .
  command: elasticsearch -Des.network.host=0.0.0.0
  ports:
    - "9200"
    - "9300"
  volumes:
    - ../../env/elasticsearch:/usr/share/elasticsearch/data

现在当你运行docker-compose up时,它应该使用你的更改来构建一个elasticsearch容器。(我曾经为Magento做过类似的事情,如此处所示。)

啊,有意思!我尝试了你在这里写的,但它最终没起作用...一开始我以为是 /docker-entrypoint.sh 而不是 /docker-entrypoint,但仍然没有起作用。然而,根据你的前两句话,我决定让自己变得更容易,只使用命名卷。 - Claudiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接