h
現在、本業でPythonをdockerで動かしています。
その中で、コンテナ起動時にpythonを実行する仕様にしている中でCMD
とENTRYPOINT
の違いについて調べたのでまとめました。
基本概念
docker run
でコンテナを起動するときに使用します。
指令 | 役割 | 上書き方法 |
---|---|---|
CMD | デフォルトの引数定義 |
docker run の引数で直接変更 |
ENTRYPOINT | コンテナのメインプロセス定義 |
--entrypoint フラグが必要 |
1つのDockerfile内でCMD
,ENTRYPOINT
をそれぞれ一度しか使用できないことに注意してください。
※複数記載した場合、最後に定義したものが実行されます。
CMD
とENTRYPOINT
は何が違うか
結論、CMDは柔軟な設定が可能で、ENTRYPOINTは必ず実行させたいコマンドが設定可能です。
故に、それぞれ単体で使用するケースと、二つを柔軟に組み合わせて使用するケースがあります。
以下にチートシートを作成したので、参考にしてみてください。
各コマンドの使い分け
ケース | 推奨 | 理由 |
---|---|---|
デフォルトの引数だけ指定したい(簡単に上書きさせたい) |
CMD 単体 |
実行時の引数で簡単に変更可能 |
実行させたいコマンドを固定したい(常に実行させる) |
ENTRYPOINT 単体 |
ユーザーが指定した引数が付け加えられるだけ |
実行コマンドを固定しつつ、引数はデフォルトを与えつつ変更も許したい |
ENTRYPOINT + CMD
|
実行ファイル+その引数として動作する |
上書きの挙動
使い方 | docker run時の上書き可否 | 説明 |
---|---|---|
CMDのみ |
docker run イメージ名 新しい引数 で上書き可能 |
柔軟に変えたい時に便利 |
ENTRYPOINTのみ |
docker run の引数はすべてENTRYPOINTの引数になる |
コマンドは変わらない |
ENTRYPOINT + CMD | CMD部分だけ上書き可能 | コマンドは固定・引数だけ変えられる |
ENTRYPOINTを変更したい場合 |
--entrypoint を明示的に指定 |
CMDだけでは変更不可 |
使い所
シーン | 使い方 | 理由 |
---|---|---|
デバッグや試行錯誤 | CMDのみ | 柔軟性が高い。runの都度挙動を変えやすい |
スクリプト実行ツールとして配布 | ENTRYPOINTのみ | 実行内容を強制できる(例:CLIツール) |
初期化スクリプト+引数指定 | ENTRYPOINT + CMD | ENTRYPOINTでスクリプト、CMDで引数をデフォルト指定 |
ハンズオン環境
実際に再現してみました。
簡単なので、眺めるだけでもある程度理解できると思います。
もし、ハンズオン的に触ってみたい方は GitHub にソースがあります。
https://github.com/shunyonai1996/docker-cmd-entrypoint-demo
$ tree
.
├── article.md
├── Dockerfile-both
├── Dockerfile-cmd
└── Dockerfile-entrypoint
CMD
一応概要から。。。
CMD
はコンテナを実行したときの「デフォルトのコマンドや引数」を指定するものです。
特徴として、docker run
実行時、引数を上書きできます。
CMD の主な目的は、コンテナ実行時のデフォルト(初期設定)を指定するためです 。
https://docs.docker.jp/engine/reference/builder.html#cmd
Dockerfile-cmd
FROM alpine:latest
CMD ["echo", "Hello CMD"]
# build
$ docker build -t cmd-demo -f Dockerfile-cmd .
[+] Building 2.0s (5/5) FINISHED
# run
$ docker run cmd-demo
Hello CMD
# 実行時、コマンドを上書き
$ docker run cmd-demo echo "Overridden CMD"
Overridden CMD
ENTRYPOINT
こちらも概要から。
ENTRYPOINT
はコンテナを「実行ファイル」として動かすため、常に実行されるコマンドを指定します。
docker run
の引数はENTRYPOINTへの引数として追加される。
ENTRYPOINT自体を変えたい場合は--entrypointオプションが必要。
ちなみに「コンテナを実行ファイルとして動かす」という表現が当初よくわからなかったので、補足します(飛ばしてもいいです)。
難しく考えなくて良くて、Dockerfile
のENTRYPOINT
に["echo"]
と記載し、docker run Hello
を実行したとしましょう。
docker run my-image Hello World
# => Hello World
上記は以下と全く同じ意味合いです。
echo Hello World
つまり、docker run コンテナ名 引数
という形で、あたかもコマンドに引数を渡すようなインターフェースに見えるということを指しています。
ENTRYPOINT は、コンテナを 実行ファイルexecutable として処理するように設定できます。
Dockerfile-entrypoint
FROM alpine:latest
ENTRYPOINT ["echo", "Hello ENTRYPOINT"]
# build
$ docker build -t entrypoint-demo -f Dockerfile-entrypoint .
[+] Building 2.1s (5/5) FINISHED
# run
$ docker run entrypoint-demo
Hello ENTRYPOINT
# 実行時、コマンドを上書き
$ docker run --entrypoint="" entrypoint-demo echo "Overridden ENTRYPOINT"
Overridden ENTRYPOINT
CMD
& ENTRYPOINT
ENTRYPOINTが「実行するコマンド」、CMDが「そのコマンドのデフォルト引数」になる。
Dockerfile-both
FROM alpine:latest
ENTRYPOINT ["echo"]
CMD ["Hello ENTRYPOINT & CMD"]
# build
$ docker build -t both-demo -f Dockerfile-both .
[+] Building 0.9s (5/5) FINISHED
# run
$ docker run both-demo
Hello ENTRYPOINT & CMD
# 実行時、引数を変更
$ docker run both-demo "Custom Argument"
Custom Argument