Como posso impedir que um contêiner do docker execute o sono?

0

sleep é um substituto para processos mais complexos, é claro.

Este Dockerfile (como você pode ver usando o formulário exec para que haja apenas um processo em execução e nenhum filho de bash ):

FROM busybox
CMD ["/bin/sleep", "100000"]

cria um contêiner ininterrupto:

docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep

Quando tento pará-lo:

time docker stop kill-sleep

kill-sleep
real    0m10.449s
user    0m0.021s
sys     0m0.027s

o comando expira 10 segundos antes de o contêiner ser eliminado.

O problema não é que sleep não manipula sinais, porque se eu o executo no host:

sleep 100000
# in another shell
ps faxww | grep sleep
kill -TERM 31333  # the PID

o processo pára imediatamente.

O problema pode estar relacionado ao fato de que isso está sendo executado como PID 1 no contêiner, mas ainda não vi uma documentação de referência para isso.

    
por giorgiosironi 01.03.2018 / 12:16

1 resposta

3

Quando você executar docker stop ... , algumas coisas acontecerão :

  1. docker envia um SIGTERM para o processo principal do contêiner. O processo é capaz de mascarar / ignorar um SIGTERM e, se o fizer (ou manuseá-lo sem terminar), " nada " acontecerá.
  2. Após um tempo limite (padrão de 10 segundos), docker envia um SIGKILL 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
    
por 01.03.2018 / 12:25

Tags