Dockerfileの作り方（基礎）

# はじめに
Dockerは多くのIT開発企業で導入されている環境構築を楽にする技術です。
DockerfileはDockerImageの設計図のようなものです。
Dockerfileを自身で作成することで構築したい環境のDocker imageを作成できます。

# Dockerfile、DockerImage、コンテナの関係

Dockerfile => DockerImage => コンテナ　の順に作成します。

**DockerImageの作成方法**
Dockerfileが存在するディレクトリで docker build .

**コンテナの作成方法**
docker run （DockerImage名 or ID）


# Dockerfileのインストラクション
* FROM
* RUN
* CMD
* ENTRYPOINT
* COPY
* ADD
* ENV
* WORKDIR

# Dockerfile作成手順
### FROM
ベースとなるイメージを決定するインストラクションです。
Dockerfileの最初に記述します。
FROMの後には基本的にOSを記述します。

```Dockerfile
FROM OS(Docker imageから選ぶ)

例)FROM ubuntu:latest
例)FROM ruby:2.5
```

### RUN
FROMで記述したOSに対応するコマンドを実行するインストラクションです。
RUN毎にLayerが作成されます。（DockerImageは層を積み重ねていくように作成されます。）

```Dockerfile
RUN OSに対応するコマンド

例)FROM ubuntu:latest
   RUN touch test
=> DockerImageにはubuntuのLayerにtouch testのLayerが追加で作成されます。
（testというファイルを作成するDockerImageを作成しています。）

例)FROM ubuntu:latest
   RUN apt-get update && apt-get install -y \
       curl\
       nginx
=> DockerImageにはubuntuのLayerにcurlとnginxという2つのパッケージをインストールするLayerが追加作成されます。
(apt-get updateはインストールするパッケージを新しいものにするために記述し、apt-get installはパッケージをインストールするために記述します。)
(-yはインストール中にyesかnoかの質問をされても、全てyesとして進むために使用し、バックスラッシュはパッケージを見やすくするための改行のために使用しています。)
```
DockerfileをbuildしてDockerImageを一度作成したものはキャッシュされるため、追加で下に下にとRUNを記述していくことでbuildの時間を少なくすることができます。
※ただし、Layerは少ない方が望ましいため、最終的には、例のように&&や、\を用いた記述のように、RUNの記述をまとめて、RUNを少なくするようにします。


### CMD
コンテナの実行コマンドを指定するインストラクション。
Dockerfileの最後に記述します。

```Dockerfile
CMD OSに対応するコマンド

例)FROM ubuntu:latest
   RUN apt-get update && apt-get install -y \
       curl\
       nginx
   CMD ["/bin/bash"]
=> Dockerfileをbuildし、DockerImageを作成した後、docker runによりコンテナ作成・実行した際に、/bin/bashが実行されるようになります。
```

### ENTRYPOINT
CMDに近い役割を持つインストラクションです。

CMDはDockerImageを実行(docker run)する際に、コマンドを上書きできるものです。(例:docker run lsとすると上記CMD説明時の例ではbashではなく、lsが実行される。)

ENTRYPOINTを使うと、コマンドの上書きできなくなり、CMDはENTRYPOINTのオプションを記述する形となります。

```Dockerfile
ENTRYPOINT OSに対応するコマンド

例)FROM ubuntu:latest
   RUN apt-get update && apt-get install -y \
       curl\
       nginx
   ENTRYPOINT ["ls"]
   CMD ["--help"]
=> ENTRYPOINTにlsコマンドを記述することでdocker runの際にlsコマンド以外のコマンドが実行できなくなり、CMDはオプションの--helpが指定されています。
```

### COPY
Dockerfileの入っているディレクトリ(BuildContextと言います)の中にあるファイルをDockerImageにコピーするインストラクションです。

```Dockerfile
Copy BuildContext内のファイル名

例)FROM ubuntu:latest
   RUN mkdir /new_dir
   COPY test /new_dir
   CMD ["/bin/bash"]
=> Dockerfileをbuildした際、DockerImageに/new_dirというディレクトリを作成し、/new_dirにtestというファイルがコピーさせるLayerがutubtuのLayerに追加作成されます。
   このDockerImageからコンテナを作成した際には、コンテナ内に/new_dirというディレクトリとtestというファイルが作成されています。
```

### ADD
COPYのコマンドと似ていて、同じくコピーができるインストラクションです。

**ADDとCOPYとの違い**
ADDは圧縮ファイルをコピーした際、コピーと解凍の両方を行います。
COPYは単純なコピーのみです。
圧縮ファイルをコピー・解凍する時にはADD、圧縮ファイルが関係ない単純なコピーにはCOPYを使います。

```Dockerfile
Copy BuildContext内のファイル名

例)FROM ubuntu:latest
   ADD sample.tar /
   CMD ["/bin/bash"]
=> Dockerfileをbuildした際、DockerImageにsample.tarを/(ルート直下)にコピー・解凍するLayerを作成されます。
   コンテナを作成した際に、コンテナのルート直下にsample.tarが解凍されたものが作成されています。
```


### ENV
環境変数を設定するインストラクションです。

```Dockerfile
ENV 環境変数

例)FROM ubuntu:latest
   ENV key1 value
   CMD ["/bin/bash"]
=> コンテナ作成時にkey1=valueという環境変数が設定されるDockerImageが作成されます。
```

### WORKDIR
インストラクションの実行ディレクトリを変更するインストラクションです。

```Dockerfile
WORKIDIR ディレクトリ

例)FROM ubuntu:latest
   RUN mkdir sample_folder
   WORKDIR /sample_folder
   RUN touch sample_file
=> sample_folderというディレクトリを作り、sample_folder内でsample_fileを作成するLayerとなります。
　　(WORKDIRを使ったことで、コンテナ内に作成した/sample_folderの中でRUNの実行ができます。)
```


# 参考
Udemy
>かめれおん講師　「米国AI開発者がゼロから教えるDocker講座」
>>https://www.udemy.com/share/103aTRAEAdd1pTTHoC/

有料ですが、初学者の私にも非常に理解しやすかったです。

# 最後に
本投稿が初学者の復習の一助となればと幸いです。