В этом есть пара мелких деталей, которые имеют значение.
Наиболее важным является то, что при отправке Ctrl + C на передний план docker-compose up
, это эквивалентно docker-compose stop
, что, в свою очередь, эквивалентно docker stop
. Это посылает SIGTERM
, а не SIGINT
. Поможет изменить линию trap
, чтобы поймать правильный сигнал.
При экспериментировании с этим после отправки Ctrl + C, docker-compose up
остановит печать контейнера вывода. Он все еще генерируется, и вы все равно можете увидеть его с помощью docker-compose logs web
.
Этот скрипт, кажется, выполняет много вещей в фоновом режиме, которые ему не нужны, и еще одну вещь меня бросает в глаза то, что ваша int_handler
функция запускает фоновый процесс, как только контейнер собирается выйти. Это также имеет анти-паттерн запуска tail -f
«для поддержания контейнера в живых», в то время как ваше приложение работает как побочный эффект.
Я получил разумное поведение от этой модификации вашего скрипт:
#!/bin/sh
int_handler() {
echo "int_handler"
# node deactivator
# forcibly exit the script (and the container)
exit 0
}
# trap SIGTERM here, not SIGINT
trap int_handler SIGTERM
echo start
# run the CMD from the Dockerfile or the `docker run` command
"$@" &
# wait for that process to exit
# (don't start an artificial `tail -f`)
# (you must `wait` or else the signal is delayed until
# the process exits on its own)
wait $!
и соответствующий тривиальный Dockerfile
:
FROM alpine
COPY script /
ENTRYPOINT ["/script"]
CMD ["sleep", "15"]
Если функция trap
не exit
, то что-либо в скрипте точки входа после финального wait
выполнит. Вы можете использовать это, если вы хотите безоговорочно очистить. Этот вариант всегда печатает stop
, даже если вы docker stop
контейнер, и завершается со статусом выхода из сценария.
#!/bin/sh
trap 'kill $pid' SIGTERM
echo start
"$@" &
pid=$!
wait $pid
rc=$?
echo stop
exit $rc