go微服务实现docker健康检查自愈,关键在于三要素协同:独立http.server暴露/health与/ready端点避免中间件干扰;healthcheck命令真实反映业务依赖状态;配合restart: on-failure与service_healthy依赖条件触发真正重启。

Go微服务要靠Docker健康检查实现自愈,关键不是加个HEALTHCHECK就完事,而是让/health端点不被框架干扰、命令能真实反映业务状态、重启策略能真正触发——三者缺一不可。
Go程序必须用独立http.Server暴露/health
很多Go服务把/health挂在主路由上(比如gin的r.GET("/health", ...)),但Docker的curl -f http://localhost:8080/health请求是从宿主机namespace发来的,不经过中间件、也不走反向代理逻辑。一旦主服务还没启动完成,或中间件卡住(如JWT鉴权失败、CORS拦截),健康检查就直接超时失败。
- 单独起一个轻量
http.Server,绑定固定端口(如:8081),只注册/health和/ready - 别复用主服务的
http.ServeMux,避免日志、熔断、限流等中间件影响响应延迟和确定性 - 用
go func() { http.ListenAndServe(":8081", healthMux) }()异步启动,别阻塞主线程 - 容器退出前,需捕获
SIGTERM并主动关闭这个健康server,否则docker stop会超时强制杀掉
docker-compose.yml里healthcheck和restart必须配对
健康检查本身只改容器状态(healthy/unhealthy),不会自动重启。没配restart策略,再准的检查也白搭。
- 用
restart: on-failure,它会在退出码非0或被标记为unhealthy时重启;别用unless-stopped,它不响应健康状态变化 -
start_period必须设,尤其对Go服务——Spring Boot、Gin、Echo初始化DB连接池、加载配置常需20~60秒,没这个参数,健康检查一上来就失败,导致反复重启循环 - 示例配置中
interval: 30s和timeout: 5s要满足timeout ,否则探测任务会堆积 - 如果服务依赖DB,
depends_on得写成condition: service_healthy,否则上游DB容器状态是running但实际还没ready,下游Go服务一连就崩
Go的/health和/ready必须语义分离
Docker只支持一个HEALTHCHECK命令,但Kubernetes里livenessProbe和readinessProbe是两个独立配置。Go代码里混用同一端点,会导致就绪失败时被误杀,或存活卡死却还在接流量。
-
/health只检查进程存活:能否响应HTTP、goroutine没panic、监听端口正常——不查DB、Redis等外部依赖 -
/ready必须验证关键依赖:用db.QueryContext(ctx, "SELECT 1")代替db.Ping(),用redis.Ping(ctx)带超时,检查gRPC下游是否可连通 - 所有依赖检查都要设上下文超时(比如
context.WithTimeout(ctx, 2*time.Second)),避免一个慢依赖拖垮整个健康检查 - 别在
/ready里做耗时操作(如全表count、生成PDF),超时设短(2~3秒),否则滚动更新会被卡住
健康检查命令不能只测端口或进程
用nc -z localhost 8080或ps aux | grep myapp这类命令,只能确认端口开了、进程活着,但Go服务可能已OOM、goroutine死锁、DB连接池耗尽——此时状态仍是healthy,流量照进,故障扩散。
- HTTP服务必须调
curl -f http://localhost:8081/health,且后端返回200 OK+ 简单body(如"ok") - gRPC服务优先用
grpc_health_probe -addr=localhost:50051,它走官方grpc.health.v1.Health协议,比nc靠谱得多 - 命令里必须带
-f(curl)或明确判断退出码,|| exit 1不能省,否则Docker收不到失败信号 - 生产环境建议在健康检查脚本里加失败计数器,5分钟内连续重启超3次就停自愈,写日志并告警——避免掩盖内存泄漏或配置错误
最易被忽略的是start_period和condition: service_healthy这两处。冷启动抖动和依赖就绪顺序,才是Go微服务在Docker里反复重启的真正元凶,不是健康检查写得不够花哨。











