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

41

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

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

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

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

а также

docker exec mysupercont /path/to/myothercommand 

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

docker run ...

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

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

Корявин Иван
источник
Это очень хорошо объясненный вопрос. Смотрите другой аналогичный пост здесь .
Грант Ли
2
docker run -d --name=name container tail -f /dev/null
SteamPowered

Ответы:

46

Вам не нужно выполнять каждый раз 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               NAMES
1329c99a831b        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» для «Выполнить»

MSemochkin
источник
1
ага, я понимаю это. Вопрос был: у меня нет ничего для запуска внутри контейнера, но мне нужно держать его в состоянии «выполнения» Итак, ваш ответ - использовать bash, чтобы сохранить контейнер в рабочем состоянии?
Корявин Иван
Да. Процесс, указанный вами во время выполнения, должен выполняться, чтобы контейнер продолжал работать. Самый простой пример - bash. Возможно, вам будет проще всего запустить контейнер с "-d" и подключиться к нему при необходимости с помощью docker attach ID. Выйти из этого сеанса без окончания bash, вы можете использоватьCTRL-p CTRL-q
MSemochkin
Процесс, который вы укажете во время выполнения контейнера, получает PID 1. Соответственно, контейнер просто не может работать без него ☺
М.С.Семочкин
Мой опыт запуска и присоединения (или запуска с -ai) заключается в том, что быстрое и интерактивное редактирование вашей командной строки не отображается. Например, tty не рендерится и не повторяет.
Дламблин
1
Это изящно. Обратите внимание, что если вы хотите запустить контейнер в фоновом режиме, не запуская его вручную (скажем, если вы запускаете веб-сервис), используйте параметры '-itd' и CTRL-p CTRL-q для отсоединения без остановки контейнер.
Таранаки
6

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

Но последний комментарий Таранаки, использующий '-itd', похоже, был тем, что приказал докер.

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

Сью Паркер
источник
3
+1 "похоже, что заказал докер" :-)
Мэтт Александр
5

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

  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 обрабатывает более экзотические ошибки и переменные среды вашей бизнес-логики. Вы также можете установить некоторые ограничения, если ваши периодические задачи застряли и имеют утечки памяти или что-то еще.

elnygren
источник
0

Хвост все равно время от времени вызывает некоторые файловые операции.

Вот мое решение спать вечно, без каких-либо побочных эффектов.

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

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

while true; do :; done & # do nothing(:) in background, in an endless loop
kill -STOP $!            # stop the background process of doing nothing
wait $!                  # wait forever, because doing nothing process is stopped
qoomon
источник
1
Трудно понять, что он делает. почему бы просто не поспать 3650d
Питер
1
Вы правы, сон, вероятно, будет работать так же хорошо, как и мое решение, однако сон в конечном итоге истечет :-D PS: Я добавлю несколько комментариев, чтобы облегчить понимание моего решения.
Qoomon