适用于nginx容器的Docker healthcheck

时间:2018-02-13 21:36:21

标签: docker nginx docker-compose

我有一个项目使用Docker Hub中的官方nginx docker容器,通过Docker Compose启动。我在Docker Compose中为每个容器配置了健康检查,最近这个nginx容器的健康检查表现得很奇怪;在使用docker-compose up -d启动时,我的所有容器都会启动,并开始运行运行状况检查,但nginx容器看起来似乎从不运行运行状况检查。如果我docker exec进入容器,我可以手动运行脚本,如果我重新启动容器,运行状况检查会正常运行。

docker ps的输出示例:

CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                            PORTS                                                                       NAMES
458a55ae8971        my_custom_image           "/tini -- /usr/local…"   7 minutes ago       Up 7 minutes (healthy)                                                                                        project_worker_1
5024781b1a73        redis:3.2                 "docker-entrypoint.s…"   7 minutes ago       Up 7 minutes (healthy)            127.0.0.1:6379->6379/tcp                                                    project_redis_1
bd405dde8ce7        postgres:9.6              "docker-entrypoint.s…"   7 minutes ago       Up 7 minutes (healthy)            127.0.0.1:15432->5432/tcp                                                   project_postgres_1
93e15c18d879        nginx:mainline            "nginx -g 'daemon of…"   7 minutes ago       Up 7 minutes (health: starting)   127.0.0.1:80->80/tcp, 127.0.0.1:443->443/tcp                                nginx

来自docker inspect nginx的示例(部分,为简洁起见):

    "State": {
        "Status": "running",
        "Running": true,
        "Paused": false,
        "Restarting": false,
        "OOMKilled": false,
        "Dead": false,
        "Pid": 11568,
        "ExitCode": 0,
        "Error": "",
        "StartedAt": "2018-02-13T21:04:22.904241169Z",
        "FinishedAt": "0001-01-01T00:00:00Z",
        "Health": {
            "Status": "unhealthy",
            "FailingStreak": 0,
            "Log": []
        }
    },

定义docker-compose.yml容器的nginx部分:

nginx:
  image: nginx:mainline
  # using container_name means there will only ever be one nginx container!
  container_name: nginx
  restart: always
  networks:
    - proxynet
  volumes:
    - /etc/nginx/conf.d
    - /etc/nginx/vhost.d
    - /usr/share/nginx/html
    - tlsdata:/etc/nginx/certs:ro
    - attachdata:/usr/share/nginx/html/uploads:ro
    - staticdata:/usr/share/nginx/html/static:ro
    - ./nginx/healthcheck.sh:/bin/healthcheck.sh
  healthcheck:
    test: ['CMD', '/bin/healthcheck.sh']
    interval: 1m
    timeout: 5s
    retries: 3
  ports:
    # Make the http/https ports available on the Docker host IPv4 loopback interface
    - '127.0.0.1:80:80'
    - '127.0.0.1:443:443'

healthcheck.sh我正在加载一个卷:

#!/bin/bash

service nginx status || exit 1

看起来这个问题只是一个问题,当容器最初启动时,systemd永远不会从状态检查返回,同时配置的运行状况检查超时不会触发。其他一切正常,nginx已启动并响应,但健康检查能够正常运行,而无需每次启动时都需要手动重启。

我的配置中是否缺少某些内容,或者我可以运行更好的检查?

4 个答案:

答案 0 :(得分:3)

对于官方的高山nginx图像,您也可以执行以下操作:

# replace "" with NA
datnew[] = lapply(datnew, function(x) {x[x == ""] <- NA; return(x)})

# order each column
datnew[] <- lapply(datnew, function(x) x[order(is.na(x))])

# short result - remove rows with any NA values
na.omit(datnew)

# long result - remove rows that are all NA, skipping the first column
datnew[!apply(is.na(datnew[-1]), 1, all), ]

wget是标准映像的一部分。这样做是将index.html / php /任何地方下载到任何地方(/ dev / null),它将超时并且失败。

答案 1 :(得分:2)

我尝试了相同的脚本并遇到了同样的问题。我将healthcheck.sh更改为改为:

#!/bin/bash

if service nginx status; then
    exit 0
else
    exit 1
fi

在docker容器中运行它会导致成功的运行状况检查。

答案 2 :(得分:1)

我认为在这种情况下不需要自定义脚本。

尝试将您的健康检查测试更改为

test: ["CMD", "service", "nginx", "status"]

对我来说很好。

尝试以"代替',以防万一:)

编辑

如果您真的想强制使用exit 1,则在失败的情况下,可以使用:

test: service nginx status || exit 1

答案 3 :(得分:0)

一年后,我找到了解决方案。首先,要进一步澄清环境,我认为正在发生的事情,并推测Docker引擎可能存在的错误。

我现在正在使用的Compose文件正在启动“官方” Alpine NGINX映像的轻度修改版本,该映像使用COPY加载到运行状况检查脚本中,并在映像中显式添加HEALTHCHECK。该映像用于nginx服务,并与运行jwilder/docker-gen的映像配合使用,以使用来自Docker的容器元数据来生成NGINX配置文件。该容器作为名为nginx-gen的服务运行。容器更改时,将重新生成配置,如果有更改,则会将SIGHUP发送到nginx服务。

我发现的是以下内容:

  • 如果所有服务一起启动,则nginx服务将永远不会运行运行状况检查;
  • 如果nginx服务在启动后不久重新启动,则运行状况检查将正常完成;
  • 如果nginx服务本身是启动的,则运行状况检查会正常完成;
  • 如果同时启动nginx-gen以外的所有服务,则运行状况检查会正常完成;
  • 如果所有服务一起启动,但是在执行任何操作之前将nginx-gen修改为sleep 60,则运行状况检查会正常完成;

因此,似乎与信号处理,Docker和NGINX之间存在一些晦涩的交互。如果将SIGHUP发送到容器中的之前中的NGINX进程,则第一次运行状况检查将在该容器中运行,则不会运行任何状况检查。

我想出的最后一个迭代方法是修改nginx-gen容器以轮询nginx容器的运行状况。它以短循环sleep循环查找带有已定义标签的容器的健康状态。 nginx容器报告运行状况良好后,nginx-gen继续生成配置文件。我还将通知方法更改为docker exec脚本,以显式测试并重新加载nginx容器中的配置,而不是依靠SIGHUP

最终结果:我可以docker-compose up -d,所有内容最终都报告healthy,而无需进一步干预。成功!