Вопрос или проблема
У меня есть стандартная система управления заданиями, которая позволяет мне запускать оболочечные скрипты в качестве заданий и завершать их по команде или когда они выполняются слишком долго.
Некоторые из моих заданий запускают контейнеры Docker в виде команды docker run -ti --rm .....
. Это работает нормально в обычном режиме: я могу передавать любые ограничения по CPU и памяти Docker для применения к контейнеру, и когда контейнер завершает работу, мое задание тоже завершает работу.
Но если система управления заданиями хочет прекратить задание раньше времени, возникают проблемы. Если она просто выполнит kill -9
для процесса docker run
, демон Docker этого не заметит, и контейнер продолжает работать, хотя система управления задачами считает, что задание завершено. Если она отправляет другой сигнал процессу docker run
, например SIGTERM или SIGHUP, этот сигнал передается начальному процессу в контейнере. Однако из-за правил Linux о сигналах для PID 1 и того, что процесс не всегда проявляет сотрудничество/реакцию/желание остановиться при получении сигнала, это также не всегда надёжно завершает контейнер.
- Есть ли способ вызвать
docker run
так, чтобы демон обнаружил отключение подключенного клиента Docker и завершил контейнер в ответ? - Существует ли конкретный сигнал, который я могу настроить в системе управления заданиями для отправки процессу
docker run
для корректного завершения, который приведет к завершению подключенного контейнера?
Ответ или решение
Ваша проблема с управлением остановкой контейнеров Docker с помощью системы управления заданиями вполне понятна. Давайте рассмотрим способы решения вопросов, которые были вами подняты.
-
Обнаружение отключения клиента Docker:
Docker не предоставляет встроенной возможности для автоматического завершения контейнера при отключении клиента, который запустилdocker run
. Однако можно использовать дополнительные инструменты или подходы для решения этой проблемы. Один из вариантов – это запуск контейнера внутри специального управляющего скрипта или программы, которая будет отслеживать состояние работы и завершать контейнер при необходимости. Вы можете написать обертку на Bash, которая будет отслеживать PID процесса и завершать контейнер, если процессdocker run
прекращает работу или получает сигнал завершения:#!/bin/bash docker run -ti --rm ... & DOCKER_PID=$! wait $DOCKER_PID exit_status=$? if [ $exit_status -ne 0 ]; then echo "Docker container failed with status $exit_status" fi
Таким образом, когда скрипт завершает свою работу, он может обрабатывать различные ситуации и завершать контейнер.
-
Использование сигналов:
Как вы упомянули, отправка определенных сигналов может не всегда приводить к надлежащему завершению работы контейнера, так как процесс с PID 1 обрабатывает сигналы иначе. Для этого в вашем сценарии следует использоватьdocker kill
, что предоставляет возможность явно указать, какой сигнал будет отправлен контейнеру:docker kill --signal=SIGTERM <container_id>
Однако вам всё равно нужно будет следить за процессами в вашей системе управления заданиями, чтобы убедиться, что у вас есть контейнер, который необходимо завершить. Если сигнал
SIGTERM
недостаточен, вы также можете использоватьSIGKILL
, но это приведет к немедленному завершению, без возможности корректного завершения процессов внутри контейнера.
Также стоит рассмотреть возможность использования библиотеки, такой как docker-py
, для программного взаимодействия с Docker API из вашей системы управления заданиями. Это позволит вам более точно отслеживать состояние контейнеров и управлять ими на более высоком уровне.
В итоге, комбинируя подходы в обход управления сигналами с программным контролем за состоянием процесса, вы сможете добиться надежного управления жизненным циклом контейнеров Docker в вашей системе задач.