树莓派3B+上Docker容器运行一段时间后healthcheck健康检查停止工作
问题现象
运行环境:Raspberry Pi 3 Model B Plus Rev 1.3,系统为所有软件包更新至最新版本的Raspberry Pi OS,Docker版本18.09.1,启用Swarm模式。
用户通过Docker容器运行SSH反向代理实现openhab远程访问,在部署栈的yml文件中配置了容器健康检查,期望健康检查失败时Swarm自动重启容器。
实际表现:容器启动后健康检查可正常运行30分钟左右(时长存在波动),之后无任何报错停止运行,即便容器实际状态异常也一直保持healthy状态,无法触发重启逻辑。
相关配置
健康检查配置
healthcheck: test: ["CMD-SHELL", "curl -f -s -o /dev/null https://my.domain.com/icon/none.png || exit 1"] start_period: 1m interval: 5s timeout: 2s retries: 3
Docker版本信息
Client: Version: 18.09.1 API version: 1.39 Go version: go1.11.6 Git commit: 4c52b90 Built: Fri, 13 Sep 2019 10:45:43 +0100 OS/Arch: linux/arm Experimental: false Server: Engine: Version: 18.09.1 API version: 1.39 (minimum version 1.12) Go version: go1.11.6 Git commit: 4c52b90 Built: Fri Sep 13 09:45:43 2019 OS/Arch: linux/arm Experimental: false
镜像Dockerfile
FROM alpine:3.11 RUN apk add --no-cache \ curl \ openssh-client \ ca-certificates \ bash COPY known_hosts /known_hosts COPY private_key /private_key RUN chmod 0400 /private_key COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT [ "/entrypoint.sh" ]
entrypoint.sh
#!/bin/bash ssh -Nn user@my.domain.com -i /private_key -o UserKnownHostsFile=/known_hosts -R 127.0.0.1:17280:openhab:8080
问题原因
- Docker版本过旧:18.09.1为2018年发布的版本,存在arm架构下健康检查进程僵死的已知bug,配套的runc 1.0.0~rc6为测试版本,稳定性不足,容易出现进程挂起导致健康检查停止运行。
- SSH连接无保活配置:长时间无流量的SSH连接会被网络中间设备断开,导致健康检查的curl请求卡住,触发Docker健康检查的timeout后进程泄漏,无法继续执行后续检查。
- 健康检查命令缺少超时控制:现有curl命令没有配置连接超时,网络异常时会导致curl进程僵死,占用健康检查的执行槽位,后续检查无法正常触发。
解决建议
- 优先升级Docker到最新稳定版:卸载现有旧版Docker,安装树莓派适配的最新稳定版Docker,同步升级runc、containerd等组件,可直接修复版本自带的健康检查bug。
- 优化健康检查命令:给curl增加连接超时参数,避免进程僵死:
test: ["CMD-SHELL", "curl -f -s --connect-timeout 1 -o /dev/null https://my.domain.com/icon/none.png || exit 1"] - 给SSH连接增加保活配置:修改entrypoint.sh的SSH命令,增加保活参数,连接异常时主动退出,触发容器重启:
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=2 -Nn user@my.domain.com -i /private_key -o UserKnownHostsFile=/known_hosts -R 127.0.0.1:17280:openhab:8080 - 临时绕过Docker健康检查:如果暂时无法升级Docker,可将健康检查逻辑集成到entrypoint.sh中,检查失败主动退出容器,绕过Docker自身的健康检查机制:
#!/bin/bash # 后台执行健康检查 ( sleep 60 while true; do curl -f -s --connect-timeout 1 -o /dev/null https://my.domain.com/icon/none.png || exit 1 sleep 5 done ) & # 前台运行SSH代理 ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=2 -Nn user@my.domain.com -i /private_key -o UserKnownHostsFile=/known_hosts -R 127.0.0.1:17280:openhab:8080 - 如需进一步排查,可开启Docker daemon的调试模式,查看/var/log/docker.log中的健康检查相关报错,定位具体异常点。
内容的提问来源于stack exchange,提问作者frapell
相关产品推荐
相关产品推荐

