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