докер запустить скрипт в фоновом режиме без выхода из контейнера

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

когда я запускаю следующую команду,

docker run image:tag /bin/sh /root/my_script.sh

и

docker ps -a

Я вижу, что команда вышла. Но это не то, чего я хочу. Мой вопрос в том, как позволить команде работать в фоновом режиме не выходя?

4 ответов


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

контейнер docker выходит, как только контейнер CMD выход. Если вы хотите, чтобы ваш контейнер продолжал работать, вам понадобится процесс, который будет продолжать работать. Один из вариантов-просто поместить цикл while в конец вашего скрипта:

while :; do
  sleep 300
done

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

если вместо этого ваш скрипт неожиданно выходит, вам, вероятно, нужно будет взглянуть на ваши журналы контейнеров (docker logs <container>) и, возможно, добавить некоторые отладки скрипта.

если вы просто спрашиваете: "как мне запустить контейнер в фоновом режиме?", тогда ответ Эмиля (передайте -d флаг docker run) поможет вам.


процесс, который запускает docker, занимает место init в дереве процессов UNIX. init является самым верхним родительским процессом, и после его выхода контейнер docker останавливается. Любой дочерний процесс (теперь процесс-сирот) также будет остановлен.

$ docker pull busybox >/dev/null
$ time docker run --rm busybox sleep 3

real    0m3.852s
user    0m0.179s
sys 0m0.012s

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

$ time docker run --rm busybox sh -c 'sleep 3 & wait'

real    0m3.916s
user    0m0.178s
sys 0m0.013s

...или вы можете заменить родительский процесс дочерним процессом с помощью exec. Это означает, что команда выполняется в пространстве родительского процесса...

$ time docker run --rm busybox sh -c 'exec sleep 3'

real    0m3.886s
user    0m0.173s
sys 0m0.010s

этот последний подход может быть сложным в зависимости от характера процесса ребенка, но имеют меньше лишних запущенные процессы более идиоматично Docker. (Это не значит, что ты должен только когда-либо иметь один


запустите контейнер с вашим скриптом в фоновом режиме с помощью команды

docker run -i -t -d  image:tag /bin/sh /root/my_script.sh

Проверьте идентификатор контейнера по docker ps команда

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

docker exec <id> /bin/sh -l -c "ps aux"

оберните программу с помощью docker-entrypoint.sh сценарий bash, который блокирует процесс контейнера и может поймать ctrl-C. Этот пример bash должен помочь: https://rimuhosting.com/knowledgebase/linux/misc/trapping-ctrl-c-in-bash

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

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