【问题标题】:Docker container will automatically stop after "docker run -d"docker run -d 后 Docker 容器会自动停止
【发布时间】:2015-07-24 10:37:45
【问题描述】:

根据我目前阅读的教程,使用“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 -it -d <image> /bin/bash 让它工作了,这会以交互方式启动一个 bash shell,并且不会关闭容器,因为 shell 进程处于活动状态。

标签: docker


【解决方案1】:

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

-d 

选项只是在守护模式下运行容器。

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

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

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

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

一切顺利

【讨论】:

    【解决方案2】:

    centos dockerfile 有一个默认命令bash

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

    2017 年更新

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

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

    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中所述:

    建议使用-d,而不是使用docker run -i -t image your-command 运行,因为您只需一个命令即可运行容器,并且无需通过按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"
    【解决方案3】:

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

    因此,如果您的 docker 入口脚本是如下后台进程:

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

    如果后面没有触发其他前台进程,'&' 使容器停止并退出。 所以解决方法就是去掉'&'或者在它之后运行另一个前台CMD,比如

    tail -f server.log
    

    【讨论】:

    • 可能想先touch那个文件,以防你找不到日志文件。
    • 通常我tail的日志文件是当前服务器日志或者重定向输出,进程启动后应该已经存在了。
    【解决方案4】:

    根据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 组合将表现得像一个 shell。
    • @Cyber​​PlayerOne... 应该是图像名称。 “docker run”是一个旧命令,他们保留它是为了向后兼容。你可以找到更多@stackoverflow.com/a/51247809/6536853docker.com/blog/whats-new-in-docker-1-13
    【解决方案5】:

    也许只有我一个人,但在 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 后退出。

    【讨论】:

      【解决方案6】:

      执行命令如下:

      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 有什么优势吗?两者都将保持容器运行。
      【解决方案7】:

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

      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

      【讨论】:

        【解决方案8】:

        背景

        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 的睡眠不接受 infinity
        • 这帮助我解决了 amazon-linux 映像问题,谢谢
        【解决方案9】:

        我已经在下面有相同问题的帖子中解释过。

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

        【讨论】:

          【解决方案10】:

          参数顺序很重要

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

          让容器在后台运行: docker run -t -d &lt;image-name&gt;

          保持容器在前台运行:docker run &lt;image-name&gt; -t -d

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

          【讨论】:

            【解决方案11】:

            我的 docker 文件中的 ENTRYPOINT 运行了这段代码 sn-p:

            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
            【解决方案12】:

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

            【讨论】:

              【解决方案13】:

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

              && /bin/bash
              

              简单地说,你的 Dockerfile 的结尾看起来像这样。

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

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

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  【解决方案15】:

                  如果你想对容器进行操作,你需要在前台运行它以保持它的存活。

                  【讨论】:

                    【解决方案16】:

                    以交互模式运行 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 秒前 Up 1 seconds awesome_haibt

                    【讨论】:

                      【解决方案17】:

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

                      1. 再次安装 docker。(当我在 ubuntu 上工作时,我从 here 安装它)

                      2. 运行命令更改权限。

                        sudo chmod 666 /var/run/docker.sock

                      3. 安装 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

                      4. 检查版本以确保我拥有最新版本并且不会因某些贬低而出现问题。

                      5. 然后我运行 docker 容器构建。

                      【讨论】:

                        猜你喜欢
                        • 2018-09-29
                        • 2019-11-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-11-22
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多