2787 votes

Quelle est la différence entre CMD et ENTRYPOINT dans un Dockerfile ?

Dans Dockerfiles, il y a deux commandes qui me semblent similaires : CMD et ENTRYPOINT . Mais je suppose qu'il y a une différence (subtile ?) entre les deux, sinon cela n'aurait aucun sens d'avoir deux commandes pour la même chose.

La documentation indique que pour CMD

L'objectif principal d'un CMD est de fournir des valeurs par défaut pour un conteneur en cours d'exécution.

et pour ENTRYPOINT :

Un ENTRYPOINT vous aide à configurer un conteneur que vous pouvez exécuter comme un exécutable.

Alors, quelle est la différence entre ces deux commandes ?

2 votes

^ que ! Merci @slm . Voici une autre référence très similaire qui pourrait être un peu plus à jour : docs.docker.com/reference/builder/#entrypoint

84 votes

Aussi déroutant que la différence entre ADD et COPY

5 votes

Ce lien fournit la différence entre RUN, CMD, et ENTRYPOINT : goinbigdata.com/docker-run-vs-cmd-vs-entrypoint

2655voto

creack Points 11635

Docker a un point d'entrée par défaut qui est /bin/sh -c mais n'a pas de commande par défaut.

Quand tu exécutes Docker comme ça : docker run -i -t ubuntu bash le point d'entrée est le point 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 qui est exécutée est /bin/sh -c bash . Cela a permis à Docker de mettre en œuvre RUN rapidement en s'appuyant sur l'analyseur syntaxique de l'interpréteur de commandes.

Par la suite, les gens ont demandé à pouvoir personnaliser ce système. ENTRYPOINT et --entrypoint ont été introduits.

Tout après ubuntu dans l'exemple ci-dessus est la commande et est passée au point d'entrée. Lorsque l'on utilise la méthode CMD l'instruction, 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 démarrerez toujours un shell bash dans le conteneur grâce à la fonction ubuntu Dockerfile a 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. L'exemple de @Jiri est bon, il montre comment utiliser une image comme un "binaire". Lorsque vous utilisez ["/bin/cat"] comme point d'entrée et ensuite faire docker run img /etc/passwd vous l'avez, /etc/passwd est la commande et est passée au point d'entrée de sorte que l'exécution du résultat final est simplement /bin/cat /etc/passwd .

Un autre exemple serait d'avoir n'importe quel 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écuté comme ceci pour le même résultat : docker run redisimg get key .

0 votes

Donc d'après ceci, si je mets ceci en haut de mon Dockerfile : RUN ln -sf /bin/bash /bin/sh && ln -sf /bin/bash /bin/sh.distrib OU je mets ceci à la fin de mon Dockerfile : ENTRYPOINT ["/bin/bash", "-c"] Les deux font exactement la même chose dans mes conteneurs Debian : modifier /bin/sh à /bin/bash ?

7 votes

Pas du tout. ENTRYPOINT définit une métadonnée qui peut (mais peut être remplacée) au moment de l'exécution, donc si vous ne changez rien, après avoir démarré votre conteneur, le résultat sera le même, cependant, RUN sera exécuté au moment de la construction et peu importe ce que vous faites au moment de l'exécution, il sera là.

18 votes

Par défaut, il n'y a pas de ENTRYPOINT ; l'utilisation d'un shell dépend de la forme utilisée de l'option CMD ( docs.docker.com/engine/reference/builder/#cmd ).

1247voto

Daishi Points 3730

Le site ENTRYPOINT spécifie une commande qui sera toujours exécutée au démarrage du conteneur.

Le site CMD spécifie les arguments qui seront fournis à la ENTRYPOINT .

Si vous voulez faire une image dédiée à une commande spécifique, vous utiliserez ENTRYPOINT ["/path/dedicated_command"]

Sinon, si vous voulez faire une image pour un usage général, vous pouvez laisser ENTRYPOINT non spécifié et utilisation CMD ["/path/dedicated_command"] car vous pourrez remplacer ce paramètre en fournissant des arguments à l'option 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 le 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 de 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 Dockerfile est :

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

L'exécution de l'image sans aucun argument fera un ping sur le 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 exécuter l'image avec un argument exécutera l'argument :

docker run -it test bash
root@e8bb7249b843:/#

Voir cet article de Brian DeHamer pour plus de détails : https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/

512 votes

The ENTRYPOINT specifies a command that will always be executed when the container starts. The CMD specifies arguments that will be fed to the ENTRYPOINT. est un bon résumé qui va droit au but.

29 votes

ENTRYPOINT peut aussi être surchargé en utilisant l'indicateur --entrypoint. par exemple docker run -it --entrypoint bash test

9 votes

J'aime vos exemples, c'est vraiment utile !

415voto

Rafaf Tahsin Points 2360

Selon documentation sur les dockers ,

Les instructions CMD et ENTRYPOINT définissent la commande qui sera exécutée lors de l'exécution d'un conteneur. Il existe quelques règles qui décrivent leur coopération.

  1. Le Dockerfile doit spécifier au moins un des éléments suivants CMD ou ENTRYPOINT des commandes.
  2. ENTRYPOINT doit être défini lorsque le conteneur est utilisé comme un exécutable.
  3. CMD doit être utilisé comme un moyen de définir des arguments par défaut pour une commande de type ENTRYPOINT ou pour exécuter une commande ad-hoc dans un conteneur.
  4. CMD seront remplacés lors de l'exécution du conteneur avec des arguments alternatifs.

Les tableaux ci-dessous montrent quelle commande est exécutée pour 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   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD ["p1_cmd", "p2_cmd"]   ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry   ║
╚════════════════════════════╩══════════════════════════════════╝

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

1 votes

Que sont px_cmd et exec_entry ? Qu'est-ce que cela signifie quand ils sont sur la même ligne d'exécution ? Ils sont passés en argument l'un à l'autre ? Même lorsque le /bin/sh -c est impliqué ?

2 votes

@Danielo515 'px_cmd' et 'exec_entry' ne sont que des chaînes factices ici. Vous pouvez simplement remarquer que /bin/sh -c serait ajouté au CMD comme préfixe lorsque le CMD est écrit en syntaxe exécutable (pas en syntaxe liste).

0 votes

Une explication fantastique.

215voto

Jiri Points 4193

Oui, c'est une bonne question. Je ne la comprends pas encore complètement, mais.. :

Je comprends que ENTRYPOINT est le binaire qui est exécuté. Vous pouvez remplacer le point d'entrée par --entrypoint="".

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

CMD est l'argument par défaut du conteneur. Sans point d'entrée, l'argument par défaut est la commande qui est 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

Ainsi, le principal avantage est qu'avec le point d'entrée, vous pouvez passer des arguments (cmd) à votre conteneur. Pour ce faire, vous devez utiliser les deux :

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

et

docker build -t=cat .

alors vous pouvez utiliser :

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

0 votes

@Blauhirn Dans votre cas, vous devez ajouter des arguments à CMD en syntaxe de liste, et vous assurer que le point d'entrée que vous avez séparé peut analyser vos arguments dans CMD. Habituellement, j'ajoute un argument '-h' au point d'entrée. Ensuite, je peux exécuter docker run image_name -h pour afficher des informations d'aide sur cette image.

98voto

upitau Points 566

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 lors de l'exécution du conteneur docker.
  • La commande ENTRYPOINT et les paramètres ne seront pas écrasés à partir de la ligne de commande. Au contraire, tous les arguments de la ligne de commande seront ajoutés après les paramètres ENTRYPOINT.

Si vous avez besoin de plus de détails ou si vous voulez voir la différence sur l'exemple, il y a un article de blog qui compare de manière exhaustive CMD et ENTRYPOINT avec de nombreux exemples. http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

0 votes

C'est un super lien !

2 votes

Peut être écrasé à partir de la ligne de commande à l'aide de la fonction --entrypoint

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X