You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker健康检查命令始终返回健康状态的问题求助

问题:Docker健康检查中pgrep命令始终返回0的异常情况

我使用docker-maven-plugin构建包含Java命令行应用的Docker容器,在健康检查中配置了通过pgrep检查指定Java进程是否存在:

<healthCheck>
  <cmd>pgrep -f "java.*my-app-name.*jar" > /dev/null || exit 1</cmd>
</healthCheck>

但发现健康检查始终返回健康状态,即使修改为检查一个不存在的进程:

<healthCheck>
  <cmd>pgrep -f "DOES-NOT-EXIST" > /dev/null || exit 1</cmd>
</healthCheck>

执行docker ps时,容器仍显示为健康状态:

容器显示健康状态截图

查看镜像的健康检查配置(docker images <IMAGE ID>输出):

"Healthcheck": {
                "Test": [
                    "CMD-SHELL",
                    "pgrep -f \"DOES-NOT-EXIST\" > /dev/null || exit 1"
                ]
            },

但进入运行中的容器手动执行命令时,命令行为符合预期:

34c68bcd9436:/ # pgrep -f "java.*my-app-name.*jar" > /dev/null || exit 1
34c68bcd9436:/ # pgrep -f "DOES-NOT-EXIST" > /dev/null || exit 1
exit

查看健康检查日志(docker inspect --format "{{json .State.Health }}" 0f607cf3bbcd | jq),发现所有检查的ExitCode都是0:

{
  "Status": "healthy",
  "FailingStreak": 0,
  "Log": [
    {
      "Start": "2023-01-18T12:02:48.7530323Z",
      "End": "2023-01-18T12:02:48.921539Z",
      "ExitCode": 0,
      "Output": ""
    },
    {
      "Start": "2023-01-18T12:03:18.9279247Z",
      "End": "2023-01-18T12:03:19.0777841Z",
      "ExitCode": 0,
      "Output": ""
    },
    {
      "Start": "2023-01-18T12:03:49.0825991Z",
      "End": "2023-01-18T12:03:49.1990431Z",
      "ExitCode": 0,
      "Output": ""
    },
    {
      "Start": "2023-01-18T12:04:19.2065635Z",
      "End": "2023-01-18T12:04:19.3829184Z",
      "ExitCode": 0,
      "Output": ""
    },
    {
      "Start": "2023-01-18T12:04:49.3996451Z",
      "End": "2023-01-18T12:04:49.5594201Z",
      "ExitCode": 0,
      "Output": ""
    }
  ]
}

当把健康检查改为直接返回失败时:

<healthCheck>
  <cmd>exit 1</cmd>
</healthCheck>

容器正常显示为不健康状态,说明问题出在pgrep命令的执行逻辑上。


可能的解决方案

  • 避免匹配健康检查自身进程:pgrep -f会匹配整个命令行,健康检查执行时的命令本身可能包含要搜索的字符串,导致误匹配。可以改用pgrep -x精确匹配进程名,或者调整搜索模式:
    <healthCheck>
      <cmd>pgrep -x java | xargs ps -o cmd= | grep -q "my-app-name.*jar" || exit 1</cmd>
    </healthCheck>
    
  • 改用pidof:如果Java进程的可执行文件名明确,使用pidof java检查进程存在性,再结合过滤确保是目标应用:
    <healthCheck>
      <cmd>pidof java && ps -p $(pidof java) -o cmd= | grep -q "my-app-name.*jar" || exit 1</cmd>
    </healthCheck>
    
  • 直接检查应用状态:如果应用提供了可检查的方式(比如生成特定PID文件、监听端口),优先使用更直接的健康检查方式:
    <healthCheck>
      <cmd>test -f /var/run/my-app.pid || exit 1</cmd>
    </healthCheck>
    

内容的提问来源于stack exchange,提问作者rmf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:40:31