Контейнер-докер автоматически останавливается после "docker run -d"

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

[email protected]:/home/root# docker run -d centos
605e3928cdddb844526bab691af51d0c9262e0a1fc3d41de3f59be1a58e1bd1d

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

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

[email protected]:/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

Док файл centos имеет команду по умолчанию bash.

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

Обновление 2017

Более поздние версии Docker позволяют запускать контейнер как в отдельном режиме, так и в режиме переднего плана (-t, -i или -it).

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

docker run -t -d centos

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

[email protected]:~$ 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 + [TG21 ] + Q.

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

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

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

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

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

docker ps покажет работающий контейнер centos.

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

Ответ 2

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

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

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

Ответ 3

Фон

Контейнер 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 выделяет "псевдо -t ty". Эти трюки заставляют продолжать работать неопределенно долго, потому что он думает, что он связан с интерактивным TTY (даже если у вас нет способа взаимодействовать с этим конкретным TTY, если вы не пройдете -i). В любом случае, это тоже должно сработать:

$ docker run -t -d centos:latest

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

Ответ 4

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

-d 

- это просто запустить контейнер в режиме деамонов.

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

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

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

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

Все лучшее

Ответ 5

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

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

Ответ 6

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

docker run -t -d <image-name>

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

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

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

docker ps

Ответ 7

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

Итак, если ваша запись в докере script является фоновым процессом, например:

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

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

tail -f server.log

Ответ 8

Возможно, это только я, но на CentOS 7.3.1611 и Docker 1.12.6, но мне пришлось использовать комбинацию ответов, отправленных @VonC и @Christopher Simon, чтобы получить эту работу надежно. Ничто из того, что я сделал до этого, не остановит контейнер от выхода после успешного запуска CMD. Я начинаю oacle-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 [email protected] -p 5022
...
[email protected] password: 
debug1: Authentication succeeded (password).

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

Ответ 9

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

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

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

docker run -td <image name>

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

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

Ответ 11

У меня была та же проблема, просто открытие другого терминала с 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

Ответ 12

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

&& /bin/bash

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

...

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

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

Ответ 13

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

Ответ 14

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

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

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

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

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