Docker-контейнер автоматически остановится после «docker run -d»


333

В соответствии с руководством, которое я прочитал, использование " docker run -d" запустит контейнер из изображения, и контейнер будет работать в фоновом режиме. Вот как это выглядит, мы можем видеть, что у нас уже есть идентификатор контейнера.

root@docker:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

Но если я побежал " docker ps", ничего не вернулось.

Итак, я попытался " docker ps -a", я вижу контейнер уже вышел:

root@docker:/home/root# docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                         PORTS               NAMES
605e3928cddd        centos:latest         "/bin/bash"         31 minutes ago      Exited (0) 31 minutes ago                          kickass_swartz

Что-то я не так сделал? Как я могу устранить эту проблему?


1
«docker run hello-world» <== работает отлично, но если я запускаю «docker run -d hello-world», я все равно не могу получить работающий контейнер.
— Джон Джон

5
У меня была похожая проблема, но я заставил ее работать, используя docker run -it -d <image> /bin/bashэто, запускает командную оболочку в интерактивном режиме и не закрывает контейнер, потому что процесс оболочки активен.
— Rtsne42

Ответы:


495

CentOS dockerfile имеет команду по умолчанию bash.

Это означает, что при запуске в background ( -d) оболочка немедленно завершается.

Обновление 2017

Более поздние версии DOCKER Авторизуйтесь , чтобы запустить контейнер как в отдельном режиме и в режиме переднего плана ( -t, -iили -it)

В этом случае вам не нужны никакие дополнительные команды, и этого достаточно:

docker run -t -d centos

Баш будет ждать в фоновом режиме.
Это было первоначально сообщалось в Кальяни-Chaudhari «s ответ и подробно описано в джерси боб » ы ответ .

vonc@voncvb:~$ d ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4a50fd9e9189        centos              "/bin/bash"         8 seconds ago       Up 2 seconds                            wonderful_wright

Обратите внимание, что для альпийских , Marinos An сообщает в комментариях :

docker run -t -d alpine/gitне поддерживает процесс.
Должен сделать:docker run --entrypoint "/bin/sh" -it alpine/git


Оригинальный ответ (2015)

Как уже упоминалось в этой статье :

Вместо запуска с docker run -i -t image your-commandиспользованием -dрекомендуется использовать, потому что вы можете запустить свой контейнер с помощью только одной команды, и вам не нужно отсоединять терминал контейнера, нажав Ctrl+ P+ Q.

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

Проблема в том, что некоторые приложения не работают на переднем плане. Как мы можем сделать это проще?

В этой ситуации вы можете добавить tail -f /dev/nullв свою команду.
При этом, даже если ваша основная команда выполняется в фоновом режиме, ваш контейнер не останавливается, потому что tail продолжает работать на переднем плане.

Так что это будет работать:

docker run -d centos tail -f /dev/null

А docker psпокажет контейнер с центосом, все еще работающий.

Оттуда вы можете присоединиться к нему или отсоединиться от него (или docker execнекоторых команд).


Извините, еще один вопрос, у меня есть сценарий, который нужно запустить при запуске, похоже, что /etc/rc.d/rc.local больше не работает (мое мышление все еще рассматривает Docker как ОС), я предполагаю, что файл Docker является лучшим вариантом в этом кейс?
— Джон Джон

5
@GuruprasadGV Это ожидается. Вместо использования Docker Attach, используйте docker exec -it <yourContainer> bash.
— VonC

3
Это также работает, если вы добавляете команду tail в конец файла точки входа.
— йар

2
Я использовал sshd в качестве моей последней (продолжительной) команды. Затем вы можете также запустить ssh на своем контейнере, как на виртуальной машине (после установки .ssh / authorized_keys и т. Д.) ... Вы также можете перейти к настройке контейнера с использованием ansible.
— андрей паштет

1
Я закончил тем, что выполнил свою команду, а также старое исправление, указанное выше: docker запустил image_name / bin / bash -c "my / command && tail -f / dev / null"
— Джорди

58

Согласно этому ответу , добавление -tфлага предотвратит выход контейнера при работе в фоновом режиме. Затем вы можете использовать, docker exec -i -t <image> /bin/bashчтобы войти в приглашение оболочки.

docker run -t -d <image> <command>

Кажется, что опция -t не очень хорошо документирована , хотя в справке говорится, что она «выделяет псевдо-TTY».


10
Ницца. Кажется менее хакерским, чем добавлениеtail -f /dev/null
— Scarysize

Спасибо! По малой вероятности это кому-то помогает, в Emacs Eshell это ведет себя не очень хорошо.
— Питер Бечич

2
docker run -t -d --name mysql -p 3306:3306 mysql- не работает для меня (Ubuntu 14.04.5): STATUS = возбужденном (1) 4 секунды назад
— Putnik

Я обнаружил, что вам не нужно <команда> здесь, если вы не хотите. Как ни странно, он также работает, чтобы заменить -t на -i (интерактивный). В документе упоминается, что использование -t и -i вместе будет вести себя как оболочка.
— Джерси бобы

44

Задний план

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

В вашем случае команда ( /bin/bashпо умолчанию centos:latestвключена) немедленно завершает работу (как это делает bash, когда он не подключен к терминалу и ему нечего запустить).

Обычно, когда вы запускаете контейнер в режиме демона (с -d), контейнер выполняет какой-то процесс демона (например httpd). В этом случае, пока запущен демон httpd, контейнер останется живым.

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

(Вы хотели попасть в командную строку bash внутри контейнера? Это просто! docker run -it centos:latest)

Решение

Простой способ сохранить контейнер живым в режиме демона на неопределенный срок - запустить его sleep infinityкак команду контейнера. Это не зависит от выполнения странных вещей, таких как выделение TTY в режиме демона. Хотя он полагается на странные вещи, такие как использование в sleepкачестве основной команды.

$ docker run -d centos:latest sleep infinity
$ docker ps
CONTAINER ID  IMAGE         COMMAND          CREATED       STATUS       PORTS NAMES
d651c7a9e0ad  centos:latest "sleep infinity" 2 seconds ago Up 2 seconds       nervous_visvesvaraya

Альтернативное решение

Как указано cjsimon, -tопция выделяет «псевдо-tty». Эти трюки заставляют продолжать работать бесконечно, потому что он думает, что он подключен к интерактивному TTY (даже если у вас нет возможности взаимодействовать с этим конкретным TTY, если вы не проходите мимо -i). В любом случае, это тоже должно сработать:

$ docker run -t -d centos:latest

Не уверен на 100%, вызовут ли -tдругие странные взаимодействия; возможно оставьте комментарий ниже, если это так.


Обратите внимание, что это не работает на альпийском, так как сон BusyBox не принимает infinity.
— Джон Кугельман

это помогло мне устранить неполадки с образом amazon-linux, спасибо
— влиятельный

18

Привет, это проблема, потому что контейнеры Docker завершают работу, если в контейнере нет запущенного приложения.

-d 

Опция - просто запустить контейнер в режиме deamon.

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

Eg: docker run -d centos sh /yourlocation/start.sh

Этот start.sh должен указывать на бесконечное приложение.

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

Всего наилучшего


12

Вы можете выполнить то, что вы хотите с помощью:

docker run -t -d <image-name>

или

docker run -i -d <image-name>

или

docker run -it -d <image-name>

Параметр команды, предложенный другими ответами (т. Е. Tail -f / dev / null), является необязательным и НЕ обязателен, чтобы ваш контейнер продолжал работать в фоновом режиме.

Также обратите внимание, что документация Docker предполагает, что сочетание параметров -i и -t приведет к тому, что он будет вести себя как оболочка.

Видеть:

https://docs.docker.com/engine/reference/run/#foreground


9

У меня есть этот фрагмент кода из ENTRYPOINTмоего файла Docker:

while true
do
    echo "Press [CTRL+C] to stop.."
    sleep 1
done

Запустите образ встроенного докера как:

docker run -td <image name>

Войдите в оболочку контейнера:

docker exec -it <container id> /bin/bash

это решение, которое вы создали бесконечный цикл для этого? : D
— Мухаммед Салман

8

выполнить команду следующим образом:

docker run -t -d <image-name>

если вы хотите указать порт, то введите команду, как показано ниже:

docker run -t -d -p <port-no> <image-name>

проверьте работающий контейнер, используя следующую команду:

docker ps

Мне действительно нравится этот ответ, потому что самый популярный ответ предполагает, что вам нужна команда (то есть tail -f / dev / null). Команда полностью необязательна. Ключом здесь является использование -t. Я также обнаружил, что -i работает вместо -t, или вы также можете использовать оба -it вместе (как видно из документации, он будет работать как оболочка).
— Джерси боб

Есть ли преимущество использования -t -dпротив -i -d? Оба будут поддерживать контейнер в рабочем состоянии.
— Висбуки

5

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

Так что, если ваш скрипт входа в докер является фоновым процессом, как показано ниже:

/usr/local/bin/confd -interval=30 -backend etcd -node $CONFIG_CENTER &

'&' Заставляет контейнер останавливаться и выходить, если нет других процессов переднего плана, запущенных позже. Таким образом, решение состоит в том, чтобы просто удалить '&' или запустить другой CMD переднего плана , например

tail -f server.log

Возможно touch, сначала понадобится этот файл, если вы не можете найти файл журнала.
— Самуэль Эль

Обычно файл журнала I tail является текущим выходом журнала сервера или перенаправления, который уже должен быть там после запуска процесса.
— Пеймин Ху

4

Контейнер Docker завершается, если задание внутри выполнено, поэтому, если вы хотите сохранить его в рабочем состоянии, даже если у него нет какой-либо работы или он уже завершен, вы можете это сделать docker run -di image. После того, как вы это сделаете, docker container lsвы увидите, что он работает.


3

Возможно, это только я, но в CentOS 7.3.1611 и Docker 1.12.6, но мне пришлось использовать комбинацию ответов, опубликованных @VonC & @Christopher Simon, чтобы это работало надежно. Ничто из того, что я сделал до этого, не остановило бы выход контейнера после успешного запуска CMD. Я запускаю oracle-xe-11Gr2 и sshd.

Dockerfile

...
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && systemctl enable sshd
...
CMD /etc/init.d/oracle-xe start && /sbin/sshd && tail -f /dev/null

Затем добавьте -d -t и -i для запуска

docker run --shm-size=2g --name oracle-db -d -t -i -p 5022:22 -p 5080:8080 -p 1521:1521 centos-oracle:7.3.1611 

Наконец, после нескольких часов ударов головой о стену

ssh -v root@127.0.0.1 -p 5022
...
root@127.0.0.1's password: 
debug1: Authentication succeeded (password).

По любой причине вышеприведенное завершится после выполнения CMD, если удален хвост -f или какие-либо из параметров -t -d -i опущены.



1

У меня была та же проблема, просто открытие другого терминала с bash на нем работало для меня:

создать контейнер:

docker run -d mcr.microsoft.com/mssql/server:2019-CTP3.0-ubuntu
containerid=52bbc9b30557

стартовый контейнер:

docker start 52bbc9b30557

Запустите bash, чтобы контейнер продолжал работать:

docker exec -it 52bbc9b30557 bash

Начать процесс вам нужно:

docker exec -it 52bbc9b30557 /path_to_cool_your_app

1

Если вы используете CMD в конце вашего Dockerfile, вы можете добавить код в конце. Это будет работать только в том случае, если ваш докер построен на Ubuntu или на любой ОС, которая может использовать bash.

&& /bin/bash

Вкратце конец вашего Dockerfile будет выглядеть примерно так.

...

CMD ls && ... && /bin/bash

Так что, если у вас что-то запускается автоматически после запуска образа докера, и когда задача будет выполнена, терминал bash будет активен внутри вашего докера. Таким образом, вы можете ввести свои команды оболочки.


1

Запуск докера с интерактивным режимом может решить проблему.

Вот пример для бегущего изображения с и без интерактивного режима

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 b6b9a942a79b1243bada59db19c7999cfff52d0a8744542fa843c95354966a18

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

КОНТЕЙНЕР ID ИМИДЖ КОМАНДА СОЗДАННЫЕ СТАТУС ИМЕНА ПОРТОВ

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker run -d -t -i test_again1.0 bash c3d6a9529fd70c5b2dc2d7e90fe662d19c6dad8549e9c812fb2b7ce2105d7ff5

chaitra @ RSK-IND-BLR-L06: ~ / dockers $ sudo docker ps

ID КОНТЕЙНЕРА ИМИДЖ СОЗДАННЫЕ ИМЕНА СОСТОЯНИЯ ПОРТОВ СОСТОЯНИЯ c3d6a9529fd7 test_again1.0 "bash" 2 секунды назад Up 1 секунда awesome_haibt


0

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


-1

Порядок аргументов имеет значение

Ответ Jersey Beans (все 3 примера) работал на меня. После долгих проб и ошибок я понял, что порядок аргументов имеет значение.

Контейнер работает в фоновом режиме: docker run -t -d <image-name>

Сохраняет контейнер работающим на переднем плане: docker run <image-name> -t -d

Это не было очевидно для меня, исходя из фона Powershell.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.