Dockerfileを読んでみる(elasticsearch-docker)

## dockerとは
* コンテナという仮想的な空間を提供して、その中でアプリケーションを実行できる
* [docker公式](https://www.docker.com/)

## Dockerfileとは
* Dockerコンテナーの構成内容を書くみたい
* Makefileみたいなイメージ

## なんで読んだ？
* Dockerはなんとなく使えていたが、どんな構成になっているかわかっていなかった
* そのうちカスタムするんじゃね？知ってなきゃやばくね？って思った
* どのように構成を指定しているかをちゃんと理解したほうが良いと思った
* ![](http://tiqav.com/Jx.gif)

## 対象
* elastic公式の、Elasticsearchコンテナ
* ちょっと使うことがあったので
* [elastic/elasticsearch-docker
](https://github.com/elastic/elasticsearch-docker/build/elasticsearch/Dockerfile)

## ざっと見る
![](http://tiqav.com/1nH.jpg)
だめだ・・
１行ずつ愚直に調べながら読むしかねぇ・・・

```
FROM docker.elastic.co/elasticsearch/elasticsearch-alpine-base:latest
```

* `FROM`は元となるDockerイメージを指定する命令文
* `elasticsearch-alpine-base`はAlpin LinuxをベースとしたElasticSearch
* Alpin Linuxは軽量でセキュアなLinuxイメージ([Alpine Linux](https://alpinelinux.org/))
* Alpin Linuxを使うとDockerイメージのサイズを減らせるらしい。（参考： [Alpine Linux で Docker イメージを劇的に小さくする](http://qiita.com/asakaguchi/items/484ba262965ef3823f61)）
* つまり、イメージのサイズを小さくするためのベースを使っているよ、と

```
MAINTAINER Elastic Docker Team <docker@elastic.co>
```
* `MAINTAINER`は生成するイメージの Author （作者）フィールドを指定します。([公式](http://docs.docker.jp/engine/reference/builder.html#maintainer)より)
* カスタムするときは自分のアカウントとかに書き換えるかな

```
ARG ELASTIC_VERSION
ARG ES_DOWNLOAD_URL
ARG ES_JAVA_OPTS
```

* `ARG`は実行時に受け取る引数
* Makefileから実行するときにそれぞれ引数で指定している
* `ELASTIC_VERSION` ：バージョン
* `ES_DOWNLOAD_URL ` ：Elasticsearchのダウンロード先
* `ES_JAVA_OPTS` ：検証環境用のパラメータっぽいけど、Makefileからの指定なし。（よくわからん）

```
ENV PATH /usr/share/elasticsearch/bin:$PATH
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
```

* 環境変数の設定
* `PATH`はElasticsearchのPATHを追加している
* `JAVA_HOME`はそのままjava homeの指定をする

```
WORKDIR /usr/share/elasticsearch
```

* `WORKDIR`は命令実行時の作業ディレクトリの指定

```
# Download/extract defined ES version. busybox tar can't strip leading dir.
RUN wget ${ES_DOWNLOAD_URL}/elasticsearch-${ELASTIC_VERSION}.tar.gz && \
    EXPECTED_SHA=$(wget -O - ${ES_DOWNLOAD_URL}/elasticsearch-${ELASTIC_VERSION}.tar.gz.sha1) && \
    test $EXPECTED_SHA == $(sha1sum elasticsearch-${ELASTIC_VERSION}.tar.gz | awk '{print $1}') && \
    tar zxf elasticsearch-${ELASTIC_VERSION}.tar.gz && \
    chown -R elasticsearch:elasticsearch elasticsearch-${ELASTIC_VERSION} && \
    mv elasticsearch-${ELASTIC_VERSION}/* . && \
    rmdir elasticsearch-${ELASTIC_VERSION} && \
    rm elasticsearch-${ELASTIC_VERSION}.tar.gz
```
なげぇ・・・
１文ずつ見てみる



```RUN wget ${ES_DOWNLOAD_URL}/elasticsearch-${ELASTIC_VERSION}.tar.gz```
* `RUN`はコマンドを実行して、結果をコミットする
* 指定したURLからElasticsearchのtar.gzを取得して

```EXPECTED_SHA=$(wget -O - ${ES_DOWNLOAD_URL}/elasticsearch-${ELASTIC_VERSION}.tar.gz.sha1)```
* `EXPECTED_SHA` にチェックサムを格納し、

```test $EXPECTED_SHA == $(sha1sum elasticsearch-${ELASTIC_VERSION}.tar.gz | awk '{print $1}')```
* チェックサムを検証して、

```tar zxf elasticsearch-${ELASTIC_VERSION}.tar.gz```
* tar.gzを解凍し、


```chown -R elasticsearch:elasticsearch elasticsearch-${ELASTIC_VERSION}```
* 権限を付与して、


```mv elasticsearch-${ELASTIC_VERSION}/* .```
* 解凍したファイルをカレントに移動し、

```rmdir elasticsearch-${ELASTIC_VERSION}```
* 解凍したディレクトリを削除して、

```rm elasticsearch-${ELASTIC_VERSION}.tar.gz```
* tar.gzを削除する

**なんだ・・・ダウンロードして配置してるだけじゃん**


```
RUN set -ex && for esdirs in config data logs; do \
        mkdir -p "$esdirs"; \
        chown -R elasticsearch:elasticsearch "$esdirs"; \
    done
```

* `set -e` で、0以外のステータスで終了した時に即終了する
* `set -x` で、コマンドの変数などを展開した状態でコンソールに表示する
* `config`, `data`, `logs` のディレクトリを作成して権限を変更する

```
USER elasticsearch
```

* `USER`は命令実行時のユーザを指定する
* elasticsearchユーザを指定する

```
# Install xpack
RUN eval ${ES_JAVA_OPTS:-} elasticsearch-plugin install --batch x-pack
```

* Elasticsearchのプラグイン(x-pack)をインストールする

```
COPY elasticsearch.yml config/
COPY log4j2.properties config/
COPY bin/es-docker bin/es-docker
```

* `COPY`はそのままコピー
* 各ファイルをコピーする


```
USER root
```

* rootユーザを指定する

```
RUN chown elasticsearch:elasticsearch config/elasticsearch.yml config/log4j2.properties bin/es-docker && \
    chmod 0750 bin/es-docker
```

* 先程コピーしたファイルの権限を変更する

```
USER elasticsearch
```
* elasticsearchユーザを指定する

```
CMD ["/bin/bash", "bin/es-docker"]
```
* `CMD`はコンテナ実行時の処理をどの形式で行うか指定する

```
EXPOSE 9200 9300
```
* `EXPOSE`はListenするポートを指定する


## まとめ
* Alpin Linuxを使って軽量なイメージを作っている
* 通常のインストールコマンドとかもそのまま使えそう
* 他にやってることとしては、Elastic公式からtar.gzをダウンロードしてきて配置しているだけだった
* 1行ずつちゃんと読めば、むずかいしいことはしていない
* カスタマイズも結構楽にできそう

## プラグインとか追加したい場合は
* 以下のように追加する

```
RUN elasticsearch-plugin install [プラグイン名]
```

## 参考
* [Dockerfile リファレンス](http://docs.docker.jp/engine/reference/builder.html)