web-dev-qa-db-ja.com

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

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

ドキュメントはCMDのために述べます

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

そしてENTRYPOINTの場合:

エントリポイントを使用すると、実行可能ファイルとして実行できるコンテナを設定できます。

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

1272
Golo Roden

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 ubuntuを入力しても同じ結果が得られます。 ubuntu Dockerfile にデフォルトのCMDが指定されているため、コンテナーでbashシェルを起動することができます。CMD ["bash"]

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

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

1331
creack

ENTRYPOINTは、コンテナの起動時に常に実行されるコマンドを指定します。

CMDENTRYPOINTに渡される引数を指定します。

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

そうではなく、汎用のイメージを作成したい場合は、ENTRYPOINTを未指定のままにしてCMD ["/path/dedicated_command"]を使用すると、docker runに引数を指定して設定をオーバーライドできます。

たとえば、Dockerfileが次のようになっているとします。

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["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"]

引数なしでイメージを実行すると、ローカルホストに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
[email protected]:/#

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

400
Daishi

docker docs によると

CMD命令とENTRYPOINT命令はどちらも、コンテナを実行したときに実行されるコマンドを定義します。それらの協力を記述する規則はほとんどありません。

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

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

- 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 exec_cmd p1_cmd            ║
╟────────────────────────────╫───────────────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd              ║
╟────────────────────────────╫───────────────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd ║
╚════════════════════════════╩═══════════════════════════════════════════════════════════╝

- 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  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
156
Rafaf Tahsin

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

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

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

CMDはcontainerのデフォルトの引数です。エントリポイントがない場合、デフォルトの引数は実行されるコマンドです。 entrypointでは、cmdはentrypointに引数として渡されます。 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
152
Jiri

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の違いの詳細:

/ bin/bashのようなdocker runへの引数は、Dockerfileに書いたCMDコマンドを上書きします。

実行時にENTRYPOINTをdocker run [args]などの通常のコマンドで上書きすることはできません。 docker run [args]の最後にあるargsは、ENTRYPOINTの引数として提供されています。このようにして、containerのような通常のバイナリのようなlsを作成できます。

そのため、CMDはENTRYPOINTのデフォルトパラメータとして機能し、[args]からCMD argsを上書きできます。

ENTRYPOINTは--entrypointで上書きすることができます。

30
Tomer Ben David

手短に:

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

あなたがより多くの詳細を必要とするかまたは例の違いを見たいと思うならば、包括的にCMDとENTRYPOINTを多くの例と比較するブログ記事があります - http://goinbigdata.com/docker-run-vs-cmd-vs-エントリーポイント/

30
upitau

受け入れられた答えは歴史を説明することにおいてすばらしいです。私はこの表が 'CMDとENTRYPOINTがどのように相互作用するか'についての公式文書から非常によく説明していると思いますenter image description here

code のEntryPoint関数に関するコメント

//エントリポイント/ usr/sbin/nginx。

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

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

文書からの別の参照

Exec形式のENTRYPOINTを使用して かなり安定したデフォルトのコマンドと引数 を設定してから、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

p.s:EntryPointがあると、CMDはEntryPointに渡される引数を保持します。 EntryPointがないと、CMDは実行されるコマンドになります。

6
Tahir Rauf

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
Jingguo Yao

CMDファイル内で言及されているDockerfileコマンドは、docker runコマンドを介してオーバーライドできますが、ENTRYPOINTはオーバーライドできません。

1
anshul

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

次の形式の小さな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
Garo

例として答えを追加します1 違いをよりよく理解するのに役立つかもしれません。

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

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コマンドを明示的に指定するのは良くありません練習)。

ENTRYPOINT命令を使用してみましょう。

FROM ubuntu
ENTRYPOINT sleep

この指示コンテナの起動時に実行されるプログラムを指定

これで実行できます:

docker run custom_sleep 20

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

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

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

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

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

0
Maroun