在“ docker run -d”之后,Docker容器将自动停止


333

根据我到目前为止阅读的教程,使用“ docker run -d”将从图像启动容器,并且该容器将在后台运行。看起来就是这样,我们可以看到我们已经有了容器ID。

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”,我仍然无法获得正在运行的容器。
J约翰

5
我有一个类似的问题,但是我通过使用docker run -it -d <image> /bin/bash它以交互方式启动bash shell并使其正常工作,因为shell进程处于活动状态,因此没有关闭容器。
Rtsne42

Answers:


495

CentOS的dockerfile有一个默认的命令bash

这意味着,在后台(-d)中运行时,外壳程序会立即退出。

更新2017

最近泊坞窗授权版本都运行在一个容器分离模式 ,并前台模式-t-i-it

在这种情况下,您不需要任何其他命令,这就足够了:

docker run -t -d centos

bash将在后台等待。
最初是在kalyani-chaudhari答案中报道过的,而在jersey bean答案中进行了详细说明。

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使用using 而不是与之一起运行,-d因为您可以只使用一个命令来运行容器,而无需通过按Ctrl+ P+ 来分离容器的终端Q

但是,-d选项存在问题。除非命令未在前台运行,否则容器将立即停止
Docker要求您的命令保持在前台运行。否则,它会认为您的应用程序停止并关闭容器。

问题是某些应用程序没有在前台运行。我们如何使它变得更容易?

在这种情况下,您可以添加tail -f /dev/null到命令中。
这样,即使您的main命令在后台运行,您的容器也不会停止,因为tail一直在前台运行。

所以这将工作:

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

A docker ps将显示centos容器仍在运行。

从那里,您可以附加到它或从它分离(或docker exec某些命令)。


抱歉,还有一个问题,我有一个需要在启动时运行的脚本,看起来像/etc/rc.d/rc.local不再起作用(我的心态仍然像对待OS一样对待docker),我认为docker file是更好的选择案件?
J约翰

5
@GuruprasadGV这是预期的。而不是使用docker attach,请使用docker exec -it <yourContainer> bash
2016年

3
如果在入口点文件的末尾添加tail命令,这也将起作用。
yara

2
我使用sshd作为我的最后一个(长期运行)命令。然后,您也可以像在VM上一样在容器上ssh(一旦设置了.ssh / authorized_keys等)...您还可以继续使用ansible配置容器。
安德鲁·帕特

1
我最终执行此命令以执行命令以及上面列出的旧版本修复程序:docker run image_name / bin / bash -c“ my / command && tail -f / dev / null”
Geordie

58

根据此答案,添加-t标志将防止容器在后台运行时退出。然后,您可以docker exec -i -t <image> /bin/bash用来进入shell提示符。

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

看来-t选项没有很好地说明,尽管帮助说明它“分配了伪TTY”。


10
真好 似乎没有附加的hackytail -f /dev/null
Scarysize

谢谢!在帮助某人的机会很小的情况下,这在Emacs Eshell中表现不佳。
Peter Becich '17

2
docker run -t -d --name mysql -p 3306:3306 mysql-不适用于我(ubuntu 14.04.5):STATUS =已退出(1)4秒前
Putnik

我发现您不需要这里的<command>,除非您愿意。奇怪的是,它也可以用-i(交互式)替换-t。该文档确实提到使用-t和-i组合将表现得像shell。
泽西豆

43

背景

Docker容器运行使它保持活动状态的进程(“命令”或“入口点”)。只要命令继续运行,容器将继续运行。

在您的情况下,命令(/bin/bash默认情况下为on 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”。这会导致bash无限期继续运行,因为它认为它已与交互式TTY连接(即使您未通过也无法与该特定TTY进行交互-i)。无论如何,这也应该达到目的:

$ docker run -t -d centos:latest

无法100%确定是否-t会产生其他怪异的互动;如果有的话,也许在下面留下评论。


请注意,这在高山上不起作用,因为BusyBox的睡眠不接受infinity
约翰·库格曼

帮我解决一个Amazon Linux的图像,谢谢
进水

18

大家好,这是因为如果容器中没有正在运行的应用程序,则Docker容器会退出。

-d 

选项仅是在守护进程模式下运行容器。

因此,使容器持续运行的技巧是指向docker中的shell文件,该文件将使您的应用程序保持运行状态。您可以尝试使用start.sh文件

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

此start.sh应指向永无止境的应用程序。

如果您不希望任何应用程序运行,则可以进行安装monit,以使您的Docker容器保持运行状态。请让我们知道这两种情况是否对您有用,以保持容器运行。

祝一切顺利


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选项将使它的行为类似于shell。

看到:

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


9

我从ENTRYPOINTdocker文件中运行了以下代码段:

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

将构建的docker映像运行为:

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 -dvs 有什么优势-i -d吗?两者都将保持容器运行。
wisbucky

5

Docker要求您的命令保持在前台运行。否则,它认为您的应用程序停止并关闭容器。

因此,如果您的docker entry脚本是一个如下所示的后台进程:

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

如果以后没有其他前台进程触发,则'&'使容器停止并退出。因此解决方案是删除'&'或在其后运行另一个前台CMD,例如

tail -f server.log

touch万一找不到日志文件,可能首先要该文件。
塞缪尔·埃尔

通常,日志文件I tail是当前服务器的日志或重定向输出,该文件在启动过程后应该已经存在。
Peiming Hu

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。

Docker文件

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

不管出于什么原因,如果删除了-f尾部,或者省略任何-t -d -i选项,则在执行CMD之后,以上内容都会退出。



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

如果您在Dockerfile的末尾使用CMD,则可以在末尾添加代码。仅当您的Docker基于ubuntu或任何可以使用bash的操作系统构建时,此方法才有效。

&& /bin/bash

简而言之,您的Dockerfile的结尾看起来像这样。

...

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

因此,如果您在运行docker映像后有任何自动运行,并且任务完成后,bash终端将在docker内部处于活动状态。因此,您可以输入shell命令。


1

以交互模式运行docker可能会解决问题。

这是在有和没有交互模式下运行图像的示例

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

chaitra @ RSK-IND-BLR-L06:〜/ dockers $须藤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 $须藤docker ps

容器ID图像命令创建的状态端口名称c3d6a9529fd7 test_again1.0“ bash” 2秒前最多1秒awesome_haibt


0

如果要在容器上进行操作,则需要在前台运行它以使其保持活动状态。


-1

论据顺序很重要

Jersey Beans答案(所有3个示例)对我都有效。经过反复试验,我意识到参数的顺序很重要。

使容器在后台运行: docker run -t -d <image-name>

使容器在前台运行: docker run <image-name> -t -d

从Powershell的背景来看,这对我来说并不明显。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.