2017年2月26日日曜日

Docker で Elasticsearch5.1 と head を試す


Docker で Elasticsearch5.1 と head を試してみます。
検証環境は以下のとおり
・Dockerホスト: CentOS7(メモリ1GB)
・Dcoker: 1.10.3
・docker-compose: 1.10.0

docker-composeの構成


以下の構成で docker-compose の環境を用意しました。
[root@centos0702 docker]# tree -Fl ./elasticsearch/
./elasticsearch/
├── docker-compose.yml
├── es51/
│   ├── Dockerfile
│   ├── config/
│   │   ├── elasticsearch.yml
│   │   ├── jvm.options
│   │   └── log4j2.properties
│   └── docker-entrypoint.sh*
└── head/
     └── Dockerfile
プロジェクト名は、"elasticsearch" の前提で設定を行います。

docker-compose.yml の設定


docker-compose.yml の内容は以下のとおり
[root@centos0702 docker]# cat elasticsearch/docker-compose.yml
version: '2'
services:
  es51a:
    build: ./es51
    image: elasticsearch:5.1
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - ./vol/es/data:/usr/share/elasticsearch/data
      - ./vol/es/backup:/usr/share/elasticsearch/backup

  es51b:
    image: elasticsearch:5.1

  head:
    build: ./head
    image: elasticsearch-head
    ports:
      - "9100:9100"
"es51a" は Elasticsearch5.1です。通常は、この1台で検証を行います。
"es51b" も Elasticsearch5.1ですが、こちらは、クラスタの検証をする場合だけ使用します。
"head" は、Elasticsearch-head です。

Elasticsearch のビルド環境


Elasticsearch5.1 のビルド環境は、es51 ディレクトリにあります。
DocukerHUB にあったものを、少し、修正して使います。
Dokerfile の内容は以下のとおり。
[root@centos0702 es51]# cat Dockerfile
FROM openjdk:8-jre

# grab gosu for easy step-down from root
ENV GOSU_VERSION 1.7
RUN set -x \
        && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
        && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
        && export GNUPGHOME="$(mktemp -d)" \
        && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
        && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
        && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
        && chmod +x /usr/local/bin/gosu \
        && gosu nobody true

RUN set -ex; \
# https://artifacts.elastic.co/GPG-KEY-elasticsearch
        key='46095ACC8548582C1A2699A9D27D666CD88E42B4'; \
        export GNUPGHOME="$(mktemp -d)"; \
        gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
        gpg --export "$key" > /etc/apt/trusted.gpg.d/elastic.gpg; \
        rm -r "$GNUPGHOME"; \
        apt-key list

# https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html
# https://www.elastic.co/guide/en/elasticsearch/reference/5.0/deb.html
RUN set -x \
        && apt-get update && apt-get install -y --no-install-recommends apt-transport-https && rm -rf /var/lib/apt/lists/* \
        && echo 'deb https://artifacts.elastic.co/packages/5.x/apt stable main' > /etc/apt/sources.list.d/elasticsearch.list

ENV ELASTICSEARCH_VERSION 5.1.1
ENV ELASTICSEARCH_DEB_VERSION 5.1.1

RUN set -x \
        \
# don't allow the package to install its sysctl file (causes the install to fail)
# Failed to write '262144' to '/proc/sys/vm/max_map_count': Read-only file system
        && dpkg-divert --rename /usr/lib/sysctl.d/elasticsearch.conf \
        \
        && apt-get update \
        && apt-get install -y --no-install-recommends "elasticsearch=$ELASTICSEARCH_DEB_VERSION" \
        && rm -rf /var/lib/apt/lists/*

ENV PATH /usr/share/elasticsearch/bin:$PATH

WORKDIR /usr/share/elasticsearch

COPY config ./config

RUN set -ex \
        && for path in \
                ./data \
                ./logs \
                ./config \
                ./config/scripts \
                ./backup \
        ; do \
                mkdir -p "$path"; \
                chown -R elasticsearch:elasticsearch "$path"; \
        done

RUN elasticsearch-plugin install analysis-kuromoji \
     && elasticsearch-plugin install analysis-icu

VOLUME [ "/usr/share/elasticsearch/data", "/usr/share/elasticsearch/backup" ]

COPY docker-entrypoint.sh /

EXPOSE 9200 9300
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["elasticsearch"]
オリジナルからの変更ポイントは以下のとおり。
・スナップショットの格納先として"backup"ディレクトリの作成を追加
・kuromoji/icu プラグインのインストール

config/elasticsearch.yml は以下のとおり。
3台でクラスタを組めるようにしています。
[root@centos0702 es51]# cat config/elasticsearch.yml
#########################
# 基本設定
#########################

# http アクセスを制限しない
http.host: 0.0.0.0

# ノード名をホスト名にする
node.name: ${HOSTNAME}

# elasticsearch-head 用
# クロスドメインアクセスを許可することでWEBブラウザから直接クエリを実行できる
http.cors.enabled: true
http.cors.allow-origin: "*"

#########################
# クラスタ設定
#########################

# クラスタメンバのアクセスを制限しない
transport.host: 0.0.0.0

# 1台でもマスタになれるようにしておく。
# 通常は、SplitBrain 対策として 全ノードの過半数を設定
discovery.zen.minimum_master_nodes: 1

# 検証環境が非力なのでタイムアウトを長めにする
discovery.zen.ping.unicast.hosts.resolve_timeout: 60s
discovery.zen.ping_timeout: 60s

# クラスタのノードを指定
discovery.zen.ping.unicast.hosts: ["elasticsearch_es51a_1","elasticsearch_es51b_1","elasticsearch_es51b_2"]

# クラスタ名
cluster.name: demo-cluster

#########################
# スナップショット設定
#########################

# スナップショットの格納先
path.repo: ["/usr/share/elasticsearch/backup"]

config/jvm.options は以下のとおり。
HEEP_SIZE を 256MB にしています。(デフォルトは2GB)
[root@centos0702 es51]# cat config/jvm.options
## JVM configuration

################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

-Xms256m
-Xmx256m

################################################################
## Expert settings
################################################################
##
## All settings below this section are considered
## expert settings. Don't tamper with them unless
## you understand what you are doing
##
################################################################

## GC configuration
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

## optimizations

# disable calls to System#gc
-XX:+DisableExplicitGC

# pre-touch memory pages used by the JVM during initialization
-XX:+AlwaysPreTouch

## basic

# force the server VM (remove on 32-bit client JVMs)
-server

# explicitly set the stack size (reduce to 320k on 32-bit client JVMs)
-Xss1m

# set to headless, just in case
-Djava.awt.headless=true

# ensure UTF-8 encoding by default (e.g. filenames)
-Dfile.encoding=UTF-8

# use our provided JNA always versus the system one
-Djna.nosys=true

# use old-style file permissions on JDK9
-Djdk.io.permissionsUseCanonicalPath=true

# flags to keep Netty from being unsafe
-Dio.netty.noUnsafe=true
-Dio.netty.noKeySetOptimization=true

# log4j 2
-Dlog4j.shutdownHookEnabled=false
-Dlog4j2.disable.jmx=true
-Dlog4j.skipJansi=true

## heap dumps

# generate a heap dump when an allocation from the Java heap fails
# heap dumps are created in the working directory of the JVM
-XX:+HeapDumpOnOutOfMemoryError

# specify an alternative path for heap dumps
# ensure the directory exists and has sufficient space
#-XX:HeapDumpPath=${heap.dump.path}

## GC logging

#-XX:+PrintGCDetails
#-XX:+PrintGCTimeStamps
#-XX:+PrintGCDateStamps
#-XX:+PrintClassHistogram
#-XX:+PrintTenuringDistribution
#-XX:+PrintGCApplicationStoppedTime

# log GC status to a file with time stamps
# ensure the directory exists
#-Xloggc:${loggc}

# Elasticsearch 5.0.0 will throw an exception on unquoted field names in JSON.
# If documents were already indexed with unquoted fields in a previous version
# of Elasticsearch, some operations may throw errors.
#
# WARNING: This option will be removed in Elasticsearch 6.0.0 and is provided
# only for migration purposes.
#-Delasticsearch.json.allow_unquoted_field_names=true

config/log4j2.properties は以下のとおり。
[root@centos0702 es51]# cat config/log4j2.properties
status = error

appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n

rootLogger.level = info
rootLogger.appenderRef.console.ref = console

docker-entrypoint.sh は以下のとおり。
このファイルには実行権限をつけておきます。( chmod +x )
[root@centos0702 es51]# cat docker-entrypoint.sh
#!/bin/bash

set -e

# Add elasticsearch as command if needed
if [ "${1:0:1}" = '-' ]; then
        set -- elasticsearch "$@"
fi

# Drop root privileges if we are running elasticsearch
# allow the container to be started with `--user`
if [ "$1" = 'elasticsearch' -a "$(id -u)" = '0' ]; then
        # Change the ownership of user-mutable directories to elasticsearch
        for path in \
                /usr/share/elasticsearch/data \
                /usr/share/elasticsearch/logs \
        ; do
                chown -R elasticsearch:elasticsearch "$path"
        done

        set -- gosu elasticsearch "$@"
        #exec gosu elasticsearch "$BASH_SOURCE" "$@"
fi

# As argument is not related to elasticsearch,
# then assume that user wants to run his own process,
# for example a `bash` shell to explore this image
exec "$@"

elasticsearch-head のビルド環境


elasticsearch-head のビルド環境は head ディレクトリになります。
Dockerfile は以下のとおり。
[root@centos0702 docker]# cat elasticsearch/head/Dockerfile
FROM node:slim

RUN apt-get update && \
    apt-get install -y git node-gyp && \
    apt-get autoremove -y && \
    apt-get clean all && \
    rm -rf /var/lib/apt/lists/* && \
    npm install -g grunt grunt-cli && \
    git clone git://github.com/mobz/elasticsearch-head.git

RUN cd elasticsearch-head && \
    npm install && \
    sed -i 's/port: 9100,/hostname: "0.0.0.0", port: 9100,/g' Gruntfile.js

WORKDIR /elasticsearch-head

EXPOSE 9100

CMD ["grunt", "server"]

Dockerイメージをビルド


Dockerイメージをビルドします。
[root@centos0702 elasticsearch]# pwd
/root/workspace/docker/elasticsearch
[root@centos0702 elasticsearch]# docker-compose buil
作成したイメージを確認します。
[root@centos0702 elasticsearch]# docker images
REPOSITORY                                TAG                 IMAGE ID            CREATED             SIZE
elasticsearch                             5.1                 e34960c49557        16 hours ago        366.4 MB
elasticsearch-head                        latest              fb3330d58553        29 hours ago        627.4 MB

動作確認


Dockerコンテナを起動して動作を確認します。
まず、es51a と head を起動します。
[root@centos0702 elasticsearch]# docker-compose up -d es51a
Creating network "elasticsearch_default" with the default driver
Creating elasticsearch_es51a_1
[root@centos0702 elasticsearch]# docker-compose up -d head
Creating elasticsearch_head_1
ブラウザで "http://<DockerホストのIPアドレス>:9100"  にアクセスします。
下図のような画面になればOKです。
赤枠には、"http://<DockerホストのIPアドレス>:9200" を入力します。



試しにドキュメントを登録してみます。
[root@centos0702 elasticsearch]# curl 'http://localhost:9200/index01/type01/1?pretty' -d '{"title":"テストのドキュメント"}'
{
  "_index" : "index01",
  "_type" : "type01",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : true
}
インデックスが作成され、head には以下のように表示されます。



Elsticsearch のノードを1台追加して、計2台にしてみます。
[root@centos0702 elasticsearch]# docker-compose up -d es51b
Creating elasticsearch_es51b_1
headの表示は以下のようになります。