J'ai remarqué que beaucoup de scripts entrypoint.sh pour docker font quelque chose comme ceci:
#!/bin/bash
set -e
... code ...
exec "$@"
Quels sont les set -e
et le exec "$@"
pour?
Il prend fondamentalement tous les arguments de ligne de commande supplémentaires et les exécute en tant que commande. L'intention est fondamentalement "Tout faire dans ce script .sh, puis dans le même shell, exécutez la commande que l'utilisateur transmet sur la ligne de commande".
Voir:
set -e
- script de sortie si une commande échoue (valeur différente de zéro)
exec "$@"
- redirigera les variables d’entrée, voir plus ici
set -e
définit une option Shell à quitter immédiatement si une commande en cours d'exécution quitte avec un code de sortie différent de zéro. Le script renverra avec le code de sortie de la commande ayant échoué. De la page de manuel de bash:
set -e:
Quittez immédiatement si un pipeline (qui peut consister en une seule commande simple), une liste ou une commande composée (voir Shell GRAMMAR ci-dessus) se ferme avec un statut différent de zéro. Le shell ne se ferme pas si la commande qui échoue fait partie de la liste des commandes immédiatement après un mot-clé while ou Until, une partie du test suivant les mots réservés if ou Elif, une partie de toute commande exécutée dans un && ou || list excepté la commande suivant le && ou || final, toutes les commandes d’un pipeline sauf le dernier, ou si la valeur de retour de la commande est inversée avec!. Si une commande composée autre qu'un sous-shell renvoie un statut différent de zéro car une commande a échoué alors que l'option -e était ignorée, le shell ne se ferme pas. Une interruption sur ERR, si elle est définie, est exécutée avant la fermeture du shell. Cette option s'applique à l'environnement Shell et à chaque environnement de sous-shell séparément (voir ENVIRONNEMENT D'EXÉCUTION DE COMMANDE ci-dessus), et peut entraîner la fermeture des sous-shell avant l'exécution de toutes les commandes du sous-shell.
Si une commande composée ou une fonction Shell s'exécute dans un contexte où -e est ignoré, aucune des commandes exécutées dans la commande composée ou le corps de la fonction ne sera affectée par le paramètre -e, même si -e est défini et qu'une commande renvoie un état d'échec. Si une commande composée ou une fonction Shell définit -e lors de l'exécution dans un contexte où -e est ignoré, ce paramètre n'aura aucun effet tant que la commande composée ou la commande contenant l'appel de fonction ne sera pas terminée.
exec "$@"
est généralement utilisé pour faire en sorte que le point d’entrée passe par la commande docker. Il remplacera le shell en cours d’exécution par la commande "$@"
pointe vers. Par défaut, cette variable pointe sur les arguments de la ligne de commande.
Si vous avez une image avec un point d’entrée pointant sur entrypoint.sh, et que vous exécutez votre conteneur en tant que docker run my_image server start
, cela se traduira par l'exécution de entrypoint.sh server start
dans le conteneur. À la ligne de l'exécutif entrypoint.sh
, le shell s'exécutant en tant que pid 1 se remplacera par la commande server start
.
Ceci est essentiel pour la gestion du signal. Sans utiliser exec
, le server start
dans l'exemple ci-dessus serait exécuté comme un autre pid et, une fois sorti, vous retourneriez à votre script Shell. Avec un shell dans le pid 1, un SIGTERM sera ignoré par défaut. Cela signifie que le signal d'arrêt gracieux que docker stop
_ envoie à votre conteneur, ne serait jamais reçu par le processus server
. Après 10 secondes (par défaut), docker stop
abandonnerait l’arrêt gracieux et enverrait un SIGKILL qui forcerait la fermeture de votre application, mais en cas de perte de données ou de connexions réseau fermées, les développeurs d’applications auraient pu coder s’ils avaient reçu le signal. Cela signifie également que votre conteneur prendra toujours les 10 secondes pour s'arrêter.
Notez qu'avec les commandes Shell comme shift
et set --
, vous pouvez modifier la valeur de "$@"
. Par exemple. voici une courte partie d'un script qui supprime le /bin/sh -c "..."
de la commande pouvant apparaître si vous utilisez la syntaxe Shell de docker pour CMD
:
# convert `/bin/sh -c "server start"` to `server start`
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then
shift 2
eval "set -- $1"
fi
....
exec "$@"