ChatGPT解决这个技术问题 Extra ChatGPT

docker run -d 后 Docker 容器会自动停止

根据我目前阅读的教程,使用“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

我做错什么了吗?如何解决此问题?

“docker run hello-world” <== 完美运行,但是如果我运行“docker run -d hello-world”,我仍然无法获得正在运行的容器。
我有一个类似的问题,但我通过使用 docker run -it -d <image> /bin/bash 让它以交互方式启动一个 bash shell 并且不会关闭容器,因为 shell 进程处于活动状态。

F
FreeSoftwareServers

centos dockerfile 有一个默认命令 bash

这意味着,当在后台 (-d) 运行时,shell 会立即退出。

2017 年更新

最新版本的 docker 授权在 foreground mode-t-i-it)的 detached mode 中运行容器

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

docker run -t -d centos

bash 将在后台等待。
这最初在 kalyani-chaudharianswer 中报告,并在 jersey beananswer 中详细说明。

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

请注意,对于 alpineMarinos An 报告 in the comments

docker run -t -d alpine/git 不会保持进程正常。不得不做: docker run --entrypoint "/bin/sh" -it alpine/git

原始答案(2015)

this article 中所述:

建议不要使用 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

或者在 Dockerfile 中:

ENTRYPOINT ["tail"]
CMD ["-f","/dev/null"]

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

从那里,您可以attach to it or detach from it(或 docker exec 一些命令)。


添加tail -f /dev/null后,我无法连接回shell,虽然我明白为什么,有没有办法让它以某种方式工作?
@GuruprasadGV 这是意料之中的。不要使用 docker attach,而是使用 docker exec -it <yourContainer> bash
如果您在入口点文件的末尾添加 tail 命令,这也有效。
我使用 sshd 作为我最后一个(长时间运行的)命令。然后,您可以像在 VM 上一样在容器上 ssh(一旦设置 .ssh/authorized_keys 等)...您还可以继续使用 ansible 配置容器。
我最终这样做是为了执行我的命令以及上面列出的旧修复: docker run image_name /bin/bash -c "my/command && tail -f /dev/null"
C
Community

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

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

似乎 -t 选项 isn't documented very well,虽然帮助说它“分配一个伪 TTY”。


好的。似乎不如附加 tail -f /dev/null
谢谢!在这对某人有帮助的可能性很小的情况下,这在 Emacs Eshell 中表现不佳。
docker run -t -d --name mysql -p 3306:3306 mysql - 对我不起作用(ubuntu 14.04.5):STATUS=Exited (1) 4 秒前
我发现这里不需要 ,除非你愿意。奇怪的是,它也可以将 -t 替换为 -i(交互式)。该文档确实提到使用 -t 和 -i 组合将表现得像一个外壳。
@CyberPlayerOne...<图像>应该是图像名称。 “docker run”是一个旧命令,他们保留它是为了向后兼容。您可以找到更多 @stackoverflow.com/a/51247809/6536853docker.com/blog/whats-new-in-docker-1-13
m
mkasberg

背景

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”。这会欺骗 bash 无限期地继续运行,因为它认为它已连接到交互式 TTY(即使如果您不通过 -i,您将无法与该特定 TTY 进行交互)。无论如何,这也应该可以解决问题:

$ docker run -t -d centos:latest

不能 100% 确定 -t 是否会产生其他奇怪的交互;如果是这样,也许可以在下面发表评论。


请注意,这在 alpine 上不起作用,因为 BusyBox 的 sleep 不接受 infinity
这帮助我对 amazon-linux 映像进行故障排除,谢谢
P
Pratik

您好,这个问题是因为如果容器中没有正在运行的应用程序,docker 容器就会退出。

-d 

选项只是以守护程序模式运行容器。

所以让你的容器持续运行的技巧是指向 docker 中的一个 shell 文件,这将使你的应用程序保持运行。你可以尝试使用 start.sh 文件

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

这个 start.sh 应该指向一个永无止境的应用程序。

如果您不想运行任何应用程序,您可以安装 monit 以保持您的 docker 容器运行。请让我们知道这两种情况是否对您保持容器运行有效。

一切顺利


j
jersey bean

您可以通过以下任一方式完成您想要的:

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


B
Binita Bharati

我从 docker 文件中的 ENTRYPOINT 运行此代码片段:

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
k
kalyani chaudhari

执行命令如下:

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(因为文档表明它将作为 shell 运行)。
使用 -t -d-i -d 有什么优势吗?两者都将保持容器运行。
V
Vrangz

如果里面的任务完成,Docker 容器就会退出,所以如果你想让它保持活动状态,即使它没有任何工作或已经完成它们,你可以做 docker run -di image。执行 docker container ls 后,您将看到它正在运行。


P
Peiming Hu

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

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

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

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

tail -f server.log

可能要先touch该文件,以防您找不到日志文件。
通常我尾的日志文件是当前服务器日志或重定向输出,在进程启动后应该已经存在。
E
Ekin

如果您在 Dockerfile 末尾使用 CMD,您可以在末尾添加代码。这仅在您的 docker 构建在 ubuntu 或任何可以使用 bash 的操作系统上时才有效。

&& /bin/bash

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

...

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

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


s
steven87vt

也许只有我一个人,但在 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).

无论出于何种原因,如果尾部 -f 被删除,或者任何 -t -d -i 选项被省略,则在执行 CMD 后上述内容将退出。


v
vimal krishna

我在下面有同样问题的帖子中解释了它。

How to retain docker alpine container after "exit" is used?


H
Hegde

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

这是使用和不使用交互模式运行图像的示例

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 秒前 1 秒 awesome_haibt


S
Steef

我遇到了同样的问题,只是打开另一个带有 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

A
Anubhav Sharma

我也面临同样的问题,但方式不同。当我创建 docker 容器时。它会自动停止在后台运行的未使用容器。有时它还会停止正在使用的容器。在我的情况下,这是因为它之前拥有的 docker.sock 文件的权限。你要做的是:-

再次安装 docker。(当我在 ubuntu 上工作时,我从这里安装它)运行命令以更改权限。 sudo chmod 666 /var/run/docker.sock 安装 docker-compose(这是可选的,因为我有 compose 文件可以一起创建许多容器) sudo curl -L "https://github.com/docker/compose/releases/download /1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose 检查对于版本,以确保我拥有最新版本并且不会因某些贬低而出现问题。然后我运行 docker 容器构建。


S
Suraj Rao

您可以简单地使用:

docker container run -d -it <container name or id> /bin/bash

对我来说,该命令需要一个图像名称,所以它不起作用
D
Dharman

有多个选项可以在前台/分离状态下运行容器。但是如果您仍然觉得问题没有解决,您可以尝试通过查看日志来解决问题。

sudo docker logs -f >> container.log

此外,您还可以使用 --details 显示提供给日志的额外详细信息。


这不是内部问题/错误。该问题似乎与 OP 用于运行容器的命令正在退出有关,因为它没有运行应用程序和/或没有等待用户输入。那么,显示日志值将如何帮助呢?
F
F1Linux

Dockerfile 中的应用程序路径不正确:

我正在使用 Alpine Linux 将应用程序从 RHEL 服务器迁移到 Docker 容器。

构建过程中没有错误,所以我很惊讶地看到容器立即退出!

第一个停靠港:

docker logs <containerID>

这表明我在 Dockerfile 中提供给 CMD 的二进制文件的路径是伪造的:

line 0: /sbin/postfix: not found

好吧,这告诉了我事情是如何被破坏的,但没有具体说明在哪里:我仍然需要 Alpine Linux 中二进制文件的正确路径......

故障排除:

谷歌搜索没有显示正确的路径,所以我在我的 Dockerfile 中添加了以下行:

RUN which postfix

然后,我查看了我的构建日志记录 - 由附加到我的构建命令的以下命令提供 - 以检索 RUN which postfix 的值

 --progress=plain > /path/to/build.log 2>&1

修复:

我删除了这个测试版本,在 Dockerfile 中为 CMD 提供了正确的路径 - /usr/sbin/postfix,删除了 RUN which postfix 并运行了另一个构建。

瞧;这个过程现在仍然存在。

所以一个 duff 路径导致容器立即退出......


H
HVL71

论证顺序很重要

Jersey Beans 答案(所有 3 个示例)对我有用。经过相当多的反复试验,我意识到论点的顺序很重要。

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

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

对我来说,来自 Powershell 背景并不明显。


J
Jackie

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


K
Kai - Kazuya Ito

这 4 个命令都可以使您的 docker 容器保持运行:

docker run -td centos
docker run -dt centos
docker run -t -d centos
docker run -d -t centos