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?

1091
demandé sur Jiri 2014-02-04 17:04:23

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.

1157
répondu creack 2018-05-09 20:46:49

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/

298
répondu Daishi 2015-12-12 22:17:34

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
146
répondu Jiri 2015-10-30 12:40:23

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.

  1. Dockerfile doit spécifier au moins une des commandes CMD ou ENTRYPOINT.
  2. ENTRYPOINT doit être défini lors de l'utilisation du conteneur en tant qu'exécutable.
  3. CMD doit être utilisé comme un moyen de définir des arguments par défaut pour une commande ENTRYPOINT ou pour exécution d'une commande ad hoc dans un conteneur.
  4. {[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  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
118
répondu Rafaf Tahsin 2017-06-07 13:41:43

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/

29
répondu upitau 2016-04-03 09:32:35

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.

18
répondu Tomer Ben David 2018-03-01 11:36:12

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' : entrez la description de l'image ici

7
répondu Xiao Peng - ZenUML.com 2017-05-31 10:39:02

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.

5
répondu Tahir Rauf 2016-08-29 04:37:36

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 pour ENTRYPOINT.

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.

1
répondu Jingguo Yao 2017-05-23 12:03:09