web-dev-qa-db-fra.com

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

Dans Dockerfiles, deux commandes me ressemblent: CMD et ENTRYPOINT. Mais je suppose qu’il existe une différence (subtile?) Entre eux - sinon, cela n’aurait aucun sens d’avoir deux commandes pour la même chose.

La documentation indique pour CMD

L'objet 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 en tant qu'exécutable.

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

1384
Golo Roden

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 le paramètre 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 ce qui est exécuté 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é à pouvoir personnaliser cela, donc ENTRYPOINT et --entrypoint ont été introduits.

Tout ce qui suit 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 utilisiez 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 plutôt cette commande docker run -i -t ubuntu. Vous allez toujours démarrer un shell bash dans le conteneur à cause du bocku Dockerfile spécifié un CMD par défaut: CMD ["bash"]

Comme tout est passé au point d'entrée, vous pouvez avoir un très joli comportement de vos images. @Jiri exemple est bon, il montre comment utiliser une image en tant que "binaire". Lorsque vous utilisez ["/bin/cat"] comme point d'entrée, puis que vous exécutez docker run img /etc/passwd, vous l'obtenez, /etc/passwd est la commande et est transmis au point d'entrée. Ainsi, le 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"] puis le lancer comme ceci pour le même résultat: docker run redisimg get key.

1447
creack

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

Le CMD spécifie les arguments qui seront envoyés au ENTRYPOINT.

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

Sinon, si vous souhaitez créer une image à des fins générales, vous pouvez laisser ENTRYPOINT non spécifiée et utiliser CMD ["/path/dedicated_command"], car vous pourrez remplacer le paramètre en fournissant des arguments à docker run.

Par exemple, si votre fichier Dockerfile est:

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

Si vous exécutez l'image sans aucun argument, vous devez envoyer une requête ping à l'hôte local:

$ 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, exécuter 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 fichier Dockerfile est:

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

Si vous exécutez l'image sans aucun argument, vous devez envoyer une requête ping à l'hôte local:

$ 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 lancera 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/

459
Daishi

Selon docker docs ,

Les instructions CMD et ENTRYPOINT déterminent quelle commande doit être exécutée lors de l'exécution d'un conteneur. Peu de règles décrivent leur coopération.

  1. Dockerfile doit spécifier au moins une des commandes CMD ou ENTRYPOINT.
  2. ENTRYPOINT devrait être défini lors de l'utilisation du conteneur en tant qu'exécutable.
  3. CMD doit être utilisé pour définir les arguments par défaut d'une commande ENTRYPOINT ou pour exécuter une commande ad-hoc dans un conteneur.
  4. CMD sera remplacé lors de l'exécution du conteneur avec des arguments alternatifs.

Les tableaux ci-dessous indiquent la commande exécutée pour différentes combinaisons 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  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
_
180
Rafaf Tahsin

Oui, c'est une bonne question. Je ne comprends pas encore tout à fait, mais:

Je comprends que ENTRYPOINT est le binaire en cours d’exécution. Vous pouvez outrepasser le point d’entrée avec --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 en tant qu'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 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
160
Jiri

Différence entre CMD et ENTRYPOINT par intuition:

  • ENTRYPOINT: commande à exécuter au démarrage du conteneur.
  • CMD: commande à exécuter lorsque le conteneur démarre ou arguments à ENTRYPOINT, le cas échéant.

Oui, ça se mélange.

Vous pouvez remplacer n'importe lequel d'entre eux lors de l'exécution de 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 à docker run tel que/bin/bash annule toute commande CMD que nous avons écrite dans Dockerfile.

ENTRYPOINT ne peut pas être annulé 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 en tant qu'arguments à ENTRYPOINT. De cette façon, nous pouvons créer un container qui ressemble à un binaire normal tel que ls.

Ainsi, CMD peut agir comme paramètre par défaut pour ENTRYPOINT, puis nous pouvons redéfinir les arguments de CMD à partir de [args].

ENTRYPOINT peut être remplacé par --entrypoint.

38
Tomer Ben David

En un mot:

  • CMD définit les commandes et/ou les paramètres par défaut, qui peuvent être remplacés à partir de la ligne de commande lors de l'exécution du conteneur docker.
  • 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 des exemples différents, voici 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 /

34
upitau

La réponse acceptée est fabuleuse pour expliquer l'histoire. Je trouve ce tableau très bien expliqué par doc officiel sur 'l'interaction entre CMD et ENTRYPOINT' : enter image description here

Commentaires sur la fonction EntryPoint dans code

// ENTRYPOINT/usr/sbin/nginx.

// Définissez le point d'entrée (par défaut, sh -c) sur/usr/sbin/nginx.

// Acceptera le CMD en tant qu'arguments dans/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 relativement stables , puis utiliser CMD pour définir des valeurs par défaut supplémentaires susceptibles d'être modifiées.

Exemple:

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

Construire : 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: En présence de EntryPoint, CMD conservera les arguments à transmettre à EntryPoint. En l'absence de EntryPoint, CMD sera la commande qui sera exécutée.

6
Tahir Rauf

La commande CMD mentionnée dans le fichier Dockerfile peut être remplacée par la commande docker run alors que ENTRYPOINT ne peut pas l'être.

3
anshul

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. CMD command param1 param2 est créé à partir du premier processus.
  • CMD ["param1","param2"]: Ce formulaire permet de fournir des arguments par défaut pour ENTRYPOINT.

ENTRYPOINT (La liste suivante ne considère pas le 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. command param1 param2 est créé à partir du premier processus.

Comme 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, certaines fonctionnalités se chevauchent entre CMD et ENTRYPOINT, ce qui confond souvent les utilisateurs.

2
Jingguo Yao

La plupart des gens l'expliquent parfaitement ici, alors je ne vais pas répéter toutes les réponses. Mais pour avoir une bonne impression, je suggérerais de le tester vous-même en examinant les processus décrits dans le conteneur.

Créez un petit fichier Docker de la forme:

FROM ubuntu:latest
CMD /bin/bash

Construisez-le, exécutez-le avec docker run -it theimage et exécutez ps -eo ppid,pid,args dans le conteneur. Comparez cette sortie à celle que vous recevez de ps lorsque vous utilisez:

  • docker run -it theimage bash
  • Reconstruction de l'image mais avec ENTRYPOINT /bin/bash et exécution dans les deux sens
  • Utiliser CMD ["/bin/bash"]
  • ...

De cette façon, vous verrez facilement les différences entre toutes les méthodes possibles pour vous-même.

0
Garo

Je vais ajouter ma réponse à titre d'exemple1 cela pourrait vous aider à mieux comprendre la différence.

Supposons que nous voulions créer une image qui toujours exécutera une commande de veille au démarrage. Nous allons créer notre propre image et spécifier une nouvelle commande:

FROM ubuntu
CMD sleep 10

Maintenant, nous construisons l'image:

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

Que faire si nous voulons changer le nombre de secondes? Nous devrions changer le Dockerfile car la valeur y est codée en dur, ou remplacer la commande en fournissant un autre:

docker run custom_sleep sleep 20

Bien que cela fonctionne, ce n'est pas une bonne solution, car nous avons une commande "sleep" redondante (le conteneur a pour but de sleep, il est donc inutile de spécifier explicitement la commande sleep entraine toi).

Essayons maintenant d’utiliser l’instruction ENTRYPOINT:

FROM ubuntu
ENTRYPOINT sleep

Cette instruction spécifie le programme qui sera exécuté au démarrage du conteneur.

Maintenant nous pouvons courir:

docker run custom_sleep 20

Qu'en est-il d'une valeur par défaut? Eh bien, vous l'avez bien compris:

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

La ENTRYPOINT est le programme qui sera exécuté et la valeur transmise au conteneur lui sera ajoutée.

La ENTRYPOINT peut être remplacée en spécifiant un indicateur --entrypoint, suivi du nouveau point d'entrée que vous souhaitez utiliser.

Pas le mien, j'ai déjà regardé un tutoriel qui fournissait cet exemple

0
Maroun