docker_practice/image/dockerfile/healthcheck.md
Kang HuaiShuai c788212aad
Use vuepress build book
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 19:15:33 +08:00

84 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### 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` 支持下列选项
* `--interval=<间隔>`两次健康检查的间隔默认为 30
* `--timeout=<时长>`健康检查命令运行超时时间如果超过这个时间本次健康检查就被视为失败默认 30
* `--retries=<次数>`当连续失败指定次数后则将容器状态视为 `unhealthy`默认 3
`CMD`, `ENTRYPOINT` 一样`HEALTHCHECK` 只可以出现一次如果写了多个只有最后一个生效
`HEALTHCHECK [选项] CMD` 后面的命令格式和 `ENTRYPOINT` 一样分为 `shell` 格式 `exec` 格式命令的返回值决定了该次健康检查的成功与否`0`成功`1`失败`2`保留不要使用这个值
假设我们有个镜像是个最简单的 Web 服务我们希望增加健康检查来判断其 Web 服务是否在正常工作我们可以用 `curl` 来帮助判断 `Dockerfile` `HEALTHCHECK` 可以这么写
```docker
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
```
当运行该镜像后可以通过 `docker container ls` 看到最初的状态为 `(health: starting)`
```bash
$ docker container ls
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
```
在等待几秒钟后再次 `docker container ls`就会看到健康状态变化为了 `(healthy)`
```bash
$ docker container ls
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: 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"
}
```