Контейнер-докер автоматически останавливается после "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
Ответ 10
Я объяснил это в следующем посте, который имеет тот же вопрос.
Как сохранить докер альпийский контейнер после использования "выхода"?
Ответ 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.