こんにちは。Яeiです。
今回は、現役エンジニアの私がDockerfileのENTRYPOINTとCMDの書き方について記事にしようと思います。
最初の頃はこの二つの命令についての使い分けが分からない場合も多いと思いますので丁寧に解説していきたいと思います。
当記事は以下の公式リファレンスを元に記載しております。
Dockerfile reference >>
目次
結論:ENTRYPOINTとCMDの書き方
ENTRYPOINTはコンテナ起動時に実行したいコマンドを記載する命令で、書き方は以下となります。
ENTRYPOINT [“executable”, “param1”, “param2”] (推奨形式)
or
ENTRYPOINT command param1 param2
CMDはENTRYPOINTのデフォルト引数を設定する命令で、書き方は以下となります。
CMD [“executable”,”param1″,”param2″] (推奨形式)
or
CMD [“param1″,”param2”]
or
CMD command param1 param2
ENTRYPOINTとCMDは以下のように組み合わせて使ってあげて下さい。
ENTRYPOINT [“executable”, “param1”, “param2”] (推奨形式)
CMD [“param3”, “param4”]
詳細:ENTRYPOINT、CMDの使い方
ENTRYPOINT の使い方
ENTRYPOINT [“executable”, “param1”, “param2”] (推奨形式)
ENTRYPOINT命令ではコンテナ起動時に実行したいコマンドを記載します。
例えば以下のようなDockerfileを作成したとしましょう。
FROM almalinux:latest
ENTRYPOINT ["echo", "i am papakoletter!"]
これをイメージビルドして実行してみるとどうなるでしょうか?
> docker image build . -t test
> docker container run --rm -it test:latest
i am papakoletter!
「i am papakoletter!」が出力されました。
これは、コンテナを起動すると「echo “i am papakoletter!”」がコンテナ上で実行されたことを意味します。
なるほど、つまりコンテナ起動時に実行したいコマンドをここに記載すれば良さそうです。
CMD の使い方
CMD [“executable”,”param1″,”param2″] (推奨形式)
CMD命令ではコンテナ起動時に実行されるコマンドに引数を渡してあげることができます。
さて、これが大変ややこしいのですが、例えば以下のようなDockerfileを作成したとしましょう。
FROM almalinux:latest
CMD ["echo", "i am papakoletter!"]
先ほどのENTRYPOINTをCMDに置き換えただけですね。これをイメージビルドして実行してみるとどうなるでしょうか?
> docker image build . -t test
> docker container run --rm -it test:latest
i am papakoletter!
なんと先ほどと同じく「i am papakoletter!」が出力されました。
そして多くの人が疑問に思うのが、あれぇ、ENTRYPOINTとCMDどっちを使えば良いんだ?
ENTRYPOINTとCMDの使い方
ENTRYPOINTにはコマンドを、CMDにはENTRYPOINTに渡す引数を設定する
と覚えておきましょう。
例えば以下のようなDockerfileを作ったとしましょう。
FROM almalinux:latest
ENTRYPOINT ["echo", "i am"]
CMD ["papakoletter!"]
これの実行結果は以下のようになります。
> docker container run --rm -it test:latest
i am papakoletter!
さて、ここで、イメージを再ビルドしないで「i am test!」に変更したくなったとします。その場合、起動時にコマンド指定してあげることで簡単に挙動を変更することができます。
> docker container run --rm -it test:latest "test!"
i am test!
このように、以下のような使い分けでENTRYPOINT、CMDを利用するのです。
・ENTRYPOINTにはコンテナ起動時に動いてほしいコマンド+必ず指定したい引数
・CMDにはデフォルト引数を指定
コンテナイメージを利用する立場に立って、Dockerfileを作成するのが良いでしょう。
なお、これを言っては元も子もないのですが、CMDしか設定していないオフィシャルイメージも多々あります。
CMDはコンテナ起動時に引数設定するだけで簡単に上書きできるのに対して、ENTRYPOINTは「–entrypoint」で上書きしてあげる必要があり面倒というのもあります。
また、オフィシャルイメージの場合、そのオフィシャルイメージをベースイメージにさらに別のイメージを作成されることを想定しているものも多いです。
そのため、変にENTRYPOINTを設定せずに、最低限のCMD程度(/bin/shとか/bin/bashとか)程度を設定していることも多いです。
なぜならば、よくありがちなのはオフィシャルイメージをプルしてコンテナ起動する際に以下のようにするケースです。
> docker container run --rm -it alpine:latest
しかし、もしもオフィシャルイメージにENTRYPOINTが設定されていた場合(例えば先ほどの例でecho)、
> docker container run --rm -it test:latest /bin/bash
i am /bin/bash
となってしまい、コンテナにログインできません。これを解消するには以下のようにENTRYPOINTを上書いてあげる必要があります。
> docker container run --rm --entrypoint "/bin/sh" -it test:latest
もちろん、オフィシャルイメージの中にはこのようにENTRYPOINT指定されているものもありますので、ログインできない場合は思い出してみて下さい。
なお、docker inspectコマンドなどでもENTRYPOINTやCMDを確認することができますので参考程度に見てみると良いかもしれません。
当記事は以上となります。
ENTRYPOINT、CMD命令について、今までCMD命令のみ覚えていた方もいるかもしれません。
しかし、実際には使い分けがあるので是非、活用してみて下さい。
長々とお疲れさまでした。