Lorsque vous exécutez docker stop ...
, certaines choses vont se produire :
-
docker
envoie un SIGTERM
au processus principal du conteneur. Le processus est capable de masquer/ignorer un fichier SIGTERM
et s'il le fait (ou le traite sans s'arrêter) " rien " se produira.
- Après un délai d'attente (10 secondes par défaut),
docker
envoie un SIGKILL
au processus principal. Ce signal ne peut pas être masqué par un processus, et donc il meurt immédiatement sans possibilité d'exécuter une procédure d'arrêt.
Idéalement, les processus sont exécutés dans docker
répondra à la SIGTERM
en temps voulu, en s'occupant de tout le ménage avant de terminer.
Si vous savez que le processus n'a pas de tâches ménagères à effectuer (par ex : sleep
), ou ne répondra pas correctement à SIGTERM
vous pouvez spécifier un délai plus court (ou plus long) avec l'option -t
drapeau :
-t, --time=10
Seconds to wait for stop before killing it
Par exemple, dans votre cas, vous voudrez peut-être exécuter docker stop -t 0 ${CONTAINER}
.
La raison pour laquelle le comportement de ce signal est différent est due à la sleep
fonctionnant avec PID = 1.
Typiquement (par exemple : exécution avec PID != 1), tout signal que le processus ne traite pas explicitement conduit à la fin du processus - essayez d'envoyer un signal sleep
a SIGUSR1
.
Cependant, lorsqu'il est exécuté avec PID = 1, les signaux non gérés sont ignorés, sinon vous vous retrouveriez avec une panique du noyau :
Kernel panic - not syncing: Attempted to kill init!
Vous pouvez envoyer un signal au conteneur docker en utilisant les outils docker, par exemple :
docker kill -s TERM kill-sleep
Comme on peut le voir, ceci n'a pas l'effet désiré, alors que ceci le fait :
docker kill -s KILL kill-sleep
Une expérience
Dockerfile
FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
run.sh
#!/bin/sh
echo "sleeping"
sleep 100000
Maintenant, exécutez
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
Et ceci dans un terminal différent :
docker stop kill-sleep
Nous observons le même délai / timeout de 10 secondes.
Une solution
Maintenant, nous allons gérer le SIGTERM
. Mise en contexte et wait
pour sleep
sont dues à la façon dont un Shell POSIX gère les signaux (voir ce pour en savoir plus).
run.sh
#!/bin/sh
die_func() {
echo "oh no"
sleep 2
exit 1
}
trap die_func TERM
echo "sleeping"
sleep 100000 &
wait
Exécutez à nouveau les commandes, et nous voyons ce que nous recherchons !
$ time docker stop kill-sleep
kill-sleep
real 0m2.515s
user 0m0.008s
sys 0m0.044s