Docker初心者にとって使い分けがよくわからないCMDとENTRYPOINT。それもそのはずで、CMDとENTRYPOINTは、同じような使い方が出来てしまいます。

コピペで学ぶチュートリアル: DockerfileのCMDとENTRYPOINTの違い

こちらの記事を見ると「同じ使い方ができてしまう」の意味がわかりやすいでしょう。

混乱しがちな両者ですが、本記事では、本番環境や自分以外の人が使うDockerfileの中で、CMDとENTRYPOINTをどう書けば使いやすいDockerイメージができるか?についてまとめます。

最初に結論

結論から先のにべ、その後で背景と理由を説明します。

まずはCMDのみの形を検討

Docker official best practicesに従いCMDのみを指定する形でほとんどの場合はOKなはずです。

CMD should almost always be used in the form of CMD ["executable", "param1", "param2"…]

上記でうまくいかない用途は?

上記でうまくいかない用途が出てきたら、あなたのDockerイメージのユーザーがENTRYPOINTの仕様を熟知している場合のみ、同じくbest practicesに紹介されているENTRYPOINTとCMDを組み合わせるパターンが使えます。

CMD should rarely be used in the manner of CMD ["param", "param"] in conjunction with ENTRYPOINT, unless you and your expected users are already quite familiar with how ENTRYPOINT works.

Dockerfileのbest practicesに載っている例では、このように指定しています。

ENTRYPOINT ["s3cmd"]
CMD ["--help"]

こちらの指定方法は以下がわかりやすいです。Docker界隈で有名な前佛 雅人さんのブログです。

ENTRYPOINTは「必ず実行」、CMDは「(デフォルトの)引数」 ‣ Pocketstudio.Net

さて、ここから先は上記の使い分け方法の背景と理由を説明していきましょう。

なぜCMDとENTRYPOINTについて混乱してしまうのか?

CMDとENTRYPOINTについて混乱しやすい理由は、まず冒頭に述べたように「同じことが出来てしまう」ため、違いがわかりづらいということが挙げられます。

Dockerfileのリファレンスを見ても、CMDもENTRYPOINTも非常に記載が長くて理解するのが大変です。一生懸命読んでもサッパリなんのことかわからなくても不思議はないですし、特に初心者にとってそうでしょう。