「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生まれ。
2019年くらいからフロントエンドエンジニアを目指している元アフィリエイターです💩

職を探しています😭
よろしくお願いします🙇

penpenをフォローする
penpenをフォローする
penpenメモ

コメント

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