Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente | |||
technique:docker:good_practices:multi [2020/10/13 16:02] – [Entrypoint qui lance plusieurs services] qduchemi | technique:docker:good_practices:multi [2022/05/24 20:58] (Version actuelle) – ppom | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | {{indexmenu_n> | ||
+ | # Gérer proprement son script d' | ||
+ | |||
+ | Une pratique commune est d' | ||
+ | |||
+ | ## Entrypoint qui lance un unique processus | ||
+ | |||
+ | ### Situation | ||
+ | |||
+ | Dans ce cas, le `Dockerfile` spécifie : | ||
+ | |||
+ | * Une instruction `ENTRYPOINT` associée à un script shell | ||
+ | * Une instruction `CMD`, passée en arguments de l' | ||
+ | |||
+ | L' | ||
+ | |||
+ | Traditionnellement, | ||
+ | |||
+ | < | ||
+ | Quels sont les risques ? | ||
+ | </ | ||
+ | |||
+ | ### Problématique | ||
+ | |||
+ | Les scripts ne transmettent pas les signaux à leurs enfants (voir [[technique: | ||
+ | |||
+ | < | ||
+ | |||
+ | Supposons un Dockerfile du style : | ||
+ | |||
+ | ``` | ||
+ | FROM debian: | ||
+ | ... | ||
+ | ENTRYPOINT [ "/ | ||
+ | # Notez qu'on lance nginx en premier plan | ||
+ | CMD [ " | ||
+ | ``` | ||
+ | |||
+ | Avec un entrypoint du style : | ||
+ | |||
+ | ```bash | ||
+ | #!/bin/sh | ||
+ | |||
+ | # Injection de secrets | ||
+ | sed [...] | ||
+ | |||
+ | # Démarrage de nginx | ||
+ | $@ | ||
+ | ``` | ||
+ | |||
+ | < | ||
+ | |||
+ | Dans ce cas, la situation ressemble à ceci : | ||
+ | |||
+ | ``` | ||
+ | NOM PID | ||
+ | entrypoint.sh | ||
+ | |__nginx | ||
+ | ``` | ||
+ | |||
+ | Comme nous venons de le voir, tout signal envoyé au conteneur arrivera à l' | ||
+ | |||
+ | < | ||
+ | |||
+ | ### Utiliser exec | ||
+ | |||
+ | Le comportement désiré serait d' | ||
+ | |||
+ | On remplace l' | ||
+ | |||
+ | ```bash | ||
+ | #!/bin/sh | ||
+ | |||
+ | # Injection de secrets | ||
+ | sed [...] | ||
+ | |||
+ | # Démarrage de nginx | ||
+ | exec $@ | ||
+ | ``` | ||
+ | |||
+ | Après exécution de l' | ||
+ | |||
+ | ``` | ||
+ | NOM PID | ||
+ | nginx 1 | ||
+ | ``` | ||
+ | |||
+ | L' | ||
+ | |||
+ | ## Entrypoint qui lance plusieurs services | ||
+ | |||
+ | < | ||
+ | |||
+ | Un entrypoint qui lance plusieurs services pourrait ressembler à ceci : | ||
+ | |||
+ | ```bash | ||
+ | #!/bin/sh | ||
+ | |||
+ | # Injection de secrets | ||
+ | sed [...] | ||
+ | |||
+ | # Lancement de PHP en arrière plan | ||
+ | php-fpm & | ||
+ | |||
+ | # Lancement de nginx en premier plan | ||
+ | exec nginx -g ' | ||
+ | ``` | ||
+ | |||
+ | Après lancement, la situation est la suivante : | ||
+ | |||
+ | ``` | ||
+ | NOM PID | ||
+ | nginx 1 | ||
+ | |__php-fpm | ||
+ | ``` | ||
+ | |||
+ | Pourquoi ? Tout simplement parce que `nginx` s'est substitué au shell via `exec`, **mais** il a aussi hérité des processus enfants du shell, comme `php-fpm`. | ||
+ | |||
+ | Ici, on se retrouve avec une problématique similaire : `nginx` va bien recevoir les signaux, mais ne les transmet pas à ses enfants. Et pour le coup, on ne peut pas ré-utiliser un `exec`, car `nginx` a toujours besoin de s' | ||
+ | |||
+ | Dans ce cas précis, il va falloir utiliser des astuces plus ou moins sales. | ||
+ | |||
+ | < | ||
+ | |||
+ | En gros, il y a deux solutions : | ||
+ | |||
+ | * Utiliser [supervisord](http:// | ||
+ | * Faire du cas par cas. Par exemple, si on sait qu'un processus enfant doit pouvoir recevoir un signal important, qu'on connaît à l' | ||
+ | |||
+ | Les trap sont des *handlers* de signaux. On ne développe pas ce point, mais c'est la solution retenue pour [Mumble](https:// | ||
+ | |||
+ | Voici un extrait de son entrypoint : | ||
+ | |||
+ | ```bash | ||
+ | python3 / | ||
+ | |||
+ | # Trap SIGUSR1 signal to reload certificates without restarting | ||
+ | _reload() { | ||
+ | echo " | ||
+ | / | ||
+ | wait | ||
+ | } | ||
+ | trap _reload SIGUSR1 | ||
+ | |||
+ | # Run murmur | ||
+ | murmurd -v -ini $CONFIG_FILE | ||
+ | wait | ||
+ | ``` | ||
+ | |||
+ | < | ||
+ | |||
+ | < | ||
+ | |||
+ | ## Est-ce-que c'est suffisant ? | ||
+ | |||
+ | Dans cette page, nous avons montré comment faire en sorte que les processus d'un conteneur Docker reçoivent les signaux qui leur sont destinés. | ||
+ | |||
+ | En revanche, ca ne règle pas tous les problèmes, car les processus qui ont un PID 1 sont traités spécialement. | ||
+ | |||
+ | < | ||