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` 可以这么写:
```Dockerfile
FROM nginx
RUN apt-get update & & apt-get install -y curl & & rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
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
03e28eb00bd0 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
03e28eb00bd0 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 : 35 em ; \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"
}
```