Dockerfile のインストラクション

# はじめに
この記事では、Dockerfile の各インストラクションについて記載します。
（随時、追記していきます。）

# 前提
関連する用語を整理します。

## インストラクション
Dockerfile に記載する ```FROM [値]``` や ```RUN [値]``` などのことです。
Dockerfile には以下のインストラクションがあります。

https://docs.docker.com/reference/dockerfile/#overview

## Dockerfile
Docker イメージを作成するためのテキストファイル（Docker イメージの設計書）です。
Dcokerfile 内のインストラクション（設定）を読み込む（ビルドする）ことで Docker イメージが作成されます。

## イメージ
コンテナを作成するためのテンプレートファイルです。
イメージを実行することで Docker コンテナが作成されます。

イメージは、複数のレイヤ（層）によって構成されています。1つのレイヤにつきOSやミドルウェアが1つインストールされています。

## コンテナ
イメージに基づいてアプリケーションを実行する環境・インスタンスです。

# 主要なインストラクション
関連する用語が整理できたので、各インストラクションの役割について記載していきます。

## [```FROM```](https://docs.docker.com/reference/dockerfile/#from)
新たに作成するイメージのベースとなるイメージを指定します。
```FROM``` は Dockerfile の先頭に記載します。```FROM``` でベースイメージを指定した後、アプリケーションのインストールやファイルの追加などの変更を加えていきます。

```Dockerfile
# FROM [--platform=<platform>] <image> [AS <name>]
# FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
# FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM node:21-alpine3.18
```

※実用例

https://qiita.com/Yasushi-Mo/items/f23a9234daa1ac4f547d

## [```RUN```](https://docs.docker.com/reference/dockerfile/#run)
```FROM``` で記載したベースイメージに対し、実行するコマンドを指定します。
コマンドを実行すると、現在のイメージの上に新しいレイヤが作成されます。作成されたレイヤは、Dockerfile の次のインストラクションで利用されます。

```Dockerfile
# INSTRUCTION command param1 param2
RUN npm install --production
```

:::note
```RUN``` 及びこの後記載する ```CMD```、```ENTRYPOINT``` には以下2つの形式があります。

- 実行形式（exec form）：```INSTRUCTION ["executable","param1","param2"]```
- シェル形式（shell form）：```INSTRUCTION command param1 param2```

それぞれ Dockerfile 内の書式を Docker コンテナで実行する際の変換方法が異なります。

- [shell or exec forms](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)
- [DockerfileのCMDとENTRYPOINTを読み解く(1/3) — Shell形式とExec形式とは何か #docker #dockerfile](https://www.creationline.com/tech-blog/39662)

シェル形式のほうが一般的に使われているようです。
:::

※実用例

https://qiita.com/Yasushi-Mo/items/f23a9234daa1ac4f547d

## [```CMD```](https://docs.docker.com/reference/dockerfile/#cmd)
Docker イメージから Docker コンテナを起動するときに実行するコマンドとオプションを指定します。
そのため、```CMD``` は Dockerfile のなかで一度しか使えません。

```Dockerfile
# CMD ["executable","param1","param2"]
CMD ["/usr/local/bin/python3", "-m", "http.server", "8000"]
```

※実用例

https://qiita.com/Yasushi-Mo/items/0c6ed9be966f764ff7ca

## [```ENV```](https://docs.docker.com/reference/dockerfile/#env)
Dockerfile 内で環境変数を設定します。
イメージビルド時とコンテナ実行時に有効です。

```Dockerfile
# ENV <key>=<value> ...
ENV MYSQL_DATABASE=sample_app
```

※実用例

https://qiita.com/Yasushi-Mo/items/fe9edaaa1e368bd593a7

## [```COPY```](https://docs.docker.com/reference/dockerfile/#copy)
ホストマシンのファイルやディレクトリをコンテナのレイヤ（イメージ）にコピーします。
```<src>``` がコピー元、```<dest>``` がコピー先です。

```Dockerfile
# COPY [OPTIONS] <src> ... <dest>
# COPY [OPTIONS] ["<src>", ... "<dest>"]
COPY package*.json ./
```

※実用例

https://qiita.com/Yasushi-Mo/items/74d96f6f60b27a121bc0

## [`ADD`](https://docs.docker.com/reference/dockerfile/#add)
ホストマシンやインターネットのファイルをコンテナのレイヤ（イメージ）にコピーします。
`COPY` よりも多機能です。

```
# ADD [OPTIONS] <src> ... <dest>
# ADD [OPTIONS] ["<src>", ... "<dest>"]
ADD hom* /mydir/
```

## [```WORKDIR```](https://docs.docker.com/reference/dockerfile/#workdir)
`RUN` や `CMD`、`ENTRYPOINT`、`COPY`、`ADD` といったインストラクションを実行するディレクトリを設定します。
Dockerfile に ```WORKDIR``` が存在しない場合、ルートディレクトリ（`/`）に自動で作成されます。

```Dockerfile
# /path/to/workdir
WORKDIR /app
```

# [`EXPOSE`](https://docs.docker.com/reference/dockerfile/#expose)
コンテナのポートを設定します。

```Dockerfile
# EXPOSE <port> [<port>/<protocol>...]
EXPOSE 80/udp
```

# 参考
- [Dockerfile reference](https://docs.docker.com/reference/dockerfile/#dockerfile-reference)
- [Docker overview](https://docs.docker.com/get-started/overview/)
- [DockerfileのCMDとENTRYPOINTを読み解く(1/3) — Shell形式とExec形式とは何か #docker #dockerfile](https://www.creationline.com/tech-blog/39662)
- [【入門】Dockerイメージ（images）の仕組みとコマンド一覧まとめ](https://www.kagoya.jp/howto/cloud/container/dockerimage/)
- [【Docker】Dockerfileについてまとめました。](https://zenn.dev/genki86web/articles/0ee20f220188c4)