docker es (Failed to created node environment)

原文地址

疑问

Hello,

I was trying to use elasticsearch-docker image for hosting dockerized elastichsearch cluster.

What I have noticed that the es-docker script:

https://github.com/elastic/elasticsearch-docker/blob/master/build/elasticsearch/bin/es-docker

is not assigning any permissions though it is running under non-root user inside container:

USER elasticsearch
CMD ["/bin/bash", "bin/es-docker"]

and documentation suggests to mount a volume for data in README:

docker run -d -p 9200:9200 -v esdatavolume:/usr/share/elasticsearch/data $ELASTIC_REG/elasticsearch

This is how I was thinking to run it:

FROM docker.elastic.co/elasticsearch/elasticsearch

ADD jvm.options /usr/share/elasticsearch/config/
ADD elasticsearch.yml /usr/share/elasticsearch/config/

EXPOSE 9200 9300

And docker-compose:


version: '2'

services:
  elasticsearch1:
    container_name: es1
    build: ./build
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - /data/elasticsearch1:/usr/share/elasticsearch/data:rw
    mem_limit: 3g
    restart: always

Which pretty aligns with README and docker-compose example in repository. But I was obviously getting exception regarding permissions:

[2016-11-11T10:36:18,442][INFO ][o.e.n.Node               ] [] initializing ...
[2016-11-11T10:36:18,462][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
Caused by: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/nodes
        at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84) ~[?:?]
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102) ~[?:?]
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107) ~[?:?]
        at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384) ~[?:?]
        at java.nio.file.Files.createDirectory(Files.java:674) ~[?:1.8.0_92-internal]
        at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781) ~[?:1.8.0_92-internal]
        at java.nio.file.Files.createDirectories(Files.java:767) ~[?:1.8.0_92-internal]
        at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:220) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.node.Node.<init>(Node.java:240) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.node.Node.<init>(Node.java:220) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:191) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:191) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:286) ~[elasticsearch-5.0.0.jar:5.0.0]
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:112) ~[elasticsearch-5.0.0.jar:5.0.0]
        ... 6 more

Of course I have already fixed that with another entrypoint script that uses the initial one which is pretty ugly solution though:

#!/bin/bash
chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/data;
su elasticsearch -c "/bin/bash es-docker"

And then Dockerfile change:

FROM docker.elastic.co/elasticsearch/elasticsearch

ADD jvm.options /usr/share/elasticsearch/config/
ADD elasticsearch.yml /usr/share/elasticsearch/config/

COPY entrypoint.sh bin/entrypoint.sh

USER root
CMD ["/bin/bash", "bin/entrypoint.sh"]

EXPOSE 9200 9300

I was really surprised that there was nobody creating any ticket/bug for this and now I am a bit confused if I misunderstood how this image should be used at all and I am missing some obvious solution for that? Am I doing something inappropriate?


解答

Hello Aleksandr,

Thank you for your interest in the Elasticsearch images.

There are a number of different issues you are having in your setup.

The permission errors you are getting in your example are because you are using a host dir as a data volume that doesn't match the uid/gid of the elasticsearch user in the image. Details in 2).

1) Tuning Elasticsearch configuration parameters

The way that you were thinking of running the image, i.e. creating your own custom image based on the Elastic one is fine, but you need to remember to chown the ADD'ed configuration files in your Dockerfile to the user/group elasticsearch. This is something done in the Elasticsearch Dockerfile right after copying elasticsearch.yml, as shown here

So your Dockerfile would then look like:

FROM docker.elastic.co/elasticsearch/elasticsearch:5.0.0

ADD jvm.options /usr/share/elasticsearch/config/
ADD elasticsearch.yml /usr/share/elasticsearch/config/
USER root
RUN chown elasticsearch:elasticsearch config/jvm.options config/elasticsearch.yml

USER elasticsearch
EXPOSE 9200 9300

For example, using a simple elasticsearch.yml file:

$ cat elasticsearch.yml 
cluster.name: "custom-cluster"
network.host: 0.0.0.0

and the same jvm.options as in the original image with a change of -Xms/-Xmx to 1G, a new image can be built using

docker build -t myes .

and running it with:

docker run -ti -p 9200:9200 -v /usr/share/elasticsearch/data myes

produces a working image with the right permissions under config/

NOTE: If you were to omit the chown commands elasticsearch.yml/jvm.options would be owned by 0:0 as documented in the Dockerfile ADD section 32 but it wouldn't be catastrophic for the Elasticsearch start as it would still have read access to those files. Still it's best practice to chown then files afterwards. I will update the documentation to warn about that for this configuration method.1

NOTE2:: You should be using FROM: docker.elastic.co/elasticsearch/elasticsearch:THEVERSION as opposed to relying on latest. Right now we have 5.0.0 and soon we will be pushing 5.0.1 (docker image versions are matching the Elasticsearch ones). Please try not to rely on :latest as it may bring whatever staging build and indeed, going forward, we will be deprecating :latest to avoid customers ending up with broken configurations.

2) Data volumes versus local mounts for /usr/share/elasticsearch/data

As you correctly mentioned in the README we recommend the use of a named volume. With docker cli this is accomplished with -v <nameofvolume>:/usr/share/elasticsearch/data. This volume will be created if not already present and can be seen with docker volume ls. The volume will persist even if you destroy the container, unless you explicitly remove it with docker volume rm <nameofvolume>.

In your docker-compose.yml example, however, you are using a host mounted directory (/data/elasticsearch1/). This will result in /usr/share/elasticsearch/data having the same permissions as your local dir. Therefore unless /data/elasticsearch/ is owned by 1000:1000 orchmod'ed to 777, Elasticsearch won't be able to write there!

So you will either need to make sure your local dir is chown -R elasticsearch:elasticsearch /data/elasticsearch1 before running the container or use non-host based data volumes.

The docker-compose.yml syntax for data volumes looks like:

# ...
    volumes:
      - esdata1:/usr/share/elasticsearch/data
volumes:
  esdata1:
    driver: local

Alternatively, if you don't mind ending up with a randomly named volume you can use

# ...
    volumes:
      - /usr/share/elasticsearch/data

The difference between data volumes and host mounted data volumes are described in the Docker Documentation .

Notes:

  1. The Docker documentation will very soon be part of the docs on the Elastic web site, so stay tuned! The documentation for Kibana on Docker is already there: https://www.elastic.co/guide/en/kibana/current/install.html 107

  2. There are number of Docker feature requests to add support for setting the uid/gid when mounting local dirs e.g. https://github.com/docker/docker/issues/2259; 124