给容器加一道“健康检查”:Docker HEALTHCHECK 从入门到避坑
很多服务“进程还在,服务已死”:端口监听着,但数据库连接池耗尽、死锁、依赖的接口一直超时,容器却始终显示 Up,负载均衡还继续往它身上送流量。Docker 的 HEALTHCHECK 就是为这种“假活”准备的:让容器自己定期证明它真的能干活,而不是仅仅还活着。
最简单的写法是在 Dockerfile 里加一行:
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://127.0.0.1:8080/health || exit 1
四个参数各有分工。interval 是检查间隔,太短会给业务添负担,太长则发现故障太慢,30 秒是个稳妥的起点。timeout 是单次检查的超时,接口本身慢就别把超时设得比接口还苛刻,否则健康检查先把自己“查死”。start-period 是启动宽限期,应用刚启动、缓存还没预热时不计失败,避免容器一起步就被判死刑。retries 是连续失败几次才算不健康,单次抖动不应直接触发重启或摘流。
健康检查的命令要选“真正代表业务可用”的探针。只检查进程存在没有意义,pgrep 返回成功时服务可能早已不能响应;只检查端口监听也不够,端口在监听、请求却全部 500 同样算假活。正确的做法是调一个轻量的业务探针:HTTP 服务用 /health,数据库用一条只读查询,缓存用一次 PING。探针要轻、要幂等、不要产生副作用——在健康检查里写数据、发短信、调外部付费接口,都是在给自己埋雷。
状态变化后要让它产生实际效果。docker ps 里 healthy/unhealthy 只是结果,真正起作用的是编排层:Docker Compose 的 depends_on: condition: service_healthy 可以让依赖服务等数据库真正就绪再启动,避免“先启动、先报错、先重启”的死循环;Swarm 和 Kubernetes 则用健康状态决定是否继续送流量、不健康的副本会被摘掉而不是继续接单。只加 HEALTHCHECK 却不接编排策略,等于装了烟雾报警器却不接消防水带。
有几个坑值得提前知道。第一,健康检查跑在容器内部,curl、wget 这类工具不一定在精简镜像里,Alpine 镜像默认没有 curl,要么装上,要么改用自带工具写探针。第二,检查命令失败会留下日志和退出码,调试时用 docker inspect 看 Health 段的 Log,比猜要快。第三,不要在健康检查里依赖外部服务:检查本服务时顺带检查第三方接口,一旦第三方抖动,自己的容器会跟着被判不健康,故障面反而扩大了。第四,健康检查不是万能的,内存泄漏、慢查询这类渐进式恶化,单靠“这次请求通没通”很难提前发现,需要配合指标和日志一起看。
一句话总结:进程存活不等于服务可用。给容器加一个轻量、真实、不依赖外部的健康检查,再让编排层根据健康状态做启动顺序和流量决策,这道检查才算真正落地。明天可以顺手检查一下自己跑着的容器:有 HEALTHCHECK 的有几个,探针查的是端口还是业务,答案往往比想象中更值得改。
- 点赞
- 收藏
- 关注作者
评论(0)