Quando você executar docker stop ...
, algumas coisas acontecerão :
-
docker
envia umSIGTERM
para o processo principal do contêiner. O processo é capaz de mascarar / ignorar umSIGTERM
e, se o fizer (ou manuseá-lo sem terminar), " nada " acontecerá. - Após um tempo limite (padrão de 10 segundos),
docker
envia umSIGKILL
para o processo principal. Esse sinal não pode ser mascarado por um processo e, portanto, morre imediatamente, sem oportunidade de executar um processo de desligamento.
De maneira ideal, os processos executados em docker
responderão ao SIGTERM
em tempo hábil, cuidando de qualquer serviço de limpeza antes de finalizar.
Se você sabe que o processo não tem nenhuma manutenção para executar (por exemplo: sleep
) ou não responderá corretamente a SIGTERM
, você pode especificar um tempo limite menor (ou maior) com o -t
flag:
-t, --time=10 Seconds to wait for stop before killing it
Por exemplo, no seu caso, você pode gostar de executar docker stop -t 0 ${CONTAINER}
.
O motivo pelo qual esse comportamento do sinal é diferente é devido ao sleep
executando com PID = 1.
Normalmente (por exemplo, executando com PID! = 1), qualquer sinal com o qual o processo não lide explicitamente leva ao processo sendo finalizado - tente enviar um sleep
a SIGUSR1
.
No entanto, quando executando com PID = 1, os sinais não manipulados são ignorados, caso contrário, você acabaria com um pânico no kernel:
Kernel panic - not syncing: Attempted to kill init!
Você pode enviar um sinal para o contêiner docker usando ferramentas docker, por exemplo:
docker kill -s TERM kill-sleep
Como podemos ver, isso não tem o efeito desejado, enquanto isso acontece:
docker kill -s KILL kill-sleep
Uma experiência
Dockerfile
FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
run.sh
#!/bin/sh
echo "sleeping"
sleep 100000
Agora, corra
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
E isso em um terminal diferente:
docker stop kill-sleep
Observamos o mesmo atraso / tempo de espera de 10 segundos.
Uma solução
Agora vamos lidar com o SIGTERM
. Backgrounding e wait
ing para sleep
são devidos a como uma shell POSIX lida com sinais (veja this para mais).
run.sh
#!/bin/sh
die_func() {
echo "oh no"
sleep 2
exit 1
}
trap die_func TERM
echo "sleeping"
sleep 100000 &
wait
Execute os comandos novamente e vemos o que procuramos!
$ time docker stop kill-sleep
kill-sleep
real 0m2.515s
user 0m0.008s
sys 0m0.044s