Dockerfilesには、私に似た2つのコマンドがあります:CMD
とENTRYPOINT
。しかし、私はそれらの間に(微妙な?)違いがあると思います - そうでなければ全く同じことのために二つのコマンドを持つことは意味がありません。
ドキュメントはCMD
のために述べます
CMDの主な目的は、実行中のコンテナにデフォルトを提供することです。
そしてENTRYPOINT
の場合:
エントリポイントを使用すると、実行可能ファイルとして実行できるコンテナを設定できます。
それでは、これら2つのコマンドの違いは何ですか?
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
。
ENTRYPOINT
は、コンテナの起動時に常に実行されるコマンドを指定します。
CMD
はENTRYPOINT
に渡される引数を指定します。
特定のコマンド専用のイメージを作りたい場合は、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
root@e8bb7249b843:/#
さらに詳細についてはBrian DeHamerによるこの記事を参照してください。 https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
docker docs によると
CMD命令とENTRYPOINT命令はどちらも、コンテナを実行したときに実行されるコマンドを定義します。それらの協力を記述する規則はほとんどありません。
- Dockerfileは、
CMD
またはENTRYPOINT
コマンドの少なくとも1つを指定する必要があります。- コンテナーを実行可能ファイルとして使用するときは、
ENTRYPOINT
を定義する必要があります。CMD
は、ENTRYPOINT
コマンドのデフォルト引数を定義する方法、またはコンテナー内でアドホックコマンドを実行する方法として使用する必要があります。- 別の引数でコンテナを実行すると、
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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
はい、それは良い質問です。まだ完全には理解できていませんが、
私は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
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
CMD
とENTRYPOINT
の違いの詳細:
/ bin/bashのようなdocker run
への引数は、Dockerfileに書いたCMDコマンドを上書きします。
実行時にENTRYPOINTをdocker run [args]
などの通常のコマンドで上書きすることはできません。 docker run [args]
の最後にあるargs
は、ENTRYPOINTの引数として提供されています。このようにして、container
のような通常のバイナリのようなls
を作成できます。
そのため、CMDはENTRYPOINTのデフォルトパラメータとして機能し、[args]からCMD argsを上書きできます。
ENTRYPOINTは--entrypoint
で上書きすることができます。
手短に:
あなたがより多くの詳細を必要とするかまたは例の違いを見たいと思うならば、包括的にCMDとENTRYPOINTを多くの例と比較するブログ記事があります - http://goinbigdata.com/docker-run-vs-cmd-vs-エントリーポイント/
受け入れられた答えは歴史を説明することにおいてすばらしいです。私はこの表が 'CMDとENTRYPOINTがどのように相互作用するか'についての公式文書から非常によく説明していると思います :
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は実行されるコマンドになります。
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の間にはいくつかの機能の重複があります。
CMD
ファイル内で言及されているDockerfile
コマンドは、docker run
コマンドを介してオーバーライドできますが、ENTRYPOINT
はオーバーライドできません。
ほとんどの人がここで完璧に説明しているので、すべての答えを繰り返すことはしません。しかし、いい感じを得るには、コンテナ内のプロセスを見て、自分でテストすることをお勧めします。
次の形式の小さな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"]
を使用このようにして、すべての可能な方法の違いを自分で簡単に確認できます。
例として答えを追加します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
フラグを指定し、その後に使用する新しいエントリポイントを指定します。
私のではなく、この例を提供するチュートリアルを見たことがあります