From 5830fdfba3f57b181a0f63d9b269c377faa01735 Mon Sep 17 00:00:00 2001 From: whm <973418690@qq.com> Date: Sun, 22 Mar 2026 00:42:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(nginx):=20=E7=AD=89=E5=BE=85=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E5=A2=9E=E5=8A=A0=20nc/TCP=20=E6=8E=A2=E6=B5=8B?= =?UTF-8?q?=E3=80=81=E9=BB=98=E8=AE=A4=20120s=E3=80=81compose=20=E8=AE=BE?= =?UTF-8?q?=20180s=20=E9=81=BF=E5=85=8D=20Podman=20=E4=B8=8B=20yh=5Fnginx?= =?UTF-8?q?=20=E8=B6=85=E6=97=B6=E9=80=80=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- docker-compose.yml | 3 ++ scripts/nginx-entrypoint-wait-dns.sh | 66 +++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index bf48250..91680d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,6 +64,9 @@ services: - api - web - admin + # Podman/慢盘:API 首次就绪可能超过 90s,避免 yh_nginx 等待超时后 Exited(1) → 全站 443 拒绝连接 + environment: + - NGINX_WAIT_UPSTREAM_SEC=180 networks: - yh_net diff --git a/scripts/nginx-entrypoint-wait-dns.sh b/scripts/nginx-entrypoint-wait-dns.sh index 89ae846..1a2436b 100644 --- a/scripts/nginx-entrypoint-wait-dns.sh +++ b/scripts/nginx-entrypoint-wait-dns.sh @@ -1,11 +1,20 @@ #!/bin/sh # 供 yh_nginx 容器:在官方 entrypoint 之前等待 Compose/Podman 网络内 web/admin/api 可访问。 # 解决 1) 启动瞬间 host not found;2) Podman 无 127.0.0.11 时勿用 resolver+变量 proxy_pass(否则 502/超时)。 +# +# 探测顺序:HTTP(wget) → TCP(nc) → ICMP(ping)。部分环境禁 ping 或 busybox wget 异常时,nc 仍可判定「能连上端口」。 set -e -MAX="${NGINX_WAIT_UPSTREAM_SEC:-90}" +MAX="${NGINX_WAIT_UPSTREAM_SEC:-120}" +DEBUG="${NGINX_WAIT_DEBUG:-0}" + +log() { + if [ "$DEBUG" = "1" ] || [ "$DEBUG" = "true" ]; then + echo "yh_nginx(wait): $*" >&2 + fi +} + echo "yh_nginx: waiting for upstream (web:80 admin:80 api:8088), max ${MAX}s..." -# 优先 HTTP 探测(ICMP 在部分环境被禁);无 wget 时用 ping ping_one() { host="$1" if ping -c1 -W2 "$host" >/dev/null 2>&1; then @@ -14,25 +23,68 @@ ping_one() { ping -c1 -w3 "$host" >/dev/null 2>&1 } +# 仅测端口是否打开(不依赖 HTTP 状态码) +tcp_open() { + host="$1" + port="$2" + if ! command -v nc >/dev/null 2>&1; then + return 1 + fi + nc -z -w3 "$host" "$port" 2>/dev/null +} + +# HTTP 成功(2xx/3xx);busybox wget 遇 404 会非 0,故 API 必须用会返回 200 的路径 +http_ok() { + host="$1" + port="$2" + path="${3:-/}" + if ! command -v wget >/dev/null 2>&1; then + return 1 + fi + # -T:秒;部分镜像仅支持短选项 + if wget -q -O/dev/null -T 5 "http://${host}:${port}${path}" 2>/dev/null; then + return 0 + fi + return 1 +} + upstream_ok() { host="$1" port="$2" path="${3:-/}" - if command -v wget >/dev/null 2>&1; then - wget -q -O/dev/null -T 3 "http://${host}:${port}${path}" 2>/dev/null && return 0 + + if http_ok "$host" "$port" "$path"; then + log "http OK ${host}:${port}${path}" + return 0 fi - ping_one "$host" + if tcp_open "$host" "$port"; then + log "tcp OK ${host}:${port}" + return 0 + fi + if ping_one "$host"; then + log "ping OK $host (HTTP/TCP 未验证,仅 DNS/L3)" + return 0 + fi + return 1 } n=0 while [ "$n" -lt "$MAX" ]; do - # api 根路径常为 404,用 /api/health(与 yuheng.docker.conf 注释一致) + # api 用 /api/health 保证 wget 为 200 if upstream_ok web 80 / && upstream_ok admin 80 / && upstream_ok api 8088 /api/health; then echo "yh_nginx: upstream OK, starting nginx..." exec /docker-entrypoint.sh nginx -g 'daemon off;' fi + + # 每 15s 打一行,便于 docker logs 排查 + if [ "$n" -gt 0 ] && [ $((n % 15)) -eq 0 ]; then + echo "yh_nginx: still waiting... ${n}s / max ${MAX}s (web admin api)" >&2 + fi + n=$((n + 1)) sleep 1 done -echo "yh_nginx: timeout waiting for web/admin/api (check 容器是否在同一网络、api 是否监听 8088)" >&2 + +echo "yh_nginx: timeout after ${MAX}s. 调试: docker logs yh_nginx;或临时 export NGINX_WAIT_UPSTREAM_SEC=300" >&2 +echo "yh_nginx: 可设 NGINX_WAIT_DEBUG=1 查看每步探测;确认 yh_api 内 curl -s http://127.0.0.1:8088/api/health" >&2 exit 1