Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
sysadmin:docker:cmd_vs_entrypoint [2021/02/28 14:24] – créée 77.192.232.26 | sysadmin:docker:cmd_vs_entrypoint [2021/12/30 00:18] (Version actuelle) – yoann | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | {{tag> | + | {{tag> |
- | ====== Docker: | + | ====== 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' | ||
+ | |||
+ | Ces deux directives existent et présentent quelques différences. Selon les besoins on utilisera l'une, l' | ||
+ | |||
+ | Au final, **CMD** ou **ENTRYPOINT** permet d' | ||
+ | |||
+ | 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 | ||
+ | </ | ||
+ | |||
+ | |||
+ | < | ||
+ | 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' | ||
+ | </ | ||
+ | |||
+ | 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' | ||
+ | <code bash> | ||
+ | docker run --rm --name test_cmd -t busybox: | ||
+ | PING localhost (127.0.0.1): | ||
+ | 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, | ||
+ | round-trip min/avg/max = 0.056/ | ||
+ | </ | ||
+ | |||
+ | On peut également redéfinir la valeur de l' ENTRYPOINT via l' | ||
+ | |||
+ | <code bash> | ||
+ | docker run --rm --name test_cmd --entrypoint hostname -t busybox: | ||
+ | 636ecd585d67 | ||
+ | </ | ||
+ | |||
+ | Comme il est plus simple pour l' | ||
+ | |||
+ | Au contraire la directive **ENTRYPOINT** s' | ||
+ | |||
+ | La même chose est faisable avec la directive **CMD** cependant l' | ||
+ | |||
+ | ===== Shell vs Exec ===== | ||
+ | |||
+ | Les directives **CMD** et **ENTRYPOINT** supportent les deux formes d' | ||
+ | |||
+ | Dans l' | ||
+ | < | ||
+ | FROM debian: | ||
+ | RUN apt-get update && apt-get install -y iputils-ping procps | ||
+ | |||
+ | # Syntaxe pour invocation type shell | ||
+ | CMD ping localhost | ||
+ | </ | ||
+ | |||
+ | Si on crée l' | ||
+ | <code bash> | ||
+ | # création de l' | ||
+ | docker image build -t " | ||
+ | |||
+ | # Création d'un conteneur utilisant cette image | ||
+ | docker container run --rm --detach --name debian_shell phobos/ | ||
+ | |||
+ | # 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 | ||
+ | 886ab5702130 | ||
+ | |||
+ | # Si on affiche les processus s' | ||
+ | docker container exec debian_shell ps -f | ||
+ | UID PID PPID C STIME TTY TIME CMD | ||
+ | root | ||
+ | root | ||
+ | root | ||
+ | </ | ||
+ | |||
+ | 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' | ||
+ | |||
+ | Une meilleure option est donc d' | ||
+ | |||
+ | Pour notre exemple le Dockerfile prend alors la forme suivante: | ||
+ | |||
+ | < | ||
+ | FROM debian: | ||
+ | RUN apt-get update && apt-get install -y iputils-ping procps | ||
+ | |||
+ | # Syntaxe pour invocation type exec | ||
+ | CMD ["/ | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Construction d'une nouvelle image | ||
+ | | ||
+ | |||
+ | # Création du conteneur avec la nouvelle image | ||
+ | docker container run --detach --rm --name debian_exec phobos/ | ||
+ | |||
+ | # affiche les processus en cours d' | ||
+ | # visibles depuis l’intérieur du conteneur | ||
+ | docker container exec debian_exec ps -f | ||
+ | UID PID PPID C STIME TTY TIME CMD | ||
+ | root | ||
+ | root | ||
+ | </ | ||
+ | |||
+ | Cette fois on voit que la commande s’exécute directement sans intervention intermédiaire du shell avec le PID 1. | ||
+ | |||
+ | < | ||
+ | Quelle que soit la directive **CMD** ou **ENTRYPOINT** la recommandation générale est d' | ||
+ | </ | ||
+ | |||
+ | ===== Utilisation conjointe ===== | ||
+ | |||
+ | Jusqu' | ||
+ | |||
+ | La combinaison des directives | ||
+ | |||
+ | < | ||
+ | RUN apt-get update && apt-get install -y iputils-ping procps | ||
+ | |||
+ | # Binaire et options non modifiables | ||
+ | ENTRYPOINT ["/ | ||
+ | |||
+ | # Arguments et options redéfinissables | ||
+ | # facilement par l' | ||
+ | CMD [" | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Création d'une nouvelle image | ||
+ | docker image build -t " | ||
+ | |||
+ | # Création et exécution d'un conteneur basé sur la nouvelle | ||
+ | docker container run --rm --name test_together -t phobos/ | ||
+ | |||
+ | docker container ps -a | ||
+ | CONTAINER ID | ||
+ | 14dcebd6b360 | ||
+ | </ | ||
+ | |||
+ | 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' | ||
+ | |||
+ | Dans l' | ||
+ | être remplacé à l' | ||
+ | |||
+ | <code bash> | ||
+ | # Création d'un conteneur avec redéfinition des arguments par défaut | ||
+ | docker container run phobos/ | ||
+ | |||
+ | # Liste les conteneurs existants | ||
+ | docker container ps -a | ||
+ | CONTAINER ID | ||
+ | 1f0e6fd6d6de | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | Dans ce cas exécuter l’exécution du conteneur s' | ||
+ | |||
+ | ==== Toujours utiliser la forme exec en utilisation conjointe ==== | ||
+ | |||
+ | Lorsqu' | ||
+ | |||
+ | ^ Dockerfile | ||
+ | | < | ||
+ | ENTRYPOINT /bin/ping -c 3 | ||
+ | CMD localhost | ||
+ | </ | ||
+ | | < | ||
+ | ENTRYPOINT ["/ | ||
+ | CMD localhost | ||
+ | </ | ||
+ | | < | ||
+ | ENTRYPOINT /bin/ping -c 3 | ||
+ | CMD [" | ||
+ | </ | ||
+ | | < | ||
+ | ENTRYPOINT ["/ | ||
+ | CMD [" | ||
+ | </ | ||
+ | |||
+ | Une seule de ces combinaisons aboutie à une ligne de commande valide: celle qui utilise les formes d' | ||