【Docker】コンテナの勉強会まとめ #2 -Dockerの基礎からコンテナのデプロイまで-

# 前回の記事
[コンテナの勉強会まとめ #1 -環境構築編-（For Windows Users）](https://qiita.com/NAMICHAN/items/1850dd9349483416ba0f)

# 本記事でのゴール：コンテナをデプロイする
[「Docker/Kubernetes 実践コンテナ入門」](https://books.rakuten.co.jp/rk/c05bd1c12393388497e5ff8becba689b/?variantId=c05bd1c12393388497e5ff8becba689b)という本をベースに、Dockerコンテナのデプロイをするまでの一連の流れを紹介する。
対応ページ：p.8~9

# コンテナ実行の手順
Dockerコンテナを実行するときは、以下の手順を踏む必要がある。
1. Dockerfileを作成する。
2. Dockerfileをビルドし、Dockerイメージを作る。
3. Dockerイメージを実行（run）する。

![10d6fdec2174-20230716.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/e9d1f302-3772-0030-65b9-896da7fa7890.png)

上記の手順を以下の章より実施する。
**※コンテナを実行するにあたって、「今このコマンドはどの階層で実行されているのか？」という部分が不明瞭になったため、各工程でコマンドの実行階層をイメージできるように画像にして貼り付けているので、私のように混乱した方はぜひ見ていただきたい。**

# 実際にやってみる
## 事前準備
コンテナをrunした後実際に実行されるアプリケーションとして、以下の「helloworld」というファイル名を付けたシェルスクリプトを用意する。
```
#!/bin/sh

echo "Hello, world!"
```
<details><summary>ファイルが作成される階層</summary>

![74a0e8e2e13e-20230717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/c827604c-3e4c-a991-c89c-9a3a17d8d8bc.png)

</details>

## Dockerfileを作成する
Dockerfileを作成する。
```
FROM ubuntu:16.04

COPY helloworld /usr/local/bin
RUN chmod +x /usr/local/bin/helloworld

CMD ["helloworld"]
```
:::note warn
この時、ファイル名を「DockerFile」「DOCKERFILE」といったものを付けると、ビルド時に以下のようなエラーが出る。「Dockerfile」「dockerfile」だと、ビルドが成功した。
:::
```
failed to solve with frontend dockerfile.v0: failed to read dockerfile: open /var/lib/docker/tmp/buildkit-mount3246733569/Dockerfile: no such file or directory
```

<details><summary>Dockerfileを作成する階層</summary>

![5de5bc9705a8-20230717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/f9f20682-88a0-87a1-0325-c8453eda3be3.png)

</details>

## Dockerfileをビルドし、Dockerイメージを作る
以下のコマンドを実行する。
```
docker image build -t helloworld:latest .
```

<details><summary>補足</summary>

### -tオプションについて
docker image buildを行う時は、必ず何かしらのオプションをつける必要がある。
-tオプションの役割は以下。Dockerイメージに、**名前とタグ**（イメージのバージョン）をつけている。
```
-t [イメージに付与する名前]:[タグ名] Dockerfile配置ディレクトリのパス
```
ちなみに以下のように [イメージに付与する名前] のみを指定すると、 [タグ名] は自動的にlatest（最新のバージョン）が使用されるようになっている。
```
docker image build -t helloworld .
```
他にもdocker image build --helpコマンドを打つと、以下のように使用できるオプションの一覧が表示される。
```
docker image build --help

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
      --network string          Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                Do not use cache when building the image
  -o, --output stringArray      Output destination (format: type=local,dest=path)
      --platform string         Set platform if server is multi-platform capable
      --progress string         Set type of progress output (auto, plain, tty). Use plain to show container
                                output (default "auto")
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --secret stringArray      Secret file to expose to the build (only if BuildKit enabled):
                                id=mysecret,src=/local/secret
      --ssh stringArray         SSH agent socket or keys to expose to the build (only if BuildKit enabled)
                                (format: default|<id>[=<socket>|<key>[,<key>]])
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
      --target string           Set the target build stage to build.
```

### コマンドの最後の「 .」について
Dockerfileの場所（ディレクトリ）を相対パスで指定している。
今回の場合、Dockerfileはdocker image buildをするディレクトリと同じ場所にあるため、ピリオドは「この場所」を指定する1つのみ。

</details>

ビルド後、docker image lsコマンドを実行し、イメージビルドが済んでいることを確認する。
```
docker image ls 

REPOSITORY                TAG          IMAGE ID       CREATED             SIZE
helloworld                latest       87b496c40905   About an hour ago   135MB
```

<details><summary>コマンドの実行階層</summary>

![0532ce8dc157-20230717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/595de91c-0762-c694-f146-3160d9a2f6a7.png)

**※補足**
- docker image buildを実行しているのはWSL上のLinuxOS
- コマンドの指示を受け取るのは常駐プロセスであるDocker
- その結果が返ってくるのはWSL上のLinuxOS

</details>

## Dockerイメージを実行（run）する
以下のコマンドを実行し、作成したアプリケーション（シェルスクリプト）が実行されることを確認する。
※ここで「Hello, world!」と表示されるのは、以下のような手順を踏んでいるため。
1. DockerfileのCMDが実行される。
2. ファイル名としての「helloworld」ファイルが実行される。
3. 最終的にそのファイルの中にある「echo "Hello, world!"」が実行された。
```
docker container run helloworld:latest
Hello, world!
```

<details><summary>コマンドの実行階層</summary>

![8d081bbe1175-20230717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/785f9667-b5f2-8378-d1aa-9d5299b29566.png)

</details>

そして実行されたコンテナを図にすると以下のようになる。
コンテナは、docker container runをして**初めて**生まれるものなので、ここに来てやっと登場する。

![d321ced40e9c-20230728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804761/30677dac-1782-2e01-93f2-5ec15ddf208b.png)


# 所感
頭で想像するより、図に書いて「今はどの階層で作業をしているのか」を明確にすると理解が早くなった。また「Dockerfileを作成する」セクションで記載した警告のように、たった一文字違うだけでエラーが起きるので、どんな風にコマンドを打つとエラーが出るのかを探るのも勉強になるし、楽しさも感じるので引き続き行っていこうと思う。