Правильный способ сохранить контейнер docker запущенным, когда он используется для периодических задач

У меня есть контейнер docker с установленным и настроенным программным обеспечением.

Нет никакой программы, которая должна запускаться / запускаться постоянно.

Что я хочу - это его способность запускать какую-то команду в зависимости от внешних событий. любить:

docker exec mysupercont /path/to/mycommand -bla -for

и

docker exec mysupercont /path/to/myothercommand 

Но "exec" невозможен, когда контейнер остановлен, а также в этом контейнере есть некоторые "рабочие" данные внутри, которые используются для этих команд, поэтому я не могу использовать

docker run ...

каждый раз, потому что он воссоздает контейнер из изображения и уничтожает мои данные.

Каков "правильный" и "лучший" способ поддерживать работу такого контейнера? Какую команду я могу запустить внутри?

Вам не нужно выполнять каждый раз docker run.

docker run на самом деле это последовательность из двух команд: "создать" и "запустить".

Когда вы запускаете контейнер, вы должны указать "-it":

-i, --interactive=false Держите STDIN открытым, даже если он не подключен
-t, --tty=false Выделяют псевдо-TTY

Пример:

docker run -it debian:stable bash

После завершения работы команда, указанная при запуске (в моем примере bash). Например, вы выполняете команду "выход". Контейнерные остановки:

CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS                     PORTS               NAMES1329c99a831b        debian:stable              "bash"                 51 seconds ago      Exited (0) 1 seconds ago                       goofy_bardeen

Теперь вы можете начать все сначала

docker start 1329c99a831b

Контейнер запускается и снова выполняет команду "bash".
Подключитесь к этому сеансу "bash" с помощью команды

docker attach 1329c99a831b

Подводить итоги: вы должны понимать разницу между run и start контейнер.
Кроме того, посмотрите на документация для роли параметров "-i t" и "-d"для "Бега"

Поскольку вы упомянули периодические задачи, и вы, вероятно, используете что-то вроде cron из-за того, как вы хотите использовать docker exec У меня есть только лекарство для тебя. По крайней мере, в итоге я сделал что-то подобное.

  1. Файл Dockerfile

    FROM <some base>CMD tail -f /dev/null
  2. Бегите с обычным docker run -d .... (Я использовал docker-compose)

  3. Настройка crontab хост-компьютеров, например:

    * * * * * docker exec mysupercont foo >> /var/log/foo.log 2>&1* * * * * docker exec mysupercont bar >> /var/log/bar.log 2>&1

Я нахожу это решение приятным, поскольку мы можем полагаться на древний и проверенный crontab в довольно стандартной среде Linux, в то время как Docker обрабатывает более экзотические deps и переменные среды вашей бизнес-логики. Вы также можете установить некоторые ограничения, если ваши периодические задачи застревают, возникают утечки памяти или что-то еще.

Tail по-прежнему будет время от времени вызывать некоторые файловые операции.

Спи вечно, без каких-либо побочных эффектов

# Ah, ha, ha, ha, stayin' alive...while :; do :; done & kill -STOP $! && wait $!

Как это работает

while :;           # Run an endless loop,do :;              # of do nothing,done &             # as background task.kill -STOP $!      # Stop the background task.wait $!            # Wait forever, because background task process has been stopped.

Весь этот вопрос о том, можете ли вы запустить остановленный контейнер или нет, зависит от того, как контейнер был первоначально создан, т.Е. запущен. Если вы выполнили завершившуюся команду или завершили интерактивную команду, например bash, вы не сможете запустить, перезапустить или выполнить остановленный контейнер. Все, что вы можете сделать, это удалить его. Это мусор.

Но последний комментарий таранаки, use '-itd', похоже, соответствует приказу докера.

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

Я сам использовал все предложенные здесь решения, но все они не обрабатывают сигналы SIGTERM, поступающие от демона Docker, когда он хочет закрыть контейнер (например docker stop $containername).

Поэтому я предлагаю следующее:

FROM base:image# ...CMD sh -c 'trap "exit" TERM; while true; do sleep 1; done'

По сути, это короткий сценарий оболочки, который сначала перехватывает ("ловушки") SIGTERM подает сигнал, а затем переходит в спящий режим на секунду в бесконечном цикле.

Я в основном использую его вместе с docker-compose и Офелия для предоставления контейнеров с боковыми вагонами для резервного копирования какой-либо другой службы в другом контейнере (например, базы данных MariaDB).

docker run -d --name=хвост контейнера имени -f /dev/null

Это очень хорошо объясненный вопрос. Смотрите другой подобный пост here.