it-swarm.com.de

Was ist der Unterschied zwischen CMD und ENTRYPOINT in einer Docker-Datei?

In Dockerfiles gibt es zwei Befehle, die mir ähnlich sehen: CMD und ENTRYPOINT. Aber ich vermute, dass es einen (subtilen?) Unterschied zwischen ihnen gibt - ansonsten wäre es nicht sinnvoll, zwei Befehle für dieselbe Sache zu haben.

In der Dokumentation wird für CMD angegeben.

Der Hauptzweck einer CMD besteht darin, Standardwerte für einen ausführenden Container bereitzustellen.

und für ENTRYPOINT:

Mit ENTRYPOINT können Sie einen Container konfigurieren, den Sie als ausführbare Datei ausführen können.

Was ist der Unterschied zwischen diesen beiden Befehlen?

1384
Golo Roden

Docker hat einen Standardeinstiegspunkt, der /bin/sh -c ist, aber keinen Standardbefehl hat.

Wenn Sie Docker wie folgt ausführen: docker run -i -t ubuntu bash Der Eintrittspunkt ist der Standardwert /bin/sh -c, das Image ist ubuntu und der Befehl ist bash.

Der Befehl wird über den Entypoint ausgeführt. das tatsächliche Ding, das ausgeführt wird, ist /bin/sh -c bash. Auf diese Weise konnte Docker RUN schnell implementieren, indem es sich auf den Parser der Shell stützte.

Später baten die Leute darum, dies anpassen zu können, und so wurden ENTRYPOINT und --entrypoint eingeführt.

Alles nach ubuntu im obigen Beispiel ist der Befehl und wird an den Entypoint übergeben. Wenn Sie die Anweisung CMD verwenden, ist dies genau so, als würden Sie docker run -i -t ubuntu <cmd> ausführen. <cmd> ist der Parameter des Eintrittspunkts.

Das gleiche Ergebnis erhalten Sie auch, wenn Sie stattdessen den Befehl docker run -i -t ubuntu eingeben. Sie werden weiterhin eine Bash-Shell im Container starten, da buntu Dockerfile eine Standard-CMD angegeben hat: CMD ["bash"]

Da alles an den Eingangspunkt übergeben wird, können Sie mit Ihren Bildern ein sehr gutes Verhalten erzielen. @ Jiri Beispiel ist gut, es zeigt, wie man ein Bild als "Binär" verwendet. Wenn Sie ["/bin/cat"] als Einstiegspunkt verwenden und dann docker run img /etc/passwd ausführen, erhalten Sie, dass /etc/passwd der Befehl ist und an den Einstiegspunkt übergeben wird, sodass die Ausführung des Endergebnisses einfach /bin/cat /etc/passwd ist.

Ein anderes Beispiel wäre, ein beliebiges CLI als Zwischenpunkt zu haben. Wenn Sie beispielsweise ein Redis-Image haben, können Sie anstelle von docker run redisimg redis -H something -u toto get key einfach ENTRYPOINT ["redis", "-H", "something", "-u", "toto"] ausführen und dann für dasselbe Ergebnis wie folgt vorgehen: docker run redisimg get key.

1447
creack

Das ENTRYPOINT gibt einen Befehl an, der immer beim Start des Containers ausgeführt wird.

Das CMD gibt Argumente an, die dem ENTRYPOINT zugeführt werden.

Wenn Sie ein Bild für einen bestimmten Befehl erstellen möchten, verwenden Sie ENTRYPOINT ["/path/dedicated_command"]

Wenn Sie ein Bild für allgemeine Zwecke erstellen möchten, können Sie ENTRYPOINT nicht angeben und CMD ["/path/dedicated_command"] verwenden, da Sie die Einstellung überschreiben können, indem Sie docker run Argumente übergeben.

Zum Beispiel, wenn Ihre Docker-Datei:

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

Wenn Sie das Bild ohne Argument ausführen, wird der localhost als Ping gesendet:

$ 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

Wenn Sie jetzt das Bild mit einem Argument ausführen, wird das Argument mit einem Ping-Befehl beantwortet:

$ 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

Zum Vergleich, wenn Ihre Docker-Datei:

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

Wenn Sie das Bild ohne Argument ausführen, wird der localhost als Ping gesendet:

$ 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

Wenn Sie das Bild jedoch mit einem Argument ausführen, wird das folgende Argument ausgeführt:

docker run -it test bash
[email protected]:/#

Weitere Informationen finden Sie in diesem Artikel von Brian DeHamer: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/

459
Daishi

Nach Docker-Dokumente ,

Sowohl CMD- als auch ENTRYPOINT-Anweisungen definieren, welcher Befehl beim Ausführen eines Containers ausgeführt wird. Es gibt nur wenige Regeln, die ihre Zusammenarbeit beschreiben.

  1. Dockerfile sollte mindestens einen der Befehle CMD oder ENTRYPOINT angeben.
  2. ENTRYPOINT sollte definiert werden, wenn der Container als ausführbare Datei verwendet wird.
  3. CMD sollte als Methode zum Definieren von Standardargumenten für einen ENTRYPOINT -Befehl oder zum Ausführen eines Ad-hoc-Befehls in einem Container verwendet werden.
  4. CMD wird überschrieben, wenn der Container mit alternativen Argumenten ausgeführt wird.

Die folgenden Tabellen zeigen , welcher Befehl für verschiedene ENTRYPOINT/CMD Kombinationen ausgeführt wird :

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

Ja, das ist eine gute Frage. Ich verstehe es noch nicht ganz, aber:

Ich verstehe, dass ENTRYPOINT die Binärdatei ist, die ausgeführt wird. Sie können entrypoint durch --entrypoint = "" überschreiben.

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

CMD ist das Standardargument für container. Ohne Entrypoint ist das Standardargument der Befehl, der ausgeführt wird. Mit entrypoint wird cmd als Argument an entrypoint übergeben. Sie können einen Befehl mit Entrypoint emulieren.

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

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

Der Hauptvorteil ist also, dass Sie mit entrypoint Argumente (cmd) an Ihren Container übergeben können. Um dies zu erreichen, müssen Sie beide verwenden:

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

und

docker build -t=cat .

dann können Sie verwenden:

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

Unterschied zwischen CMD und ENTRYPOINT durch Intuition:

  • ENTRYPOINT: Befehl, der ausgeführt wird, wenn der Container gestartet wird.
  • CMD: Befehl, der ausgeführt wird, wenn der Container gestartet wird, oder Argumente für ENTRYPOINT, falls angegeben.

Ja, es ist durcheinander.

Sie können jeden von ihnen überschreiben, wenn Sie docker run ausführen.

Unterschied zwischen CMD und ENTRYPOINT am Beispiel:

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

Weitere Informationen zum Unterschied zwischen CMD und ENTRYPOINT:

Ein Argument für docker run wie/bin/bash überschreibt jeden CMD-Befehl, den wir in Dockerfile geschrieben haben.

ENTRYPOINT kann zur Laufzeit nicht mit normalen Befehlen wie docker run [args] überschrieben werden. Die args am Ende von docker run [args] werden als Argumente für ENTRYPOINT bereitgestellt. Auf diese Weise können wir eine container erstellen, die einer normalen Binärdatei wie ls ähnelt.

CMD kann also als Standardparameter für ENTRYPOINT fungieren, und dann können wir die CMD-Argumente von [Argumente] überschreiben.

ENTRYPOINT kann mit --entrypoint überschrieben werden.

38
Tomer Ben David

In einer Nussschale:

  • CMD legt Standardbefehle und/oder -parameter fest, die über die Befehlszeile überschrieben werden können, wenn der Docker-Container ausgeführt wird.
  • ENTRYPOINT-Befehl und -Parameter werden nicht über die Befehlszeile überschrieben. Stattdessen werden alle Befehlszeilenargumente nach den ENTRYPOINT-Parametern hinzugefügt.

Wenn Sie mehr Details benötigen oder Unterschiede an einem Beispiel sehen möchten, gibt es einen Blog-Beitrag, der CMD und ENTRYPOINT umfassend mit vielen Beispielen vergleicht - http://goinbigdata.com/docker-run-vs-cmd- vs-Entypoint /

34
upitau

Die akzeptierte Antwort ist fabelhaft in der Erklärung der Geschichte. Ich finde, diese Tabelle erklärt es sehr gut aus offizielles Dokument über das Zusammenspiel von CMD und ENTRYPOINT : enter image description here

Kommentare zur EntryPoint-Funktion in Code

// ENTRYPOINT/usr/sbin/nginx.

// Setzen Sie den Entypoint (standardmäßig sh -c) auf/usr/sbin/nginx.

// Akzeptiert die CMD als Argumente für/usr/sbin/nginx.

Ein weiterer Verweis aus Dokumenten

Sie können die exec-Form von ENTRYPOINT verwenden, um ziemlich stabile Standardbefehle und -argumente festzulegen, und dann CMD verwenden, um zusätzliche Standardeinstellungen festzulegen, die mit größerer Wahrscheinlichkeit geändert werden.

Beispiel:

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

Build : 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: In Anwesenheit von EntryPoint speichert CMD Argumente, die an EntryPoint weitergeleitet werden. In Abwesenheit von EntryPoint ist CMD der Befehl, der ausgeführt wird.

6
Tahir Rauf

Der Befehl CMD, der in der Datei Dockerfile erwähnt wird, kann mit dem Befehl docker run überschrieben werden, während ENTRYPOINT nicht überschrieben werden kann.

3
anshul

CMD:

  • CMD ["executable","param1","param2"]: ["executable","param1","param2"] ist der erste Prozess.
  • CMD command param1 param2: /bin/sh -c CMD command param1 param2 ist der erste Prozess. CMD command param1 param2 wird vom ersten Prozess an gegabelt.
  • CMD ["param1","param2"]: Dieses Formular wird verwendet, um Standardargumente für ENTRYPOINT bereitzustellen.

ENTRYPOINT (In der folgenden Liste wird der Fall nicht berücksichtigt, in dem CMD und ENTRYPOINT zusammen verwendet werden.)

  • ENTRYPOINT ["executable", "param1", "param2"]: ["executable", "param1", "param2"] ist der erste Prozess.
  • ENTRYPOINT command param1 param2: /bin/sh -c command param1 param2 ist der erste Prozess. command param1 param2 wird vom ersten Prozess an gegabelt.

Wie creack sagte, wurde CMD zuerst entwickelt. Dann wurde ENTRYPOINT für mehr Individualisierung entwickelt. Da sie nicht zusammen entworfen wurden, gibt es einige Funktionsüberschneidungen zwischen CMD und ENTRYPOINT, die Menschen oft verwirren.

2
Jingguo Yao

Die meisten Leute erklären es hier perfekt, deshalb werde ich nicht alle Antworten wiederholen. Aber um ein gutes Gefühl zu bekommen, würde ich vorschlagen, es selbst zu testen, indem Sie sich die Prozesse im Container ansehen.

Erstellen Sie eine winzige Dockerfile des Formulars:

FROM ubuntu:latest
CMD /bin/bash

Erstellen Sie es, führen Sie es mit docker run -it theimage ein und führen Sie ps -eo ppid,pid,args im Container aus. Vergleichen Sie diese Ausgabe mit der Ausgabe, die Sie von ps erhalten, wenn Sie Folgendes verwenden:

  • docker run -it theimage bash
  • Erstellen Sie das Image mit ENTRYPOINT /bin/bash neu und führen Sie es auf beide Arten aus
  • CMD ["/bin/bash"] verwenden
  • ...

Auf diese Weise können Sie die Unterschiede zwischen allen möglichen Methoden leicht selbst erkennen.

0
Garo

Ich werde meine Antwort als Beispiel hinzufügen1 das könnte Ihnen helfen, den Unterschied besser zu verstehen.

Nehmen wir an, wir möchten ein Image erstellen, das immer beim Start einen Befehl für den Ruhezustand ausführt. Wir erstellen ein eigenes Image und geben einen neuen Befehl an:

FROM ubuntu
CMD sleep 10

Nun bauen wir das Image auf:

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

Was ist, wenn wir die Anzahl der Sekunden ändern möchten? Wir müssten Dockerfile ändern, da der Wert dort fest codiert ist, oder den Befehl überschreiben, indem wir einen anderen Wert angeben:

docker run custom_sleep sleep 20

Obwohl dies funktioniert, ist es keine gute Lösung, da wir einen redundanten "sleep" -Befehl haben (der Zweck des Containers ist sleep, also ist es nicht gut, den sleep -Befehl explizit anzugeben trainieren).

Versuchen wir nun, die Anweisung ENTRYPOINT zu verwenden:

FROM ubuntu
ENTRYPOINT sleep

Diese Anweisung gibt das Programm an, das ausgeführt wird, wenn der Container gestartet wird.

Jetzt können wir laufen:

docker run custom_sleep 20

Was ist mit einem Standardwert? Nun, Sie haben es richtig erraten:

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

Das ENTRYPOINT ist das Programm, das ausgeführt wird, und der an den Container übergebene Wert wird daran angehängt.

Das ENTRYPOINT kann überschrieben werden, indem ein --entrypoint -Flag gefolgt von dem neuen Einstiegspunkt angegeben wird, den Sie verwenden möchten.

Ich habe mir einmal ein Tutorial angesehen, das dieses Beispiel lieferte

0
Maroun