【问题标题】:How to detect if docker run succeeded programmatically?如何检测 docker run 是否以编程方式成功?
【发布时间】:2014-08-24 00:31:17
【问题描述】:

我正在编写一个非常简单的 bash 脚本来快速检查我的容器是否仍然可以正确构建和启动,以及里面的应用程序是否响应请求。

有时docker run 会失败,例如因为我试图将容器绑定到的端口已经分配。但是当这种情况发生时docker run 的退出代码仍然是 0,所以我不能使用退出代码。如何以编程方式检查容器是否已正确启动?

我正在考虑的解决方案是:

  • 分析错误输出
  • docker ps查看容器是否在运行

但是这两个看起来有点矫枉过正和丑陋。我是否错过了检查docker run 是否成功的更好方法?

【问题讨论】:

  • 我不确定这里有什么问题。如果有问题的过程以通常的方式运行,那么您可以简单地检查退出代码。如果即使在失败的情况下它也会发出 0 退出代码,请尝试确定它是否是错误。如果程序在任何情况下都返回 0 的退出代码,那么您可能别无选择,只能解析输出。
  • 正如@devnull 所说,如果你不能相信docker run 会在失败时返回一个非零返回码,那么你所能做的就是解析输出(这可能很复杂或脆弱)或使用另一个命令(即您的ps 建议)来检查第一个命令的结果。您可能需要考虑向 docker 提交票证,看看他们是否也可以修复来自 run 的返回码。
  • 确保您拥有最新版本。
  • 是在您的容器中运行的自定义代码吗?如果是这样,您可以在 Dockerfile 中导出一个端口,当您的程序处于稳定运行状态时,在该端口上发送“OK”消息。您的客户端代码等待“OK”消息。
  • 您能否提供一个示例来说明您是如何运行 docker 以及使用哪个版本的?快速测试显示 docker exit code 对我来说是 1 docker run -d -p 9010:9010 busybox true ; echo $?

标签: bash docker


【解决方案1】:

正如 Abel Muiño 在 cmets 中所建议的,这可能已在更新的 Docker 版本中得到修复(我目前运行的是 0.9.1)。

但是,如果您像我一样暂时无法使用旧版本,我确实找到了一个不错的解决方法来检查容器是否使用 docker inspect 启动。

docker inspect 返回一个 JSON 对象,其中包含有关容器的大量信息,尤其是容器当前是否正在运行。 -f 标志可让您轻松提取所需的位:

docker inspect -f {{.State.Running}} $CONTAINER_ID

docker inspect -f "{{.State.Running}}" $CONTAINER_ID

将返回 truefalse

请注意,您可能希望在启动容器和检查容器是否启动之间使用sleep 1(或更多)。如果您的设置有问题,它可能会在很短的时间内显示为“正在运行”,然后才真正退出。

【讨论】:

  • 为什么不使用docker inspect -f {{.State.Running}} <container-id> 而使用jq 呢?只是想知道。
  • 因为我没有意识到检查可以让你直接这样做!谢谢@DharmitShah,这是一个很好的建议,我会更新我的答案。
  • 如果没有这样的容器,要抑制错误消息,请使用2> /dev/null重定向stderr。
  • 如果我将其分配给 var,则在使用 2> /dev/null 时会出现错误,因为它不会评估任何内容。如果容器不存在,如何使其默认为false
  • 这不适应由于重启策略而不断重启的容器......即如果一个容器被赋予了一个除非停止/总是重启的策略,.State.Running 将总是返回 true.... 只是一些需要厌倦的东西!
【解决方案2】:

为避免解析任何内容,您可以使用 docker top,如果容器未运行,则返回 1:

id=$(docker run mycontainer)
if ! docker top $id &>/dev/null
then
    echo "Container crashed unexpectedly..."
    return 1
fi

【讨论】:

    【解决方案3】:

    我们可以使用docker exec $id true 2>/dev/null || echo not running

    此命令不会像“docker top”那样写入标准输出。它在容器未运行时写入 stderr,与“docker top”消息相同。

    【讨论】:

      【解决方案4】:

      将上述建议应用于脚本。

      1 - 创建一个脚本 keepMyDockerUp.sh :

      vi keepMyDockerUp.sh
      
      
      #!/bin/bash
      Container_ID=INSERT_YOUR_CONTAINER_ID HERE
      result=$( docker inspect -f {{.State.Running}} $Container_ID)
      echo "result is" $result
      if [ $result = "true" ]
      then
      echo "docker is already running"
      else
      systemctl restart docker
      docker start $Container_ID
      fi
      

      2 - 然后只需将其添加到 cron,这样您的脚本就会不时验证您的 Docker 容器是否已启动:

      crontab -e
      

      转到最后一行并添加您的脚本文件。例如:

      * * * * * /root/keepMyDockerUp.sh
      

      3 - 保存 crontab,再也不用担心您的 Docker 容器再次停机。

      希望对你有帮助...

      ;-)

      【讨论】:

        【解决方案5】:

        我不得不使用:

        $ docker inspect -f {{.State.Health.Status}} xxx
        

        (容器处于运行状态,但容器内的服务没有完全启动。

        部分检查输出:

        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 1618,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-03-08T10:39:24.061732398Z",
            "FinishedAt": "0001-01-01T00:00:00Z",
            "Health": {
                "Status": "starting",
                "FailingStreak": 0,
                "Log": []
        

        【讨论】:

        • 这不会说明运行是否成功。因为容器可能运行然后失败。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-27
        • 1970-01-01
        • 2012-08-03
        • 1970-01-01
        相关资源
        最近更新 更多