最終更新
リンドくん
たなべ先生、DockerfileでENTRYPOINTとCMDっていう2つの命令があるんですけど、これって何が違うんですか?どっちを使えばいいのか迷ってしまって...
たなべ
確かに最初は混乱しやすいポイントなんだ。
実はENTRYPOINTとCMDはどちらもコンテナ起動時に実行されるコマンドを指定するものなんだけど、使い方と役割が少し違うんだよ。今日はその違いをしっかり理解していこう!
Dockerを使ってアプリケーションをコンテナ化する際、Dockerfileの中で必ず目にするのがENTRYPOINT
とCMD
という命令です。
どちらもコンテナが起動したときに実行されるコマンドを指定するものですが、その挙動と使い分けには明確な違いがあります。
この記事では、Docker初心者の方でも理解できるよう、ENTRYPOINTとCMDの基本的な概念から実践的な使い分けをステップバイステップで解説していきます。
HackATAは、エンジニアを目指す方のためのプログラミング学習コーチングサービスです。 経験豊富な現役エンジニアがあなたの学習をサポートします。
✓ 質問し放題
✓ β版公開中(2025年内の特別割引)
リンドくん
そもそも、なぜ2つも似たような命令があるんですか?1つでいいような気がするんですが...
たなべ
それはね、Dockerが柔軟性と確実性の両方を実現するためなんだ。
ENTRYPOINTは「絶対に実行したいコマンド」、CMDは「デフォルトの引数や動作」というイメージで考えるとわかりやすいよ。
ENTRYPOINTは、コンテナが実行するメインのコマンドを固定するための命令です。
一度ENTRYPOINTで指定したコマンドは、コンテナ起動時に上書きすることが基本的にはできません(--entrypoint
オプションを使えば上書きできますが、通常は推奨されません)。
ENTRYPOINTの主な特徴は以下の通りです。
CMDは、コンテナ起動時のデフォルトの動作や引数を定義するための命令です。
CMDで指定した内容は、docker runコマンドで別のコマンドを指定すると簡単に上書きされます。
CMDの主な特徴は以下の通りです。
DockerがENTRYPOINTとCMDの両方を用意している理由は、確実性と柔軟性のバランスを取るためです。
この2つを組み合わせることで、開発者はコンテナの動作を柔軟にコントロールしながらも、コンテナの目的を明確に保つことができるのです。
リンドくん
ENTRYPOINTの具体的な使い方を教えてください!
たなべ
わかった!実際のコード例を見ながら説明していこう。
ENTRYPOINTにはexec形式とshell形式の2つの書き方があるんだ。
ENTRYPOINTには、記述方法が2種類あります。
exec形式はJSON配列の形式で記述します。これが推奨される書き方です。
具体例:
この場合、コンテナは必ずpython app.py
というコマンドを実行します。
shell形式はシェルを介して実行されます。
具体例:
exec形式が推奨される理由は、以下のような重要なポイントがあります。
実際のプロジェクトでは、よほどの理由がない限りexec形式を使用することをおすすめします。
Webサーバーを起動するコンテナの例を見てみましょう。
このDockerfileでビルドしたコンテナは、常にnginxサーバーとして動作します。
docker runコマンドで別のコマンドを指定しようとしても、nginxが実行されます(--entrypoint
を使わない限り)。
リンドくん
じゃあCMDはどう使うんですか?ENTRYPOINTと組み合わせる場合もあるって聞きましたけど...
たなべ
そうなんだ!CMDも2つの形式があって、さらにENTRYPOINTと組み合わせることでより柔軟な設定ができるようになるんだよ。
CMDには実は3つの記述方法があります。
具体例:
具体例:
この形式は、ENTRYPOINTと組み合わせて使用します。
具体例:
この場合、デフォルトではpython app.py --host 0.0.0.0 --port 8000
が実行されますが、docker runコマンドで引数を指定すれば、CMDの部分だけが上書きされます。
CMDの最大の特徴は、簡単に上書きできることです。
このDockerfileからビルドしたイメージを使用する場合は以下のような挙動になります。
データベースコンテナの設定例を見てみましょう。
この設定により、通常はPostgreSQLサーバーとして起動しますが、必要に応じて以下のように動作を変更できます。
このように、CMDを使うことで同じイメージから異なる用途のコンテナを簡単に作成できます。
リンドくん
2つを組み合わせるとどんないいことがあるんですか?
たなべ
これがDockerの真骨頂なんだ!
確実性と柔軟性を両立できるようになるんだよ。実際のプロジェクトでよく使われるパターンを紹介するね。
ENTRYPOINTとCMDを組み合わせると、以下のような動作になります。
実行時には、実行ファイル デフォルトパラメータ
というコマンドが実行されます。
そして、docker runでパラメータを指定すると、CMDの部分だけが置き換わります。
本番環境とデバッグ環境で動作を切り替えられるDockerfileの例です。
使い方は以下の通りです。
AWSのCLIツールのようなコマンドラインツールをコンテナ化する例です。
使い方は以下の通りです。
データ処理スクリプトで、処理モードを柔軟に切り替えられる例です。
使い方は以下の通りです。
1つのイメージから複数の役割のコンテナを起動できる例です。
↓entrypoint.py
の内容例↓
使い方は以下の通りです。
このパターンは、マイクロサービスアーキテクチャで同じコードベースから異なる役割のコンテナを起動する際に非常に便利です。
リンドくん
実際のプロジェクトでは、どういう基準で使い分ければいいんでしょうか?
たなべ
いい質問だね!チーム開発や本番運用を考えると、いくつか重要なガイドラインがあるんだ。
これを守ることで、保守しやすいDockerfileが作れるよ。
ENTRYPOINTとCMDを使い分ける際の基本的な考え方は以下の通りです。
ENTRYPOINTを使うべきケース
CMDを使うべきケース
組み合わせを使うべきケース
チーム開発で混乱を避けるための推奨ルールです。
複数記述すると、最後の1つだけが有効になります。意図しない動作を避けるため、明示的に1つずつ記述しましょう。
本番環境で使用する際の重要なポイントです。
exec形式を使用し、アプリケーションがPID 1として動作するようにします。
Dockerfileではシンプルなデフォルト値を設定し、環境ごとの設定はdocker-compose.ymlで行います。
Dockerfile:
docker-compose.prod.yml(本番環境):
この方法により、Dockerfileはシンプルに保ちつつ、環境ごとの設定を柔軟に管理できます。
リンドくん
ENTRYPOINTとCMDの違い、やっと理解できました!組み合わせて使うと本当に便利ですね。
たなべ
そう思ってもらえて嬉しいよ!
最初は混乱するかもしれないけど、実際に手を動かして試してみることが一番の理解への近道だからね。ぜひ自分のプロジェクトで実践してみてほしいな。
この記事では、DockerのENTRYPOINTとCMDの違いと使い分けについて詳しく解説してきました。
重要なポイントをおさらいしましょう。
ENTRYPOINTとCMDの違いを理解することは、Dockerを使いこなす上での重要なステップです。
特に、これら2つを適切に組み合わせることで、開発から本番環境まで一貫した動作を保ちながら、必要な柔軟性も確保できます。
最初は戸惑うかもしれませんが、実際に様々なパターンを試してみることで、徐々に「このケースではこう書くべき」という感覚が身についてきます。
ぜひ今回紹介したサンプルコードを参考に、自分のプロジェクトでDockerfileを書いてみてください。