Dockerfileの話。
以下の4つの違いが分からなかったので調べた結果メモ。
Dockerfile
のRUN
Dockerfile
のCMD
Dockerfile
のENTRYPOINT
run
コマンドと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
というコマンドを実行したのと同じ意味になるので、以下のような表示になります。
つまり、
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
と実行されているのが確認できます。
あと余談ですが
docker-compose.yml
では、COMMAND
でコマンドを指定することができますが、これを指定してもDockerfileのCMD
は上書きされます。
例えばdocker-compose.yml
からDockerfile
を呼び出していた場合に、Dockerfile
の方でCMD
、docker-compose.yml
でCOMMAND
をそれぞれ設定した場合、CMD
のほうは無視されてCOMMAND
が優先されるみたいです。
ややこしすぎるぜ😣
おわり
コメント