DockerfileのCMDとENTRYPOINTの違いは何ですか?


1698

Dockerfilesであり、私に似ている2つのコマンドは、次のとおりですCMDENTRYPOINT。しかし、私はそれらの間に(微妙な?)違いがあると思います-そうでなければ、まったく同じものに対して2つのコマンドがあることは意味がありません。

ドキュメントの状態 CMD

CMDの主な目的は、実行中のコンテナにデフォルトを提供することです。

そしてのためにENTRYPOINT

ENTRYPOINTは、実行可能ファイルとして実行できるコンテナを構成するのに役立ちます。

では、これら2つのコマンドの違いは何ですか?


12
このブログ投稿には、違いとそれらを一緒に使用する方法についての良い説明があります:crosbymichael.com/dockerfile-best-practices.html
slm 2015年

2
^あれ!@slmに感謝します。ここではもう少し最新のかもしれないもう一つの非常に同様の参照です:docs.docker.com/reference/builder/#entrypoint
アダムMonsen

5
混乱としてADD及びCOPY
レドワルド

1
このリンクは、RUN、CMD、ENTRYPOINTの違いを提供します:goinbigdata.com/docker-run-vs-cmd-vs-entrypoint
prafi

1
@JaimeHablutzelフレーズは、自分に好意を示すことです
Jonathan Komar

回答:


1736

Dockerにはデフォルトのエントリポイント/bin/sh -cがありますが、デフォルトのコマンドはありません。

次のようにdockerを実行すると docker run -i -t ubuntu bash 、エントリポイントがデフォルト/bin/sh -cで、イメージはubuntuで、コマンドはbashです。

コマンドはエントリポイントを介して実行されます。つまり、実際に実行されるのは/bin/sh -c bashです。これにより、Docker RUNはシェルのパーサーに依存することで迅速に実装できました。

後で、人々はこれをカスタマイズできるようにしたいのでENTRYPOINT--entrypoint導入されました。

ubuntu上記の例の後のすべてがコマンドであり、エントリポイントに渡されます。CMD命令を使用するとき、それはあなたがやっていたかのように正確ですdocker run -i -t ubuntu <cmd><cmd>エントリポイントのパラメータになります。

代わりにこのコマンドを入力しても、同じ結果が得られますdocker run -i -t ubuntuubuntu DockerfileでデフォルトのCMDが指定されているため、コンテナーでbashシェルを開始します。CMD ["bash"]

すべてがエントリポイントに渡されるため、画像から非常に優れた動作を得ることができます。@Jiriの例は良いです。画像を「バイナリ」として使用する方法を示しています。["/bin/cat"]エントリポイントとして使用してdocker run img /etc/passwdからを実行すると、それ/etc/passwdがコマンドであり、エントリポイントに渡されるため、最終結果の実行は単純です/bin/cat /etc/passwdです。

もう1つの例は、任意のcliをエントリポイントとして持つことです。たとえば、redisイメージがある場合、を実行する代わりにdocker run redisimg redis -H something -u toto get key、単にENTRYPOINT ["redis", "-H", "something", "-u", "toto"]次のように実行して、同じ結果を得ることができますdocker run redisimg get key


3
どういたしまして。ENTRYPOINTは実行時にメタデータを設定できます(ただし、オーバーライドできます)。何も変更しない場合、コンテナーを起動した後、結果は同じになりますが、RUNはビルド時に実行されます。実行時に行うと、ここにあります。
2015

8
デフォルトではありませんENTRYPOINT。シェルを使用するかどうかは、使用するCMDコマンドの形式(docs.docker.com/engine/reference/builder/#cmd)によって異なります。
Blaisorblade、2016年

19
これのおかげで、何が上書きされ、何が追加されるかなど、一見難解なルールを覚えるのに苦労していたので、歴史的なコンテキストは非常に役立ちます。事実とシナリオをリストするだけではありません:-)
ashirley

84
これは素晴らしい答えです。DockerのドキュメントではCMDvs と呼ばれるセクションの下にこれを追加する必要があると思いますENTRYPOINT
Tarik、2016

5
@Webmanいいえ。2つの異なる指示です。両方が存在する場合、CMDはENTRYPOINTのパラメーターとして扱われます。
Light.G

628

ENTRYPOINT指定コンテナの起動時に常に実行されるコマンド。

は、に提供CMDされる引数を指定しますENTRYPOINT

特定のコマンド専用のイメージを作成する場合は、次を使用します ENTRYPOINT ["/path/dedicated_command"]

それ以外の場合で、一般的な目的でイメージを作成する場合は、ENTRYPOINT未指定のままにしてCMD ["/path/dedicated_command"]、に引数を指定することで設定を上書きできるので使用できますdocker run

たとえば、Dockerfileが次の場合:

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]

引数なしでイメージを実行すると、localhostにpingが送信されます。

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms

次に、引数を指定してイメージを実行すると、引数にpingが送信されます。

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

比較のために、Dockerfileが次の場合:

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]

引数なしでイメージを実行すると、localhostにpingが送信されます。

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms

ただし、引数を指定してイメージを実行すると、引数が実行されます。

docker run -it test bash
root@e8bb7249b843:/#

詳細については、Brian DeHamerによるこの記事を参照してください。https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/


219
The ENTRYPOINT specifies a command that will always be executed when the container starts. The CMD specifies arguments that will be fed to the ENTRYPOINT.要点をまとめた良い要約です。
Jingguo Yao

1
ENTRYPOINTは、-entrypointフラグを使用してオーバーライドすることもできます。例:docker run -it --entrypoint bash test
seenimurugan

2
私はあなたの例が好きです、それは本当に役に立ちます!
Chau Giang

2
@Jingguo Yao:CMDに-CMD ["nginx"、 "-g"、 "daemon"、 "off"]などのコマンドが含まれている場合はどうなりますか?連鎖しますか?
KMC、

@KMC CMDはENTRYPOINTのデフォルトの引数であり、イメージを実行するときに新しい引数を渡すことでオーバーライドします。
MGP

237

docker docsによると、

CMD命令とENTRYPOINT命令はどちらも、コンテナの実行時に実行されるコマンドを定義します。彼らの協力を説明するいくつかのルールがあります。

  1. Dockerfileでは、CMDまたはENTRYPOINTコマンドの少なくとも1つを指定する必要があります。
  2. ENTRYPOINT コンテナを実行可能ファイルとして使用するときに定義する必要があります。
  3. CMD のデフォルト引数を定義する方法として使用する必要があります ENTRYPOINTコマンドのまたはコンテナでアドホックコマンドを実行するあります。
  4. CMD 代替の引数でコンテナを実行すると、オーバーライドされます。

以下の表は、さまざまな/ 組み合わせに対して実行されるコマンドを示してますENTRYPOINTCMD

- No ENTRYPOINT

╔════════════════════════════╦═════════════════════════════╗
║ No CMD                     ║ error, not allowed          ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════╝

- ENTRYPOINT exec_entry p1_entry

╔════════════════════════════╦══════════════════════════════════╗
║ No CMD                     ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry   ║
╚════════════════════════════╩══════════════════════════════════╝

- ENTRYPOINT [“exec_entry”, “p1_entry”]

╔════════════════════════════╦═════════════════════════════════════════════════╗
║ No CMD                     ║ exec_entry p1_entry                             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_entry p1_entry exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ exec_entry p1_entry p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝

px_cmdおよびexec_entryとは何ですか?それらが同じ実行ライン上にある場合、どういう意味ですか?それらは互いに引数として渡されますか?/bin/sh -c関与している場合でも?
Danielo515 2017年

1
@ Danielo515 'px_cmd'と 'exec_entry'は、ここでは単なるダミー文字列です。/bin/sh -cCMDが実行可能な構文(リスト構文ではなく)で記述されているときに、それがCMDにプレフィックスとして追加されることに気付くでしょう。
Light.G 2018

1
@roykiユーザーがdocker runに引数を指定すると、CMDで指定されたデフォルトをオーバーライドします。
ドンロンダドン

2
ENTRYPOINT exec_entry p1_ent誤って説明されました。シェルフォームは、CMDまたは実行コマンドライン引数が使用されないようにします-docs.docker.com/engine/reference/builder/#entrypoint
Mariusz Miesiak

1
@MariuszMiesiak更新されました。ご意見をいただきありがとうございます。
Rafaf Tahsin

170

はい、それは良い質問です。私はまだそれを完全には理解していませんが、:

それENTRYPOINTが実行されているバイナリであることを理解しています。--entrypoint = ""でエントリポイントを上書きできます。

docker run -t -i --entrypoint="/bin/bash" ubuntu

CMDはコンテナのデフォルトの引数です。エントリポイントがない場合、デフォルトの引数は実行されるコマンドです。entrypointでは、cmdが引数としてentrypointに渡されます。エントリポイントを使用してコマンドをエミュレートできます。

# no entrypoint
docker run ubuntu /bin/cat /etc/passwd

# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd

したがって、主な利点は、エントリポイントを使用して引数(cmd)をコンテナに渡すことができることです。これを行うには、次の両方を使用する必要があります。

# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]

そして

docker build -t=cat .

それからあなたは使うことができます:

docker run cat /etc/passwd
#              ^^^^^^^^^^^
#                   CMD
#          ^^^      
#          image (tag)- using the default ENTRYPOINT

@Blauhirnこの場合、リスト構文でCMDに引数を追加し、指定したエントリポイントがCMDで引数を解析できることを確認する必要があります。通常、エントリポイントに「-h」引数を追加します。次にdocker run image_name -h、この画像のヘルプ情報を表示するために実行します。
Light.G 2018

1
これが最もシンプルで明確な答えです。
Eric Wang

44

直感による CMDとENTRYPOINTの違い

  • ENTRYPOINT:コンテナーの開始時に実行するコマンド。
  • CMD:コンテナの起動時に実行するコマンド、または指定されている場合はENTRYPOINTの引数。

はい、混同しています。

docker runを実行するときに、これらのいずれかをオーバーライドできます。

例による CMDとENTRYPOINTの違い:

docker run -it --rm yourcontainer /bin/bash            <-- /bin/bash overrides CMD
                                                       <-- /bin/bash does not override ENTRYPOINT
docker run -it --rm --entrypoint ls yourcontainer      <-- overrides ENTRYPOINT with ls
docker run -it --rm --entrypoint ls yourcontainer  -la  <-- overrides ENTRYPOINT with ls and overrides CMD with -la

その他の違いにCMDENTRYPOINT

への議論 docker run/ bin / bashなどのは、Dockerfileに書き込んだCMDコマンドを上書きします。

ENTRYPOINTは、などの通常のコマンドを使用して実行時にオーバーライドすることはできませんdocker run [args]args終わりのdocker run [args]ENTRYPOINTへの引数として提供されています。このようにして、次のcontainerような通常のバイナリのようなaを作成できます。ls

したがって、CMDはENTRYPOINTのデフォルトパラメータとして機能し、CMD argsを[args]からオーバーライドできます。

ENTRYPOINTはでオーバーライドできます--entrypoint


38

手短に:

  • CMDはデフォルトのコマンドやパラメーターを設定します。これらは、Dockerコンテナーの実行時にコマンドラインから上書きできます。
  • ENTRYPOINTコマンドとパラメーターは、コマンドラインから上書きされません。代わりに、すべてのコマンドライン引数がENTRYPOINTパラメータの後に追加されます。

-あなたはより多くの細部を必要とするかの例で違いを見たい場合は、総合的に多くの例でCMDとENTRYPOINTを比較するブログ投稿がありhttp://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/は、


21

私は例として私の答えを追加します1違いをよりよく理解するのに役立つ。

起動時に常にスリープコマンドを実行するイメージを作成するとします。独自のイメージを作成し、新しいコマンドを指定します。

FROM ubuntu
CMD sleep 10

次に、イメージを作成します。

docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits

秒数を変更したい場合はどうなりますか?Dockerfile値がそこにハードコーディングされているため、を変更するか、別の値を指定してコマンドをオーバーライドする必要があります。

docker run custom_sleep sleep 20

これは機能しますが、冗長な「sleep」コマンドがあるため、これは適切な解決策ではありません(コンテナーの目的はsleepであるため、明示的に指定する必要があります)sleepコマンド勧めできません)。

次のENTRYPOINT命令を使用してみましょう:

FROM ubuntu
ENTRYPOINT sleep

この命令は、コンテナの起動時に実行されるプログラムを指定します

これで実行できます:

docker run custom_sleep 20

デフォルト値はどうですか?まあ、あなたはそれを正しく推測しました:

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]

ENTRYPOINT実行されるプログラムであり、コンテナに渡された値は、それに追加されます。

ENTRYPOINT--entrypointフラグを指定し、その後に使用する新しいエントリポイントを指定することでオーバーライドできます。

私ではなく、この例を提供するチュートリアルを見たことがあります


1
これがチュートリアルへのリンクです:youtu.be/OYbEWUbmk90。将来のユーザーに役立つかもしれません。
ChiPlusPlus


7

コード内のEntryPoint関数に関するコメント

// ENTRYPOINT / usr / sbin / nginx。

//エントリポイント(デフォルトはsh -c)を/ usr / sbin / nginxに設定します。

// CMDを/ usr / sbin / nginxへの引数として受け入れます。

文書からの別の参照

ENTRYPOINTのexec形式を使用して、かなり安定したデフォルトのコマンドと引数を設定し、次にCMDを使用して、変更される可能性が高い追加のデフォルトを設定できます。

例:

FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]

ビルド:sudo docker build -t ent_cmd。

CMD arguments are easy to override.

NO argument (sudo docker -it ent_cmd)                :  ping localhost 
argument    (sudo docker run -it ent_cmd google.com) :  ping google.com

To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd

ps:EntryPointがある場合、CMDはEntryPointにフィードされる引数を保持します。EntryPointがない場合、CMDが実行されるコマンドになります。


3

CMDDockerfileファイル内で言及されたdocker runコマンドは、コマンドをENTRYPOINT使用して上書きできますが、上書きできません。


4
docker run --helpコマンドはそれ以外の場合は次のように言います:--entrypoint string Overwrite the default ENTRYPOINT of the image
iomv

3

私はすべての回答を読みました。次のように、一見して理解を深めるために要約します。

まず、コンテナで実行されるコマンド全体には、コマンド引数の 2つの部分が含まれ ます。

  • ENTRYPOINTは、コンテナの起動時に呼び出される実行可能ファイルを定義します(コマンド用)

  • CMDは、ENTRYPOINTに渡される引数を指定します(引数の場合)

Kubernetes In Actionの本では、それに関する重要な注意が示されています。(第7章)

CMD命令を使用して、イメージの実行時に実行するコマンドを指定できますが、正しい方法は、ENTRYPOINT命令を介してそれを実行し、デフォルトの引数を定義する場合のみCMDを指定することです。

この記事を読んで、わかりやすい説明を簡単に読むこともできます。


2

CMD:

  • CMD ["executable","param1","param2"]["executable","param1","param2"]最初のプロセスです。
  • CMD command param1 param2/bin/sh -c CMD command param1 param2最初のプロセスです。CMD command param1 param2最初のプロセスから分岐されます。
  • CMD ["param1","param2"]:このフォームは、のデフォルト引数を提供するために使用されますENTRYPOINT

ENTRYPOINT(次のリストは、CMDとENTRYPOINTが一緒に使用される場合を考慮していません):

  • ENTRYPOINT ["executable", "param1", "param2"]["executable", "param1", "param2"]最初のプロセスです。
  • ENTRYPOINT command param1 param2/bin/sh -c command param1 param2最初のプロセスです。command param1 param2最初のプロセスから分岐されます。

以下のようcreackは言った、CMDは、最初に開発されました。その後、ENTRYPOINTは、さらにカスタマイズするために開発されました。それらは一緒に設計されていないため、CMDとENTRYPOINTの間にはいくつかの機能の重複があり、しばしば混乱を招きます。


2

ほとんどの人はここでそれを完全に説明するので、私はすべての答えを繰り返すことはしません。しかし、良い感じを得るために、コンテナー内のプロセスを見て、自分でテストすることをお勧めします。

次の形式の小さなDockerfileを作成します。

FROM ubuntu:latest
CMD /bin/bash

ビルドして、コンテナでdocker run -it theimage実行ps -eo ppid,pid,argsします。この出力を、使用時にpsから受け取る出力と比較します。

  • docker run -it theimage bash
  • イメージを再構築しますがENTRYPOINT /bin/bash、両方で実行します
  • 使用する CMD ["/bin/bash"]
  • ...

この方法で、すべての可能な方法の違いを自分で簡単に確認できます。


0

Dockerfileのベストプラクティスの公式ドキュメントは、違いを説明するのに非常に役立ちます。 Dockerfileのベストプラクティス

CMD:

CMD命令を使用して、イメージに含まれているソフトウェアを引数とともに実行する必要があります。ほとんどの場合、CMDはの形式で使用する必要がありCMD ["executable", "param1", "param2"…]ます。したがって、イメージがApacheやRailsなどのサービス用である場合は、次のように実行します。CMD ["apache2","-DFOREGROUND"]。実際、この形式の指示は、サービスベースのイメージに推奨されます。

エントリーポイント:

ENTRYPOINTの最適な使用法は、イメージのメインコマンドを設定して、そのイメージがそのコマンドであるかのように実行できるようにすることです(その後、CMDをデフォルトのフラグとして使用します)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.