Dockerfileを極めて、Dockerマスターになろう！

# Dockerfileを極めて、Dockerマスターになろう！

- ***Dockerfile***とは

- 「Dockerfile」ファイルは、プログラムのビルドでよく利用されるmakeツールの「Makefile」ファイルと同様に、Dockerコンテナーの構成内容をまとめて記述するシンプルなテキスト形式のファイルです。*

## 注意事項
- *Dockerでは*  ==***コマンドをフォアグラウンドで動かさないとコンテナが停止***== *してしまいます。特に、* ***デーモンプログラム*** *は、* ***デフォルトでバックグランド動作をするため*** *設定したものの* ***「起動しない/自動的に停止してしまう」*** *といった不具合に遭う原因となるので注意が必要です。*
  
- *例えばnginxはデフォルトはデーモンとして動くので、(nginxの)daemon off設定を行い、* ***フォアグラウンドで動かす必要があります。***

~~~
ENTRYPOINT /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
~~~

## 基本構文
- 1行につき1つの操作を｛命令｝と｛引数｝でスペース区切りで記述します。「#」から始まる行はコメントとして処理されます。「docker build」コマンドでは、「Dockerfile」ファイルの上から順番に処理が実行されます。

~~~
｛命令｝ ｛引数｝
~~~

- ｛命令｝は、大文字／小文字を区別しませんが、識別しやすいよう大文字にするのが推奨です。主な｛命令｝と用途を以下に示します。

|**｛命令｝**|**用途**|
|---|---|
|**FROM**|元となるDockerイメージの指定|
|**MAINTAINER**|作成者の情報|
|**RUN**|コマンドの実行|
|**ADD**|ファイル／ディレクトリの追加|
|**CMD**|コンテナーの実行コマンド 1|
|**ENTRYPOINT**|コンテナーの実行コマンド 2|
|**WORKDIR**|作業ディレクトリの指定|
|**ENV**|環境変数の指定|
|**USER**|実行ユーザーの指定|
|**EXPOSE**|ポートのエクスポート|
|**VOLUME**|ボリュームのマウント|

## CMDとENTRYPOINTの違い
- *「docker run」コマンドでは、引数にコンテナーで実行するコマンドを指定しました。Dockerイメージの用途によっては、サービスを提供する場合など実行するコマンドが最初から決まっている場合があります。* ***「ENTRYPOINT」*** *および* ***「CMD」*** *を記述することで実行するコマンドおよび引数を事前に定義でき、「docker run」コマンド実行時に* ***省略*** *できるようになります。* ***「CMD」*** *の場合は「docker run」で実行するコマンドを* ***上書きできます*** *が、* ***「ENTRYPOINT」*** *の場合は* ***上書きできない*** *点が異なります。*

## ENVでパスを設定

- `RUN` したい時にパスが通っていないとエラーになります。以下のように ***`RUN` の前あたりで`ENV`でパスを通してあげる***と大概の場合は ***`RUN`が通ります***。(bashのexportと同じですね!)

~~~
ENV PATH $PATH:/usr/local/jruby/bin
RUN jgem install hoge
~~~

- 上記の例は PATH に /usr/local/jruby/bin を追加しています。この後(パスが通るため) jgem や jruby 等が使えるようになります。

## EXPOSEで外部に公開するポートを指定

- *この設定は、`docker run`時に* ***`-pオプション`を指定するのと同じ役割*** *があります。例えば、* ***nginxを外部に公開するには、80番ポートを公開すれば良い*** *ので、Dockerfileに*

~~~
EXPOSE 80
~~~

と書くことができますが、EXPOSEコマンドはコンテナのポートを公開するだけなので、このままでは ***外部からアクセスはできません。*** 外部からアクセスする場合は、 ==vmの起動時に== `docker run -p <ホストOSポート番号>:<コンテナポート番号>` のように、 ==ホストOSのポートにコンテナのポートをバインド== しましょう。

## ビルド

- Dockerfileからdockerイメージのビルド

~~~
docker build [ -t ｛イメージ名｝ [ :｛タグ名｝ ] ] ｛Dockerfileのあるディレクトリ｝
~~~

- nginxのDockerfileからdockerイメージをビルドする例

==nginx1.0フォルダには、下記のものを入れておく。==

- Dockerfile
- ADDコマンドでコピーするファイル。(***.conf等の設定ファイルを予め修正しておいて、同梱すると良い)

~~~sh
docker build -t soushi/nginx:1.0 ~/OneDrive/docker/nginx1.0/
~~~

## Dockerfileの一例

- nginxサーバーを作るためのDockerfile

~~~
FROM centos:6
MAINTAINER soushi <webservice@soushi.jp>
RUN rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
RUN yum -y install nginx
ENTRYPOINT /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
RUN sed -i -e "/^http/a \ \ \ \ server \{\n\tlocation \/ \{\n\t\troot \/var\/www\;\n\t\}\n\n\ \ \ \ \}" /etc/nginx/nginx.conf

# Define mountable directories.
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/var/log/nginx", "/var/www"]

# Define working directory.
WORKDIR /etc/nginx

# Define default command.
CMD ["nginx"]

# Expose ports.
EXPOSE 80
EXPOSE 443
~~~

# コンテナが起動しない場合

## 1 ENTRYPOINTに引数を書く場合、それぞれをダブルクォーテーションで囲う。

~~~
!これは誤り
ENTRYPOINT ["/usr/bin/influxdb -config=/opt/influxdb/versions/0.8.8/config.toml"]
~~~

~~~
# 正しくは下記のように書く
ENTRYPOINT ["/usr/bin/influxdb", "-config=/opt/influxdb/versions/0.8.8/config.toml"]
~~~