2016-11-25 18:02:43 +00:00
# # # HEALTHCHECK 健康检查
格式 :
* ` HEALTHCHECK [选项] CMD <命令> ` : 设置检查容器健康状况的命令
* ` HEALTHCHECK NONE ` : 如果基础镜像有健康检查指令 , 使用这行可以屏蔽掉其健康检查指令
` HEALTHCHECK ` 指令是告诉 Docker 应该如何进行判断容器的状态是否正常 , 这是 Docker 1.12 引入的新指令 。
在没有 ` HEALTHCHECK ` 指令前 , Docker 引擎只可以通过容器内主进程是否退出来判断容器是否状态异常 。 很多情况下这没问题 , 但是如果程序进入死锁状态 , 或者死循环状态 , 应用进程并不退出 , 但是该容器已经无法提供服务了 。 在 1.12 以前 , Docker 不会检测到容器的这种状态 , 从而不会重新调度 , 导致可能会有部分容器已经无法提供服务了却还在接受用户请求 。
而自 1.12 之后 , Docker 提供了 ` HEALTHCHECK ` 指令 , 通过该指令指定一行命令 , 用这行命令来判断容器主进程的服务状态是否还正常 , 从而比较真实的反应容器实际状态 。
当在一个镜像指定了 ` HEALTHCHECK ` 指令后 , 用其启动容器 , 初始状态会为 ` starting ` , 在 ` HEALTHCHECK ` 指令检查成功后变为 ` healthy ` , 如果连续一定次数失败 , 则会变为 ` unhealthy ` 。
` HEALTHCHECK ` 支持下列选项 :
2016-12-15 01:42:50 +00:00
* ` --interval=<间隔> ` : 两次健康检查的间隔 , 默认为 30 秒 ;
2016-11-25 18:02:43 +00:00
* ` --timeout=<时长> ` : 健康检查命令运行超时时间 , 如果超过这个时间 , 本次健康检查就被视为失败 , 默认 30 秒 ;
* ` --retries=<次数> ` : 当连续失败指定次数后 , 则将容器状态视为 ` unhealthy ` , 默认 3 次 。
和 ` CMD ` , ` ENTRYPOINT ` 一样 , ` HEALTHCHECK ` 只可以出现一次 , 如果写了多个 , 只有最后一个生效 。
在 ` HEALTHCHECK [选项] CMD ` 后面的命令 , 格式和 ` ENTRYPOINT ` 一样 , 分为 ` shell ` 格式 , 和 ` exec ` 格式 。 命令的返回值决定了该次健康检查的成功与否 : ` 0 ` : 成功 ; ` 1 ` : 失败 ; ` 2 ` : 保留 , 不要使用这个值 。
假设我们有个镜像是个最简单的 Web 服务 , 我们希望增加健康检查来判断其 Web 服务是否在正常工作 , 我们可以用 ` curl ` 来帮助判断 , 其 ` Dockerfile ` 的 ` HEALTHCHECK ` 可以这么写 :
2019-10-29 06:31:45 +00:00
` ` ` docker
2016-11-25 18:02:43 +00:00
FROM nginx
RUN apt - get update && apt - get install - y curl && rm - rf / var / lib / apt / lists / *
HEALTHCHECK -- interval = 5 s -- timeout = 3 s \
CMD curl - fs http : //localhost/ || exit 1
` ` `
这里我们设置了每 5 秒检查一次 ( 这里为了试验所以间隔非常短 , 实际应该相对较长 ) , 如果健康检查命令超过 3 秒没响应就视为失败 , 并且使用 ` curl -fs http://localhost/ || exit 1 ` 作为健康检查命令 。
使用 ` docker build ` 来构建这个镜像 :
` ` ` bash
$ docker build - t myweb : v1 .
` ` `
构建好了后 , 我们启动一个容器 :
` ` ` bash
$ docker run - d -- name web - p 80 : 80 myweb : v1
` ` `
2018-01-15 14:00:53 +00:00
当运行该镜像后 , 可以通过 ` docker container ls ` 看到最初的状态为 ` (health: starting) ` :
2016-11-25 18:02:43 +00:00
` ` ` bash
2018-01-15 14:00:53 +00:00
$ docker container ls
2016-11-25 18:02:43 +00:00
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e28 eb00bd0 myweb : v1 "nginx -g 'daemon off" 3 seconds ago Up 2 seconds ( health : starting ) 80 / tcp , 443 / tcp web
` ` `
2018-01-15 14:00:53 +00:00
在等待几秒钟后 , 再次 ` docker container ls ` , 就会看到健康状态变化为了 ` (healthy) ` :
2016-11-25 18:02:43 +00:00
` ` ` bash
2018-01-15 14:00:53 +00:00
$ docker container ls
2016-11-25 18:02:43 +00:00
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e28 eb00bd0 myweb : v1 "nginx -g 'daemon off" 18 seconds ago Up 16 seconds ( healthy ) 80 / tcp , 443 / tcp web
` ` `
如果健康检查连续失败超过了重试次数 , 状态就会变为 ` (unhealthy) ` 。
为了帮助排障 , 健康检查命令的输出 ( 包括 ` stdout ` 以及 ` stderr ` ) 都会被存储于健康状态里 , 可以用 ` docker inspect ` 来查看 。
` ` ` bash
$ docker inspect -- format ' { { json . State . Health } } ' web | python - m json . tool
{
"FailingStreak" : 0 ,
"Log" : [
{
"End" : "2016-11-25T14:35:37.940957051Z" ,
"ExitCode" : 0 ,
"Output" : "<!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\n body {\n width: 35em;\n margin: 0 auto;\n font-family: Tahoma, Verdana, Arial, sans-serif;\n }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n" ,
"Start" : "2016-11-25T14:35:37.780192565Z"
}
] ,
"Status" : "healthy"
}
` ` `