Quelle est la différence entre CMD et ENTRYPOINT dans un Dockerfile?
Dans Dockerfiles il y a deux commandes qui ressemblent à moi: CMD
et ENTRYPOINT
. Mais je suppose qu'il y a un (subtil?) différence entre eux-sinon cela n'aurait aucun sens d'avoir deux commandes pour la même chose.
La documentation indique CMD
Le but principal D'un CMD est de fournir des valeurs par défaut pour un conteneur en cours d'exécution.
Et pour ENTRYPOINT
:
Un point D'entrée vous aide à configurer un conteneur que vous pouvez exécuter comme un exécutable.
Alors, quelle est la différence entre ces deux commandes?
9 réponses
Docker a un point d'entrée par défaut qui est /bin/sh -c
mais n'a pas de commande par défaut.
Lorsque vous exécutez docker comme ceci:
docker run -i -t ubuntu bash
le point d'entrée est la valeur par défaut /bin/sh -c
, l'image est ubuntu
, et la commande est bash
.
La commande est exécutée via le point d'entrée. c'est-à-dire que la chose réelle qui est exécutée est /bin/sh -c bash
. Cela a permis à Docker d'implémenter RUN
rapidement en s'appuyant sur l'analyseur du shell.
Plus tard, les gens ont demandé de pouvoir personnaliser cela, donc ENTRYPOINT
et --entrypoint
ont été introduites.
Tout ubuntu
dans l'exemple ci-dessus est la commande et est transmis au point d'entrée. Lorsque vous utilisez l'instruction CMD
, c'est exactement comme si vous faisiez docker run -i -t ubuntu <cmd>
. <cmd>
sera le paramètre du point d'entrée.
Vous obtiendrez également le même résultat si vous tapez à la place cette commande docker run -i -t ubuntu
. Vous allez toujours démarrer un shell bash dans le conteneur en raison du ubuntu Dockerfile spécifié un CMD par défaut: CMD ["bash"]
Comme tout est passé au point d'entrée, vous pouvez avoir un comportement très agréable à partir de vos images. @Jiri exemple est bon, il montre comment utiliser une image comme un "binaire". Lorsque vous utilisez ["/bin/cat"]
comme entrypoint et que vous faites docker run img /etc/passwd
, vous l'obtenez, /etc/passwd
est la commande et est passée à l'entrypoint de sorte que l'exécution du résultat final est simplement /bin/cat /etc/passwd
.
Un autre exemple serait d'avoir n'importe quelle cli comme point d'entrée. Par exemple, si vous avez une image redis, au lieu d'exécuter docker run redisimg redis -H something -u toto get key
, Vous pouvez simplement avoir ENTRYPOINT ["redis", "-H", "something", "-u", "toto"]
et ensuite exécuter comme ceci pour le même résultat: docker run redisimg get key
.
Le ENTRYPOINT
spécifie une commande qui sera toujours exécutée au démarrage du conteneur.
Le CMD
spécifie les arguments qui seront nourris à la ENTRYPOINT
.
Si vous souhaitez créer une image dédiée à une commande spécifique, vous utiliserez ENTRYPOINT ["/path/dedicated_command"]
Sinon, si vous voulez créer une image à usage général, vous pouvez laisser ENTRYPOINT
non spécifié et utiliser CMD ["/path/dedicated_command"]
car vous pourrez remplacer le paramètre en fournissant des arguments à docker run
.
Par exemple, si votre Dockerfile est:
FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
L'exécution de l'image sans aucun argument fera un ping sur localhost:
$ 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
Maintenant, l'exécution de l'image avec un argument fera un ping sur l'argument:
$ 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
À titre de comparaison, si votre fichier Dockerfile est:
FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
L'exécution de l'image sans aucun argument fera un ping sur localhost:
$ 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
Mais l'exécution de l'image avec un argument exécutera l'argument:
docker run -it test bash
root@e8bb7249b843:/#
Voir cet article de Brian DeHamer pour encore plus détail: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
Oui, c'est une bonne question. Je ne le comprends pas encore complètement, mais:
Je comprends que ENTRYPOINT
est le binaire en cours d'exécution. Vous pouvez overide entrypoint par --entrypoint="".
docker run -t -i --entrypoint="/bin/bash" ubuntu
CMD est l'argument par défaut du conteneur. Sans entrypoint, l'argument par défaut est la commande exécutée. Avec entrypoint, cmd est passé à entrypoint comme argument. Vous pouvez émuler une commande avec entrypoint.
# no entrypoint
docker run ubuntu /bin/cat /etc/passwd
# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
Donc, le principal avantage est qu'avec entrypoint vous pouvez passer arguments (cmd) à votre conteneur. Pour ce faire, vous devez utiliser les deux:
# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]
Et
docker build -t=cat .
Ensuite, vous pouvez utiliser:
docker run cat /etc/passwd
# ^^^^^^^^^^^
# CMD
# ^^^
# image (tag)- using the default ENTRYPOINT
Selon docker docs,
Les instructions CMD et ENTRYPOINT définissent la commande exécutée lors de l'exécution d'un conteneur. Il y a peu de règles qui décrivent leur de la coopération.
- Dockerfile doit spécifier au moins une des commandes
CMD
ouENTRYPOINT
.ENTRYPOINT
doit être défini lors de l'utilisation du conteneur en tant qu'exécutable.CMD
doit être utilisé comme un moyen de définir des arguments par défaut pour une commandeENTRYPOINT
ou pour exécution d'une commande ad hoc dans un conteneur.- {[3] } sera remplacé lors de l'exécution du conteneur avec des arguments alternatifs.
Les tableaux ci-dessous montre quelle commande est exécutée pour les différents ENTRYPOINT
/ CMD
combinaisons:
-- 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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
En un mot:
- CMD définit la commande et/ou les paramètres par défaut, qui peuvent être écrasés à partir de la ligne de commande lorsque le conteneur docker s'exécute.
- la commande et les paramètres ENTRYPOINT ne seront pas écrasés à partir de la ligne de commande. Au lieu de cela, tous les arguments de ligne de commande seront ajoutés après les paramètres ENTRYPOINT.
Si vous avez besoin de plus de détails ou si vous souhaitez voir la différence sur l'exemple, il y a un article de blog qui compare globalement CMD et ENTRYPOINT avec beaucoup d'exemples - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/
Différence entre CMD et ENTRYPOINT par intuition:
- ENTRYPOINT: commande à exécuter au démarrage du conteneur.
- CMD: commande à exécuter au démarrage du conteneur ou arguments à ENTRYPOINT si spécifié.
Oui, ça se mélange.
Vous pouvez remplacer l'un d'eux lors de l'exécution docker run.
Différence entre CMD et ENTRYPOINT par exemple :
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
Plus sur la différence entre CMD
et ENTRYPOINT
:
L'Argument de docker run
tel que / bin / bash remplace toute commande CMD que nous avons écrite dans Dockerfile.
ENTRYPOINT ne peut pas être remplacé au moment de l'exécution avec des commandes normales telles que docker run [args]
. Les args
à la fin de docker run [args]
sont fournis comme arguments pour ENTRYPOINT. De cette façon, nous pouvons créer un container
, qui est comme un binaire normal comme ls
.
Donc CMD peut agir comme paramètres par défaut pour ENTRYPOINT et ensuite nous pouvons remplacer les args CMD de [args].
ENTRYPOINT peut être remplacer par --entrypoint
.
La réponse acceptée est fabuleuse pour expliquer l'histoire. Je trouve que ce tableau l'explique très bien à partir de doc officiel sur 'comment cmd et ENTRYPOINT interagissent' :
Commentaires sur la fonction EntryPoint dans code
// point d'entrée /usr/sbin/nginx.
/ / définit le point d'entrée (par défaut sh-c) sur /usr/sbin/nginx.
/ / acceptera le CMD comme arguments pour /usr / sbin / nginx.
Une autre Référence de documents
Vous pouvez utiliser la forme exec de ENTRYPOINT pour définir des commandes et des arguments par défaut assez stables , puis utiliser CMD pour définir des valeurs par défaut supplémentaires susceptibles d'être modifiés.
Exemple:
FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]
Construire: sudo docker construire -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: En présence D'EntryPoint, CMD contiendra des arguments à fed to EntryPoint. En l'absence D'EntryPoint, CMD sera la commande qui sera exécutée.
CMD:
-
CMD ["executable","param1","param2"]
:["executable","param1","param2"]
est le premier processus. -
CMD command param1 param2
:/bin/sh -c CMD command param1 param2
est le premier processus. {[2] } est bifurqué du premier processus. -
CMD ["param1","param2"]
: Ce formulaire est utilisé pour fournir des arguments par défaut pourENTRYPOINT
.
ENTRYPOINT (la liste suivante ne tient pas compte du cas où CMD et ENTRYPOINT sont utilisés ensemble):
-
ENTRYPOINT ["executable", "param1", "param2"]
:["executable", "param1", "param2"]
est le premier processus. -
ENTRYPOINT command param1 param2
:/bin/sh -c command param1 param2
est le premier processus. {[11] } est bifurqué du premier processus.
Comme l'a dit creack , CMD a été développé en premier. Ensuite, ENTRYPOINT a été développé pour plus de personnalisation. Comme ils ne sont pas conçus ensemble, il y a des chevauchements de fonctionnalités entre CMD et ENTRYPOINT, qui confondent souvent les gens.