Dockerにおけるイメージとは

## はじめに
こちらはDockerのイメージについてまとめた記事になります。情報が陳腐化している箇所があるかもですが、ご了承いただければ幸いです。:bow:

以下は、私がDocker関連についてまとめている記事になります。もし興味がありましたらご覧になってください。

* [Dockerにおけるコンテナ](https://qiita.com/Hirohana/items/c881118021fd156ccefe "Dockerにおけるコンテナ") 
* [Dockerにおけるイメージとは](https://qiita.com/Hirohana/items/a7b11c72e525c48d34bf "Dockerにおけるイメージとは") 
* [Dockerにおけるネットワーク](https://qiita.com/Hirohana/items/3fff1a1d11a0f1505dad "Dockerにおけるネットワーク") 
* [Dockerにおけるデータ管理](https://qiita.com/Hirohana/items/59a22d549fcfb096f0b9 "Dockerにおけるデータ管理")

## Dockerイメージとは
:::note info
Dockerコンテナを作成するための元となるテンプレートです。イメージには、コンテナの実行に必要なすべてのファイルシステムや依存関係、設定情報などが含まれています。
:::


![スクリーンショット (249).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1220815/2f3612ca-0637-d730-0e01-a334f58508e7.png)

* コンテナ実行に必要なファイルをまとめたファイルシステムです。
* AUFSなどの特殊なファイルシステムが使用されています。
* イメージ上のデータはレイヤーで構成され読み取り専用です。
* Dockerイメージにnginxをインストールするコマンドを実行すればそれが1つの階層として作られ、設定ファイルをイメージ内にコピーすればさらに階層が作られます。
* コンテナレイヤー上にファイルの追加や削除、パッケージ追加を行いそれをイメージとして保存する事も可能です。

Dockerコンテナはなるべく軽量に、サイズを抑えることが重要なので、無駄なイメージがファイルに含まれないようにイメージを作成することが重要です。

### ローカル上のDockerイメージ確認
```terminal: terminal
$ docker images
```

### Dockerイメージにタグ付けして、バージョン管理するコマンド
```terminal: terminal
$ docker tag docker/whalesay my_whalesay:ver1

REPOSITORY        TAG       IMAGE ID       CREATED       SIZE
my_whalesay       ver1      6b362a9f73eb   8 years ago   247MB
```

### Dockerイメージの詳細情報を表示
```terminal: terminal
$ docker inspect my_whalesay:ver1
```

### ローカルのDockerイメージを削除するコマンド
```terminal: terminal
$ docker rmi docker/whalesay

// 強制削除 -fをつける
$ docker rmi -f docker/whalesay
```

### イメージを取得(pull)するコマンド
イメージの後ろにバージョンを指定しなければデフォルトで`@latest`のイメージを取得する。
```terminal: terminal
$ docker pull docker/whalesay
```

## Dockerfileのイメージビルド
Dockerfileからイメージを作成することを`イメージビルド`と呼びます。

```Dockerfile: Dockerfile
FROM docker/whalesay:latest

COPY default.conf /etc/nginx/conf.d/default.conf

RUN apt-get -y update && apt-get install -y fortunes

CMD /usr/games/fortune | cowsay
```

* `FROM`指令は、ベースとなるイメージを指定します。Docker イメージは、別のイメージをベースに構築されることが多いです。FROM 指令は、Dockerfile の最初の行で指定される必要があります。

* `COPY`指示は、ビルドコンテキスト内のファイルやディレクトリをイメージ内の指定したパスにコピーします。

* `RUN`指令は、コマンドを実行してイメージ内で操作を行います。Dockerイメージを構築する際に、パッケージのインストール、ファイルの作成、環境変数の設定など、さまざまな操作を実行するために使用されます。RUN指令は、Dockerfile 内で複数回使用することができます。

* `CMD`指令は、コンテナが実行されるときに実行されるデフォルトのコマンドまたは引数を指定します。CMD 指令は、Dockerfile 内で一度だけ使用することができます。また、CMD 指令は、コマンドを配列形式で指定するか、文字列形式で指定することができます。

次にDockerfileをビルドするコマンドについて解説します。

```terminal: terminal
$ docker build -t docker-whale .
```
* `-t`オプションは、ビルドするイメージにタグを付けるためのオプションです。docker-whale はイメージに付けられるタグの名前です。タグはイメージを特定するために使用されます。

* `.`は Dockerfile が存在するディレクトリを表します。この場合、カレントディレクトリにある Dockerfile を使用してイメージをビルドします。`.`を使用することで、現在のディレクトリにある Dockerfile をビルドコンテキストに含めることができます。

<details><summary>ビルドコンテキストとは</summary>

ビルドコンテキスト（Build Context）は、Docker イメージのビルドプロセスで使用される作業ディレクトリやファイルの集合です。ビルドコンテキストは、docker build コマンドを実行する際に指定されるディレクトリまたはパスです。

Docker イメージのビルドでは、ビルドコンテキスト内のファイルとディレクトリが使用されます。Docker エンジンは、ビルドコンテキスト内のすべてのファイルを圧縮し、Docker デーモンに送信します。このため、ビルドコンテキストが大きい場合や不必要なファイルが含まれる場合、ビルドプロセスが遅くなる可能性があります。

ビルドコンテキストには通常、Dockerfile とその依存ファイル、必要なアプリケーションコード、設定ファイルなどが含まれます。Dockerfile はビルドコンテキスト内に存在する必要があります。docker build コマンドを実行する際には、ビルドコンテキストがカレントディレクトリである場合、. を使用して明示的に指定することが一般的です。

ビルドコンテキスト内のファイルとディレクトリは、Dockerfile 内で COPY や ADD の指令を使用してイメージ内にコピーされます。ビルドコンテキスト内のファイルの変更がある場合、Docker はキャッシュの利用やビルドの最適化においてその変更を検知し、ビルドプロセスの効率性を向上させることができます。

ただし、ビルドコンテキストには注意が必要です。不要なファイルやディレクトリを含めると、ビルドプロセスや最終的なイメージのサイズが不必要に大きくなる可能性があります。適切なファイルの選択と組織、不要なファイルの .dockerignore ファイルへの追加など、ビルドコンテキストの最適化が重要です。
</details>

また、イメージをビルドする際にキャッシュを無効にするには`--no-cache`オプションを記述します。

```terminal: terminal
$ docker build --no-cache -t docker-whale .
```

## コンテナからイメージを作成するdocker commit
`docker commit`コマンドは、コンテナからイメージを作成することです。

注意点としてはdocker commitコマンドで何かしら操作が行われたコンテナからimageファイルを作成した場合は、コンテナ内で行われた作業はどこにも明確な記録が残りません。
そのため扱いにくいimageファイルになってしまう可能性があるので、通常はDockerfileで変更を加えたほうが無難です。

```terminal: terminal
$ docker commit <コンテナ名 または コンテナID> <イメージ名>:<タグ名>
```

## 終わりに
最後まで記事をご覧いただきありがとうございました。

間違い等ありましたらご指摘いただけると幸いです:bow:

## 参考

https://docs.docker.jp/