Когда вы запустите docker stop ...
, произойдут некоторые вещи:
docker
отправляет SIGTERM
в основной процесс контейнера.
Процесс может маскировать / игнорировать SIGTERM
, и если он это делает (или обрабатывает без прерывания), « ничего » не произойдет.
- По истечении времени ожидания (по умолчанию 10 секунд)
docker
отправляет SIGKILL
основному процессу. Этот сигнал не может быть замаскирован процессом, и, таким образом, он немедленно умирает, не имея возможности выполнить процедуру выключения.
В идеале процессы, выполняемые в docker
будут своевременно реагировать на SIGTERM
, заботясь о любом ведении домашнего хозяйства до его завершения.
Если вы знаете, что процесс либо не выполняет какие-либо служебные действия (например, sleep
), либо не будет правильно отвечать на SIGTERM
, вы можете указать более короткий (или более длинный) тайм-аут с флагом -t
:
-t, --time=10
Seconds to wait for stop before killing it
Например, в вашем случае вы можете запустить docker stop -t 0 ${CONTAINER}
.
Причина, по которой это поведение сигнала отличается, заключается в том, что sleep
работает с PID = 1.
Обычно (например: работает с PID!= 1), любой сигнал, с которым процесс явно не имеет дело, приводит к его завершению - попробуйте отправить sleep
в SIGUSR1
режим.
Однако при работе с PID = 1 необработанные сигналы игнорируются, в противном случае вы получите панику ядра:
Kernel panic - not syncing: Attempted to kill init!
Вы можете отправить сигнал в Docker-контейнер с помощью инструментов Docker, например:
docker kill -s TERM kill-sleep
Как мы видим, это не дает желаемого эффекта, тогда как это:
docker kill -s KILL kill-sleep
Эксперимент
Dockerfile
FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
run.sh
#!/bin/sh
echo "sleeping"
sleep 100000
Теперь беги
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
И это в другом терминале:
docker stop kill-sleep
Мы наблюдаем ту же 10-секундную задержку / тайм-аут.
Решение
Теперь давайте разберемся с SIGTERM
. Фоновая обработка и wait
sleep
связаны с тем, как оболочка POSIX обрабатывает сигналы (подробнее об этом ).
run.sh
#!/bin/sh
die_func() {
echo "oh no"
sleep 2
exit 1
}
trap die_func TERM
echo "sleeping"
sleep 100000 &
wait
Запустите команды еще раз, и мы увидим, что нам нужно!
$ time docker stop kill-sleep
kill-sleep
real 0m2.515s
user 0m0.008s
sys 0m0.044s