「CMD」と「RUN」「ENTRYPOINT」と「runとcreateの引数」【Dockerfile】

Dockerfileの話。

以下の4つの違いが分からなかったので調べた結果メモ。

  • DockerfileRUN
  • DockerfileCMD
  • DockerfileENTRYPOINT
  • runコマンドとcreateコマンドに渡すCMD引数

違い

  • DockerfileRUN
    • イメージを作成するときに実行されるコマンド(標準入出力を伴うコマンドは使えない)
  • DockerfileENTRYPOINT
    • コンテナを実行したときに”必ず”実行されるコマンド
  • DockerfileCMD
    • コンテナを実行したときに”デフォルトで”実行されるコマンド
    • ENTRYPOINTも指定されている場合は、ENTRYPOINTの引数として渡される
  • runコマンドとcreateコマンドに渡すCMD引数
    • コンテナを実行したときに”必ず”実行されるコマンド
    • DockerfileCMDが指定されていた場合でも、こちらでCMDを指定した場合は、DockerfileCMDは無視される。
    • DockerfileCMDと同じく、ENTRYPOINTも指定されている場合は、ENTRYPOINTの引数として渡される

 

DockerfileRUNについては分かりやすいと思いますが

他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

参考【図解】dockerの主要コマンドまとめ

 

これで立ち上がったコンテナを見てみると、

起動直後からtopコマンドが叩かれた状態からスタートするので、いきなりtopコマンドの結果が永遠と表示されます↓。

▲コンテナを立ち上げた直後からこの画面になる。

 

はい。ここまでがENTRYPOINTの説明です。

次に、さきほどのDockerfile

FROM ubuntu:20.04
ENTRYPOINT ["/bin/top"]
CMD ["-w","10"]

という指定を追加します。

そして、先ほどと同じようにイメージのbuild→イメージからコンテナのrunという手順を踏んで、コンテナを立ち上げます。

すると、今度は/bin/top -w 10というコマンドを実行したのと同じ意味になるので、以下のような表示になります。

▲topコマンドには-wオプションがあり、このオプションを指定すると表示する桁数を指定できます。この場合は10桁だけ表示されています。

つまり、

  • ENTRYPOINTCMDを指定すると・・・
    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

というコマンドを実行してコンテナを立ち上げます。

すると以下のような画面が表示されます。

 

つまりこれはDockerfileCMD ["-w","10"]の行が無視され、

代わりにrunコマンドの引数として渡された-w 20ENTRYPOINTの引数として渡されることを表しています。

 

ちなみに一度終了したコンテナでも、

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の方でCMDdocker-compose.ymlCOMMANDをそれぞれ設定した場合、CMDのほうは無視されてCOMMANDが優先されるみたいです。

 

ややこしすぎるぜ😣

 

おわり

仮想環境
スポンサーリンク
この記事を書いた人
penpen

1991生まれ。WEBエンジニア。

技術スタック:TypeScript/Next.js/Express/Docker/AWS

フォローする
フォローする

コメント

タイトルとURLをコピーしました