Остановите контейнер Docker от переживания своей команды docker run.

Вопрос или проблема

У меня есть стандартная система управления заданиями, которая позволяет мне запускать оболочечные скрипты в качестве заданий и завершать их по команде или когда они выполняются слишком долго.

Некоторые из моих заданий запускают контейнеры Docker в виде команды docker run -ti --rm ...... Это работает нормально в обычном режиме: я могу передавать любые ограничения по CPU и памяти Docker для применения к контейнеру, и когда контейнер завершает работу, мое задание тоже завершает работу.

Но если система управления заданиями хочет прекратить задание раньше времени, возникают проблемы. Если она просто выполнит kill -9 для процесса docker run, демон Docker этого не заметит, и контейнер продолжает работать, хотя система управления задачами считает, что задание завершено. Если она отправляет другой сигнал процессу docker run, например SIGTERM или SIGHUP, этот сигнал передается начальному процессу в контейнере. Однако из-за правил Linux о сигналах для PID 1 и того, что процесс не всегда проявляет сотрудничество/реакцию/желание остановиться при получении сигнала, это также не всегда надёжно завершает контейнер.

  1. Есть ли способ вызвать docker run так, чтобы демон обнаружил отключение подключенного клиента Docker и завершил контейнер в ответ?
  2. Существует ли конкретный сигнал, который я могу настроить в системе управления заданиями для отправки процессу docker run для корректного завершения, который приведет к завершению подключенного контейнера?

Ответ или решение

Ваша проблема с управлением остановкой контейнеров Docker с помощью системы управления заданиями вполне понятна. Давайте рассмотрим способы решения вопросов, которые были вами подняты.

  1. Обнаружение отключения клиента 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

    Таким образом, когда скрипт завершает свою работу, он может обрабатывать различные ситуации и завершать контейнер.

  2. Использование сигналов:
    Как вы упомянули, отправка определенных сигналов может не всегда приводить к надлежащему завершению работы контейнера, так как процесс с PID 1 обрабатывает сигналы иначе. Для этого в вашем сценарии следует использовать docker kill, что предоставляет возможность явно указать, какой сигнал будет отправлен контейнеру:

    docker kill --signal=SIGTERM <container_id>

    Однако вам всё равно нужно будет следить за процессами в вашей системе управления заданиями, чтобы убедиться, что у вас есть контейнер, который необходимо завершить. Если сигнал SIGTERM недостаточен, вы также можете использовать SIGKILL, но это приведет к немедленному завершению, без возможности корректного завершения процессов внутри контейнера.

Также стоит рассмотреть возможность использования библиотеки, такой как docker-py, для программного взаимодействия с Docker API из вашей системы управления заданиями. Это позволит вам более точно отслеживать состояние контейнеров и управлять ими на более высоком уровне.

В итоге, комбинируя подходы в обход управления сигналами с программным контролем за состоянием процесса, вы сможете добиться надежного управления жизненным циклом контейнеров Docker в вашей системе задач.

Оцените материал
Добавить комментарий

Капча загружается...