Dockerfile入口点执行Curl调用Grafana API报错:连接被拒绝
问题原因与解决方案
问题核心
你的grafana-bootstrap-post容器启动时执行curl命令失败,手动进入容器执行却成功,原因很明确:Docker Compose的depends_on仅保证依赖的容器启动,不保证容器内的服务完全就绪。grafana容器启动后,Grafana服务需要加载配置、初始化数据库,这个过程需要时间,此时3000端口还未对外开放,所以curl连接被拒绝;等你手动进入容器时,Grafana早已完成初始化,端口正常监听,所以调用成功。
可行解决方案
方案1:在bootstrap.sh中添加重试逻辑
给curl命令加上循环重试,直到成功或达到最大次数,这是最直接的修改方式:
#!/bin/bash MAX_RETRIES=20 RETRY_DELAY=5 # 循环重试调用Grafana API for ((attempt=1; attempt<=MAX_RETRIES; attempt++)); do echo "[$(date)] 尝试连接Grafana API (第 $attempt/$MAX_RETRIES 次)" curl -X POST -H "Content-Type: application/json" -d '{"name":"Algo Quant"}' http://admin:admin@grafana:3000/api/orgs # 检查curl执行结果,成功则退出脚本 if [ $? -eq 0 ]; then echo "[$(date)] Grafana API调用成功" exit 0 fi echo "[$(date)] 连接失败,$RETRY_DELAY秒后重试..." sleep $RETRY_DELAY done # 重试耗尽仍失败,退出并返回错误码 echo "[$(date)] 重试$MAX_RETRIES次后仍无法连接Grafana API" exit 1
方案2:给Grafana配置健康检查,让depends_on等待服务就绪
在Docker Compose的grafana服务中添加健康检查规则,同时修改grafana-bootstrap-post的depends_on条件,让它等待Grafana服务真正就绪:
services: grafana: image: grafana/grafana:9.2.3 ports: - 3000:3000 restart: unless-stopped volumes: - _volume__ops_monitoring_grafana:/var/lib/grafana - $PWD/config/plugins/:/var/lib/grafana/plugins/ - $PWD/config/_ops_monitoring_grafana/provisioning/current/:/etc/grafana/provisioning/ #- $PWD/config/_ops_monitoring_grafana/grafana.ini:/etc/grafana/grafana.ini depends_on: - "grafana-bootstrap-pre" # 添加健康检查,检测Grafana API是否就绪 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 5s # 每5秒检查一次 timeout: 5s # 超时时间5秒 retries: 10 # 最多重试10次 start_period: 10s # 启动后等待10秒再开始检查 grafana-bootstrap-post: build: context: $PWD dockerfile: .hack/build/docker/post/Dockerfile env_file: - $PWD/config/__envrc.d/grafana-bootstrap-post.envrcd volumes: - $PWD/config/_ops_monitoring_grafana/provisioning.default/:/etc/grafana/provisioning/provisioning.default/ - $PWD/config/_ops_monitoring_grafana/provisioning/current/:/etc/grafana/provisioning/current/ depends_on: # 等待grafana服务健康检查通过后再启动 grafana: condition: service_healthy
方案3:使用wait-for-it脚本等待端口就绪
给grafana-bootstrap-post容器加入wait-for-it脚本,先等待Grafana的3000端口开放,再执行你的bootstrap.sh:
修改grafana-bootstrap-post的Dockerfile
FROM ubuntu:20.04 COPY config/scripts/bootstrap.sh . RUN apt-get update && apt-get -y install curl wget \ && wget -O /wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh \ && chmod +x /wait-for-it.sh \ && apt-get clean && rm -rf /var/lib/apt/lists/* # 先等待grafana:3000端口就绪,再执行bootstrap脚本 ENTRYPOINT ["/bin/bash", "-c", "/wait-for-it.sh grafana:3000 -- ./bootstrap.sh --run"]
验证方法
修改完成后,重新启动所有服务:
docker-compose down && docker-compose up --build
此时grafana-bootstrap-post容器内的curl命令应该能成功调用Grafana API。
内容的提问来源于stack exchange,提问作者Danny Murphy
相关产品推荐
相关产品推荐

