Контейнер 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цю функцію, запускає bash shell і не закриває контейнер, оскільки процес оболонки активний.
Rtsne42

Відповіді:


495

CentOS dockerfile має команду за замовчуванням bash.

Це означає, що при запуску у фоновому режимі ( -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

Зверніть увагу , що для альпійської , Марінос повідомляє в коментарях :

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

Проблема полягає в тому, що деякий додаток не працює на передньому плані. Як нам зробити це легше?

У цій ситуації ви можете додати tail -f /dev/nullдо своєї команди.
Роблячи це, навіть якщо ваша основна команда працює у фоновому режимі, ваш контейнер не зупиняється, оскільки хвіст продовжує працювати на передньому плані.

Отже, це спрацювало б:

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

A docker psпоказав би контейнер centos, який все ще працює.

Звідти ви можете приєднати до нього або відірватися від нього (або docker execдеякі команди).


Вибачте, ще одне запитання: мені потрібно запустити сценарій при запуску, схоже, що /etc/rc.d/rc.local більше не працює (мій настрій все ще ставиться до докера як ОС), я вважаю, що файл докера є кращим варіантом у цьому справи?
J Джон

5
@GuruprasadGV Очікується. Замість використання докерного вкладення використовуйте docker exec -it <yourContainer> bash.
VonC

3
Це також працює, якщо ви додаєте хвостову команду в кінці файлу вхідної точки.
яра

2
Я використовував sshd як свою останню (тривалу) команду. Потім ви можете навантажувати ssh на ваш контейнер, як і на VM (як тільки ви встановите .ssh / санкціоновані_кеї тощо) ... Ви також можете продовжити налаштування контейнера за допомогою ansible.
andrew pate

1
Я в кінцевому підсумку робив це, щоб виконати свою команду, а також попередній виправлений файл, зазначений вище: docker run 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
додається

Дякую! З малого шансу це допомагає комусь, в Emacs Eshell це не так добре поводиться.
Петро Бечич

2
docker run -t -d --name mysql -p 3306:3306 mysql- не працює для мене (ubuntu 14.04.5): STATUS = Вийшов (1) 4 секунди тому
Putnik

Я виявив, що вам тут не потрібен <command>, якщо ви не хочете. Як не дивно, він також працює на заміну -t на -i (інтерактивний). Документ згадує використання -t і -i у поєднанні буде поводитись як оболонка.
джерсі боб

43

Фон

Контейнер Docker запускає процес ("команда" або "точка входу"), який підтримує його живим. Контейнер буде працювати, доки команда продовжує виконуватись.

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

Зазвичай, коли ви запускаєте контейнер у демоновому режимі (з -d), контейнер виконує якийсь процес демон (наприклад httpd). У цьому випадку, доки демон httpd працює, контейнер залишатиметься живим.

Ви, схоже, намагаєтесь зробити це - зберегти контейнер живим без демонового процесу, що проходить всередині контейнера. Це дещо дивно (адже контейнер не робить нічого корисного, поки ви не взаємодієте з ним, можливо, з ним docker exec), але є певні випадки, коли це може мати сенс зробити щось подібне.

(Ти мав на увазі потрапити до башти підказки всередині контейнера? Це просто! 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

Привіт, це питання тому, що контейнери докер виходять, якщо в контейнері немає запущеної програми.

-d 

варіант - просто запустити контейнер у режимі deamon.

Таким чином, фокус, щоб ваш контейнер постійно працював, - це вказати на файл оболонки в докері, який буде тримати роботу програми. Можна спробувати файл 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) є абсолютно необов’язковим і НЕ потрібен, щоб ваш контейнер не працював у фоновому режимі.

Також зауважте, що документація Докера говорить про те, що поєднання параметрів -i та -t призведе до того, що вона поводиться як оболонка.

Подивитися:

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


9

У мене цей фрагмент коду запускається з 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

це рішення, яке ви створили для цього нескінченний цикл? : D
Мухаммед СаЛман

8

виконайте команду наступним чином:

docker run -t -d <image-name>

якщо ви хочете вказати порт, тоді командуйте як нижче:

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

перевірити запущений контейнер за допомогою наступної команди:

docker ps

Мені справді подобається ця відповідь найкраще, тому що найпопулярніша відповідь говорить про те, що вам потрібна команда (тобто хвіст -f / dev / null). Команда абсолютно необов’язкова. Ключовим тут є використання -t. Я також виявив, що я працюю замість -t, або ви також можете використовувати обоє -і комбіновані (як свідчить документація, вона працюватиме як оболонка).
квасоля з джерсі

Чи є якась перевага використання -t -dvs -i -d? Обидва триматимуть контейнер працювати.
Вісбукі

5

Докер вимагає, щоб ваша команда продовжувала працювати на передньому плані. В іншому випадку він вважає, що ваші програми зупиняються та закривають контейнер.

Отже, якщо ваш скрипт введення докера є фоновим процесом, наприклад:

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

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

tail -f server.log

Потрібно спробувати спочатку touchцей файл, якщо ви не знайдете файл журналу.
Самуель Ель

Зазвичай у файлі журналу I хвостом є поточний журнал сервера або вихідний переспрямування, який повинен бути вже після запуску процесу.
Пеймінг Ху

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.

Докерфайл

...
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

У мене був той самий випуск, просто відкриття іншого терміналу з ударом на ньому спрацювало:

створити контейнер:

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

ІМЕНТ ІНФОРМАЦІЇ КОНТАЙНЕРУ КОМАНДА СТВОРЕННЯ ІМЕНІВ ПОРТУ СТАТУСУ

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

ІМЕНТ КОНТАЙНЕРА ІМІДЖЕННЯ КОМАНДА СТВОРЕННЯ СТАТУСНИХ ІМЕНІВ ПОРТУ ІМЕНИ c3d6a9529fd7 test_again1.0 "bash" 2 секунди тому Вгору 1 секунда awesome_haibt


0

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


-1

Аргументація має значення

Відповідь Джерсі Бібса (всі 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.