Outils pour utilisateurs

Outils du site


sysadmin:docker:cmd_vs_entrypoint

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
sysadmin:docker:cmd_vs_entrypoint [2021/02/28 14:24] – créée 77.192.232.26sysadmin:docker:cmd_vs_entrypoint [2021/12/30 00:18] (Version actuelle) yoann
Ligne 1: Ligne 1:
-{{tag>sysadmin devops docker dokerfile}}+{{tag>sysadmin devops docker dokerfile todo}}
  
-====== Docker: cmd et entrypoint ======+====== Docker : CMD et ENTRYPOINT ====== 
 + 
 +Les directives **CMD** et **ENTRYPOINT** utilisées dans le Dockerfile permettent toutes les deux de définir une commande initiale présente dans l'image qui sera invoquée au démarrage du conteneur. 
 + 
 +Ces deux directives existent et présentent quelques différences. Selon les besoins on utilisera l'une, l'autre ou les deux. 
 + 
 +Au final, **CMD** ou **ENTRYPOINT** permet d'identifier quel fichier exécutable devrait être invoqué lorsque le conteneur est démarré à partir de l'image. 
 + 
 +Tenter de démarrer une image qui ne contient aucune directive **CMD** ou **ENTRYPOINT** retourne une erreur: 
 + 
 +<code bash> 
 +docker run alpine 
 +FATA[0000] Error response from daemon: No command specified 
 +</code> 
 + 
 + 
 +<note> 
 +De nombreuses images de distributions GNU/Linux présentes sur le dépôt Docker Hub utilise les shells (sh, bash) avec la directive CMD, cela permet à l'utilisateur d'être directement introduit dans un shell lorsque le conteneur est créé avec cette image (si les argument -i et -t sont utilisés lors de l'appel à docker run). 
 +</note> 
 + 
 +La commande définie dans le Dockerfile peut être redéfinie sur la ligne de commande en spécifiant un argument après le nom de l'image: 
 +<code bash> 
 +docker run --rm --name test_cmd -t busybox:1.34-glibc /bin/sh -c "ping -c 2 localhost" 
 +PING localhost (127.0.0.1): 56 data bytes 
 +64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.056 ms 
 +64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.089 ms 
 + 
 +--- localhost ping statistics --- 
 +2 packets transmitted, 2 packets received, 0% packet loss 
 +round-trip min/avg/max = 0.056/0.072/0.089 ms 
 +</code> 
 + 
 +On peut également redéfinir la valeur de l' ENTRYPOINT via l'option **%%--entrypoint%%**, dans ce cas l'option est placée avant le nom de l'image: 
 + 
 +<code bash> 
 +docker run --rm --name test_cmd --entrypoint hostname -t busybox:1.34-glibc 
 +636ecd585d67 
 +</code> 
 + 
 +Comme il est plus simple pour l'usager final de redéfinir la directive **CMD**, la recommandation générale est de l'utiliser de préférence dans le Dokerfile quand on souhaite permettre à l'utilisateur de choisir quel exécutable il souhaite invoquer lors du démarrage du conteneur (offrir à l'utilisateur de la flexibilité). 
 + 
 +Au contraire la directive **ENTRYPOINT** s'utilise plutôt dans les cas ou le conteneur définit un environnement particulier pour un exécutable, un service et qu'il n' est pas prévu que l'usager final redéfinisse cet exécutable. 
 + 
 +La même chose est faisable avec la directive **CMD** cependant l'usage de **ENTRYPOINT** envoi un signal fort indiquant que le conteneur est conçu exclusivement dans le but d’invoquer correctement cet exécutable. 
 + 
 +===== Shell vs Exec ===== 
 + 
 +Les directives **CMD** et **ENTRYPOINT** supportent les deux formes d'invocation possibles: **shell** ou **exec**. 
 + 
 +Dans l'extrait ci-dessous le Dockerfile utilise l'invocation shell 
 +<file> 
 +FROM debian:stretch-slim 
 +RUN apt-get update && apt-get install -y iputils-ping procps 
 + 
 +# Syntaxe pour invocation type shell  
 +CMD ping localhost 
 +</file> 
 + 
 +Si on crée l'image puis le conteneur, tout fonctionne normalement 
 +<code bash> 
 +# création de l'image à partir du Dockerfile présent dans le répertoire courant 
 +docker image build -t "phobos/debian:shell" .  
 + 
 +# Création d'un conteneur utilisant cette image 
 +docker container run --rm --detach --name debian_shell phobos/debian:shell 
 + 
 +# Si on affiche les conteneur en cours d’exécution on peut lire la commande lancée 
 +# dans notre conteneur 
 +docker container list 
 +CONTAINER ID   IMAGE                   COMMAND                  CREATED          NAMES 
 +886ab5702130   phobos/debain:shell    "/bin/sh -c 'ping lo…"   30 seconds ago   busybox_shell 
 + 
 +# Si on affiche les processus s'exécutant depuis l'intérieur du conteneur 
 +docker container exec debian_shell ps -f 
 +UID          PID    PPID  C STIME TTY          TIME CMD 
 +root                  0 17:23 ?        00:00:00 /bin/sh -c ping localhost 
 +root                  0 17:23 ?        00:00:00 ping localhost 
 +root                  0 17:25 ?        00:00:00 ps -f 
 +</code> 
 + 
 +On visualise qu'en effet le processus avec le PID 1 est un shell demandant l’exécution de la commande ping. La commande ping est le processus fils avec ici le PID 7, il a bien pour parent ( PPID 1) le shell. 
 + 
 +Ce mode de fonctionnement peut poser des problèmes dans le cas ou l'on souhaite communiquer avec le processus via des signaux POSIX car le shell ne communiquera pas ces signaux aux processus enfants. 
 + 
 +Un autre problème pouvant se présenter en cas de construction d'une image minimale, c'est l'absence d'un shell. Lorsque Docker construit la commande a exécuter, il ne vérifie pas la présence du shell à l'intérieur du conteneur, si le binaire /bin/sh n'est pas présent dans l'image le démarrage du conteneur échouera systématiquement. 
 + 
 +Une meilleure option est donc d'utiliser la forme d'invocation **exec** 
 + 
 +Pour notre exemple le Dockerfile prend alors la forme suivante: 
 + 
 +<file> 
 +FROM debian:stretch-slim 
 +RUN apt-get update && apt-get install -y iputils-ping procps 
 + 
 +# Syntaxe pour invocation type exec 
 +CMD ["/bin/ping", "localhost"
 +</file> 
 + 
 +<code bash> 
 +# Construction d'une nouvelle image 
 + docker image build -t "phobos/debian:exec"
 + 
 +# Création du conteneur avec la nouvelle image 
 +docker container run --detach --rm --name debian_exec phobos/debian:exec 
 + 
 +# affiche les processus en cours d'execution  
 +# visibles depuis l’intérieur du conteneur 
 +docker container exec debian_exec ps -f 
 +UID          PID    PPID  C STIME TTY          TIME CMD 
 +root                  0 17:43 ?        00:00:00 /bin/ping localhost 
 +root                  0 17:44 ?        00:00:00 ps -f 
 +</code> 
 + 
 +Cette fois on voit que la commande s’exécute directement sans intervention intermédiaire du shell avec le PID 1. 
 + 
 +<note> 
 +Quelle que soit la directive **CMD** ou **ENTRYPOINT** la recommandation générale est d'**utiliser la forme d'invocation exec**. 
 +</note> 
 + 
 +===== Utilisation conjointe ===== 
 + 
 +Jusqu'à présent on a proposé d'utiliser soit **CMD** soit **ENTRYPOINT** mais pas les deux conjointement. Ce cas peut cependant s'avérer utile. 
 + 
 +La combinaison des directives  **ENTRYPOINT** et **CMD** permet de spécifier l' exécutable par défaut pour l'image tout en fournissant à l'utilisateur une façon simple de redéfinir certains arguments ou options. 
 + 
 +<file> 
 +RUN apt-get update && apt-get install -y iputils-ping procps 
 + 
 +# Binaire et options non modifiables 
 +ENTRYPOINT ["/bin/ping", "-c", "10"
 + 
 +# Arguments et options redéfinissables 
 +# facilement par l'utilisateur 
 +CMD ["localhost"
 +</file> 
 + 
 +<code bash> 
 +# Création d'une nouvelle image 
 +docker image build -t "phobos/debian:together"
 + 
 +# Création et exécution d'un conteneur basé sur la nouvelle  image  
 +docker container run --rm --name test_together -t phobos/debian:together 
 + 
 +docker container ps -a 
 +CONTAINER ID   IMAGE                    COMMAND                       CREATED          STATUS                       
 +14dcebd6b360   phobos/debian:together   "/bin/ping -c 10 localhost"   45 seconds ago   Exited (0) 34 seconds ago 
 +</code> 
 + 
 +On note que la commande exécutée dans le conteneur est une combinaison de d' **ENTRYPOINT** et de **CMD**. Quand les deux directives existent dans le Dockerfile, les valeurs de **CMD** sont ajoutées à celle d' **ENTRYPOINT** pour créer la commande à exécuter dans le conteneur. 
 + 
 +Les valeurs définies via CMD pouvant facilement être redéfinies par l'utilisateur (par ajout d'un ou plusieurs arguments après le nom de l'image dans la commande "docker run"), on peut utiliser ce comportement pour proposer une option par défaut indéfinissable par l'utilisateur. 
 + 
 +Dans l'exemple ci-dessus la cible par défaut "localhost" peut  
 +être remplacé à l'execution de la manière suivante: 
 + 
 +<code bash> 
 +# Création d'un conteneur avec redéfinition des arguments par défaut 
 +docker container run phobos/debian:together gateway.phobos.lan 
 + 
 +# Liste les conteneurs existants 
 +docker container ps -a 
 +CONTAINER ID   IMAGE                    COMMAND                                CREATED              STATUS 
 +1f0e6fd6d6de   phobos/debian:together   "/bin/ping -c 10 gateway.phobos.lan"   About a minute ago   Exited (0) 58 seconds ago  
 +... 
 +</code> 
 + 
 +Dans ce cas exécuter l’exécution du conteneur s'apparente à la manière d’exécuter toute autre commande: on indique le nom de la commande suivie des arguments que l'on souhaite passer à cette commande. 
 + 
 +==== Toujours utiliser la forme exec en utilisation conjointe ==== 
 + 
 +Lorsqu'on utilise **ENTRYPOINT** et **CMD** conjointement il est **impératif de toujours utiliser la forme d'invocation via exec**. Essayer d'utiliser l'invocation via shell ou de mixer les méthodes d'invocation shell/exec ne donnera pas le résultat attendu. 
 + 
 +^ Dockerfile                          ^ Commande invoquée                   | 
 +| <file> 
 +ENTRYPOINT /bin/ping -c 3 
 +CMD localhost 
 +</file>                               | %% /bin/sh -c '/bin/ping -c 3' /bin/sh -c localhost%% | 
 +| <file> 
 +ENTRYPOINT ["/bin/ping","-c","3"
 +CMD localhost 
 +</file>                               | %% /bin/ping -c 3 /bin/sh -c localhost %% | 
 +| <file> 
 +ENTRYPOINT /bin/ping -c 3 
 +CMD ["localhost"
 +</file>                               | %% /bin/sh -c '/bin/ping -c 3' localhost %% | 
 +| <file> 
 +ENTRYPOINT ["/bin/ping","-c","3"
 +CMD ["localhost"
 +</file>                               | %%  /bin/ping -c 3 localhost %% | 
 + 
 +Une seule de ces combinaisons aboutie à une ligne de commande valide: celle qui utilise les formes d'invocation **exec** à la fois pour **ENTRYPOINT et CMD**.
  
  
sysadmin/docker/cmd_vs_entrypoint.1614522245.txt.gz · Dernière modification : 2021/02/28 14:24 de 77.192.232.26