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.