ShellフォームとExecフォームの違いとENTRYPOINTとCMDの使い分けについて

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/aff949f8-9682-a525-fd85-2904d541fd88.png)
ShellフォームとExecフォームの違いとENTRYPOINTとCMDの使い分けについて

本記事は、以下のクリエーションライン様の記事を参考にさせていただいております。

[DockerfileのCMDとENTRYPOINTを読み解く\(3/3\) \- CMD/ENTRYPOINT/Shell/Exec一覧表 \#docker \#dockerfile \- クリエーションライン株式会社](https://www.creationline.com/tech-blog/39730)

# 0. はじめに

社内で「ShellフォームとExecフォームの違いとENTRYPOINTとCMDの使い分けがよくわからん」という話が合ったのでまとめてみた、という話になります。

# 1. ENTRYPOINTとCMDは何が違うの？

ENTRYPOINTとCMDはdocker runしたときのデフォルトで実行されるコマンドですが、CMDはdocker run時の引数でオプションとして指定できます。

例: s3cmdを実行したいDockerイメージ

```
#Dockerfile
ENTRYPOINT ["s3cmd"]
CMD ["--help"]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/6e785188-e0f5-41d6-ffab-c0e8fd9731de.png)

docker runで引数を渡して実行すると、CMDの指定が上書きされて実行できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/724f0e76-6120-af67-d4ba-e3d969660042.png)


つまり、
```
s3cmd ls s3://mybucket
```
が実行される

::: note
CMDには基本的にデフォルトのオプションを記載する
:::

# 2. Shell formとExec formについて

簡単に言うと
  「Dockerコンテナ内でアプリケーションを呼び出す(起動する)ときの書式」です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/68fe1fd2-4b6e-52dd-aba1-7e7a3257b862.png)

## 2-2. Shell formとExec formの中身の違い

Shell formは、以下のようなDockerfile内の書式を右のように変換してDockerコンテナ内で実行します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/7fb938fe-19e2-a198-d3b4-032d415048b9.png)

Exec formは、以下のようなDockerfile内の書式を右のように変換してDockerコンテナ内で実行します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/0a7ecad6-66dd-9b0c-bfc4-82921b9a287d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/ab2b434d-bb67-4343-f5eb-e1e9971597ee.png)

::: note
- Shell formはsh経由で実行されるので/bin/shが必須
- /bin/sh経由で実行されるので変数展開が可能
- しかし、/bin/sh の変数展開を悪用される可能性もある
- 基本的に攻撃面を減らすためにExec formを使うべき
- しかし、Exec fromは変数展開できないのでENTRYPOINTとCMDを組み合わせる
:::

DockerfileのCMDとENTRYPOINTを読み解く(1/3) - Shell形式とExec形式とは何か  - クリエーションライン株式会社
https://www.creationline.com/lab/39662

# 3. ENTRYPOINTとCMDの使い分け

どちらもコマンドを実行できるという点では同じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/c1172ad0-7daa-d163-3f02-afd2f282a831.png)

ではどちらを使ってもいいのでは？？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/ef492579-231a-1b8c-f3f1-8bd777e1db3c.png)

## 3-1. docker run run-param1を実行してみる

以下のENTRYPOINTでdocker run _run-param1_ すると下のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/b7dcf28b-a356-d61d-9d20-9eaf87ffc003.png)

以下のCMDでdocker run _run-param1_ すると下のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/8d657691-ec48-fd54-03dd-e86844cc9959.png)

::: note warn
ENTRYPOINTはdocker run <オプション> で上書きされない
CMDはdocker run <オプション> で上書きされる
:::

DockerfileのCMDとENTRYPOINTを読み解く(2/3) - CMD命令とENTRYPOINT命令の基礎 - クリエーションライン株式会社
https://www.creationline.com/lab/39705

# 4. 結局なにが正解？

できるだけ Exec formを使う

::: note
/bin/shを使わないことによる攻撃面の削減
変数展開によるインジェクション発生の削減
:::

# 5. ENTRYPOINTとCMDを組み合わせる

Exec formを使ったときにパラメーターを外部から渡すことができる

以下のENTRYPOINTとCMDでdocker runすると右のようになります(Exec form)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/72c1ec16-9650-6f90-c695-e1dfa722c7ca.png)

以下のCMDでdocker run run-param1すると右のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/12e26bf0-c17c-5603-edac-5ab0420651fb.png)

# 6. まとめ

ShellフォームとExecフォームの違いとENTRYPOINTとCMDの使い分けについて解説してみました。

# 7. 参照

DockerfileのCMDとENTRYPOINTを読み解く(1/3) - Shell形式とExec形式とは何か #docker #dockerfile - クリエーションライン株式会社
https://www.creationline.com/tech-blog/39662

DockerfileのCMDとENTRYPOINTを読み解く(2/3) - CMD命令とENTRYPOINT命令の基礎 #docker #dockerfile - クリエーションライン株式会社
https://www.creationline.com/tech-blog/39705

DockerfileのCMDとENTRYPOINTを読み解く(3/3) - CMD/ENTRYPOINT/Shell/Exec一覧表 #docker #dockerfile - クリエーションライン株式会社
https://www.creationline.com/tech-blog/39730