Background
通常情况下,我们会使用一个容器运行一种服务,比如一个容器运行数据库服务,一个容器作为web服务器等等, 因此一个容器被setup起来并不能代表其中的服务毫无问题,因此如何check容器中的服务器是否正常才是最重要的问题。
容器的状态
我们都知道,通过docker ps
你可以看到所有正在运行的容器,以及容器的部分信息:
[图片上传失败...(image-f10236-1555504132810)]
有两个列是需要关注的:
COMMAND:
通常为了容器中的service正常启动,我们会使用CMD/ENTRYPOINT
设置一段指令。容器启动之后,通常会根据 Dockerfile 中的 CMD 或 ENTRYPOINT 启动一个进程,Command描述的就是这个进程执行的指令。-
STATUS
描述的是当前容器的状态,以及容器在多久之前进入这样的状态。也可以说他描述的是上面COMMAND
指令执行的情况。命令显示:
有的容器正在运行,状态为 UP。
有的容器已经正常停止了,状态是 Exited (0)。或者说
COMMAND执行的指令正常退出
有的则因发生故障停止了,退出代码为非 0,例如 Exited (137)、Exited (1) 等。
虽然,我们通常会通过CMD、ENTRYPOINT
设置COMMAND
指令是容器server的启动指令,我们也能通过STATUS
看到启动指令是否执行成功。但是及时COMMAND没有出错STATUS是up
也不能等同于这个server可以提供服务
Health Check
What
Docker允许指定一个命令作为health check
命令,Docker可以通过这个指令执行的成功与否来判定容器当前的状态。
Docker 支持的 Health Check 可以是任何一个单独的命令,Docker 会在容器中执行该命令,如果返回 0,容器被认为是 healthy,如果返回 1,则为 unhealthy。
当一个容器有指定健康检查 (HEALTHCHECK) 时,它除了普通的容器状态之外,还有:
-
starting
: Initial status when the container is still starting -
healthy
: 如果health check成功 -
unhealthy
: If a single run of the takes longer than the specified timeout then it is considered unhealthy. If a health check fails then the will run retries number of times and will be declared unhealthy if the still fails.
这些状态你可以通过docker ps
看到。
how to check health
In Dockerfile
- 给镜像设置HEALTHCHECK
HEALTHCHECK [option] CMD <command>
- command是HEAlthcheck的指令:如果你的service是restful api,指令可以是
curl heartbeat api
- option:
- --interval=<interval>: 两次健康检查命令执行的间隔时间. default value 是 30 seconds.
- --timeout=<interval>: 设置某一个次health check执行的timeout时间,一旦超时代表这一次healthcheck失败. default value 是 30 seconds.
- --retries=<number of times>: 设置health check连续失败次数一旦达到设置的值容器状态就会变成
unhealthy
. default value 是 3. - --start-period=<interval>: The initialization time of application startup. Failed health check during the startup is not counted. The default value is 0 second (introduced since version 17.05).
- command是HEAlthcheck的指令:如果你的service是restful api,指令可以是
Note
The HEALTHCHECK 只能在Dockerfile中出现一次,如果你设置了多次,那么就会直接使用最后一个命令
- 如果本身镜像中有HEALTHCHECK,下面的指令可以禁止HEALTHCHECK
HEALTHCHECK NONE
一旦容器被正常启动,初始状态就是starting
. Docker engine会自动的根据你设定的--interval
, 每个interval
时间运行一次这个health check command, 并且根据每次运行的结果及时的update你的容器的status
举个例子:
FROM elasticsearch:5.5
HEALTHCHECK --interval=5s --timeout=2s --retries=12 \
CMD curl --silent --fail localhost:9200/_cluster/health || exit 1
In docker compose
docker compose 2.1版本之后才支持health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
- test: 定义了health check的指令,只能是string或者一个list。如果是list,第一个参数只能是
NONE, CMD or CMD-SHELL
healthcheck:
test: curl -f https://localhost || exit 1
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
可以使用如下指令disable掉image的healthcheck
healthcheck:
disable: true