Dockerfileの話。
以下の4つの違いが分からなかったので調べた結果メモ。
DockerfileのRUNDockerfileのCMDDockerfileのENTRYPOINTrunコマンドとcreateコマンドに渡すCMD引数
違い
DockerfileのRUN- イメージを作成するときに実行されるコマンド(標準入出力を伴うコマンドは使えない)
DockerfileのENTRYPOINT- コンテナを実行したときに”必ず”実行されるコマンド
DockerfileのCMD- コンテナを実行したときに”デフォルトで”実行されるコマンド
ENTRYPOINTも指定されている場合は、ENTRYPOINTの引数として渡される
runコマンドとcreateコマンドに渡すCMD引数- コンテナを実行したときに”必ず”実行されるコマンド
DockerfileでCMDが指定されていた場合でも、こちらでCMDを指定した場合は、DockerfileのCMDは無視される。DockerfileのCMDと同じく、ENTRYPOINTも指定されている場合は、ENTRYPOINTの引数として渡される
DockerfileのRUNについては分かりやすいと思いますが
他3つは結構ややこしいと思うので例を出して説明します。
例えば、以下のようなDockerfileがあるとします。
FROM ubuntu:20.04 ENTRYPOINT ["/bin/top"]
これは、ubuntuをイメージを参考にして作った「起動した瞬間にtopコマンドを叩くだけのイメージ」です。
(topコマンドはLinuxの負荷を一定秒数ごとに測定するためのコマンドです)
実用性皆無ですが、説明をわかりやすくするためですので。。
このDockerfileから、以下のコマンドでhogeというイメージを作成します。
docker build -t hoge .
参考:docker buildコマンドとは?ビルドコンテキストとは
そしてhogeイメージから、以下のコマンドでfugaというコンテナを作成&立ち上げます。
docker run -it --name fuga hoge
これで立ち上がったコンテナを見てみると、
起動直後からtopコマンドが叩かれた状態からスタートするので、いきなりtopコマンドの結果が永遠と表示されます↓。

▲コンテナを立ち上げた直後からこの画面になる。
はい。ここまでがENTRYPOINTの説明です。
次に、さきほどのDockerfileに
FROM ubuntu:20.04 ENTRYPOINT ["/bin/top"] CMD ["-w","10"]
という指定を追加します。
そして、先ほどと同じようにイメージのbuild→イメージからコンテナのrunという手順を踏んで、コンテナを立ち上げます。
すると、今度は/bin/top -w 10というコマンドを実行したのと同じ意味になるので、以下のような表示になります。

▲topコマンドには-wオプションがあり、このオプションを指定すると表示する桁数を指定できます。この場合は10桁だけ表示されています。
つまり、
ENTRYPOINTとCMDを指定すると・・・
→ENTRYPOINTの引数としてCMDが渡される
ENTRYPOINTだけ指定すると・・・
→ENTRYPOINTがコマンドとして実行される
のような動きになるのが確認できます。
あとここでは確認していませんが
CMDだけ指定すると・・・
→CMD自体がコマンドとして実行される
という動きになります。
さて、次に同じく以下のDockerfileを用意して
FROM ubuntu:20.04 ENTRYPOINT ["/bin/top"] CMD ["-w","10"]
さきほどと同じようにイメージのbuildしてから
docker run -it --name fuga hoge -w 20
というコマンドを実行してコンテナを立ち上げます。
すると以下のような画面が表示されます。

つまりこれはDockerfileのCMD ["-w","10"]の行が無視され、
代わりにrunコマンドの引数として渡された-w 20がENTRYPOINTの引数として渡されることを表しています。
ちなみに一度終了したコンテナでも、
docker start -a fuga
のような感じで、-aを付けることでPID1のプロセスにアタッチすることができるので、これでコンテナを立ち上げるたびに/bin/topが実行されているのが確認できます。
もしくは
docker exec -it fuga bash
と実行すると「コンテナ内で新しくbashプロセスを立ち上げてそれに接続する」みたいなことができるので、接続後にps -aufと実行すればPID1で/bin/top -w 20と実行されているのが確認できます。

▲PID1にENTRYPOINTで指定したコマンドが実行されている。PID7はexecで新しく立ち上げたプロセス。そこから派生しているのがPID20。
あと余談ですが
docker-compose.ymlでは、COMMANDでコマンドを指定することができますが、これを指定してもDockerfileのCMDは上書きされます。
例えばdocker-compose.ymlからDockerfileを呼び出していた場合に、Dockerfileの方でCMD、docker-compose.ymlでCOMMANDをそれぞれ設定した場合、CMDのほうは無視されてCOMMANDが優先されるみたいです。
ややこしすぎるぜ😣
おわり
コメント