From 5bfdd04f2171b6b1adfb34b05e4647069828a94c Mon Sep 17 00:00:00 2001 From: whm <973418690@qq.com> Date: Sat, 21 Mar 2026 23:57:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(nginx):=20Podman=20=E4=B8=8B=E5=BC=83?= =?UTF-8?q?=E7=94=A8=20127.0.0.11=20resolver=EF=BC=8C=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=89=8D=E7=AD=89=E5=BE=85=E4=B8=8A=E6=B8=B8=E5=8F=AF=E8=BE=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- docker-compose.yml | 3 +++ nginx/yuheng.docker.conf | 17 +++++-------- scripts/nginx-entrypoint-wait-dns.sh | 38 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 scripts/nginx-entrypoint-wait-dns.sh diff --git a/docker-compose.yml b/docker-compose.yml index fa241f1..bf48250 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,7 +54,10 @@ services: container_name: yh_nginx ports: - "443:443" + # Podman 无 Docker 的 127.0.0.11:勿在 nginx 里用 resolver+变量 proxy_pass。先等 web/admin/api 可解析再启动 nginx。 + entrypoint: ["/bin/sh", "/nginx-entrypoint-wait-dns.sh"] volumes: + - ./scripts/nginx-entrypoint-wait-dns.sh:/nginx-entrypoint-wait-dns.sh:ro - ./nginx/yuheng.docker.conf:/etc/nginx/conf.d/default.conf:ro - /etc/ssl/yh_web/yuheng.yuxindazhineng.com:/etc/ssl/yh_web/yuheng.yuxindazhineng.com:ro depends_on: diff --git a/nginx/yuheng.docker.conf b/nginx/yuheng.docker.conf index 88f5117..2fd123f 100644 --- a/nginx/yuheng.docker.conf +++ b/nginx/yuheng.docker.conf @@ -1,7 +1,8 @@ # 供 docker-compose 中 nginx 使用:仅监听 443,反代到 api/web/admin;证书挂载到 /etc/ssl/yh_web/yuheng.yuxindazhineng.com/ # -# 使用 resolver + 变量形式的 proxy_pass:避免启动时同步解析 upstream 主机名失败 -#(Docker/Podman 在 yh_nginx 刚起来时,内置 DNS 里可能还没有 web/admin/api,会报 host not found in upstream "web") +# 使用静态 proxy_pass(依赖 Compose/Podman 内置 DNS)。容器启动顺序由 depends_on + docker-compose.yml +# 中 entrypoint 等待脚本保证:解析就绪后再启动 nginx,避免「host not found in upstream」。 +# 勿配合 127.0.0.11 resolver + 变量 proxy_pass 用于 Podman:无该 DNS 时会导致长时间超时 → 502。 server { listen 443 ssl; @@ -10,9 +11,6 @@ server { server_name yuheng.yuxindazhineng.com; client_max_body_size 800m; - # Docker Compose 内置 DNS;若 Podman 下首包 502,可在此增加本网关 IP(podman network inspect 查看) - resolver 127.0.0.11 valid=10s ipv6=off; - ssl_certificate /etc/ssl/yh_web/yuheng.yuxindazhineng.com/fullchain.pem; ssl_certificate_key /etc/ssl/yh_web/yuheng.yuxindazhineng.com/privkey.pem; ssl_session_timeout 1d; @@ -21,8 +19,7 @@ server { ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; location / { - set $upstream_web web; - proxy_pass http://$upstream_web:80; + proxy_pass http://web:80; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -31,8 +28,7 @@ server { } location /admin/ { - set $upstream_admin admin; - proxy_pass http://$upstream_admin:80/; + proxy_pass http://admin:80/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -42,8 +38,7 @@ server { # 不要用尾部斜杠,否则 /api/health 会变成 /health,而后端注册的是 /api/health location /api/ { - set $upstream_api api; - proxy_pass http://$upstream_api:8088; + proxy_pass http://api:8088; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/scripts/nginx-entrypoint-wait-dns.sh b/scripts/nginx-entrypoint-wait-dns.sh new file mode 100644 index 0000000..89ae846 --- /dev/null +++ b/scripts/nginx-entrypoint-wait-dns.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# 供 yh_nginx 容器:在官方 entrypoint 之前等待 Compose/Podman 网络内 web/admin/api 可访问。 +# 解决 1) 启动瞬间 host not found;2) Podman 无 127.0.0.11 时勿用 resolver+变量 proxy_pass(否则 502/超时)。 +set -e +MAX="${NGINX_WAIT_UPSTREAM_SEC:-90}" +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 + return 0 + fi + ping -c1 -w3 "$host" >/dev/null 2>&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 + fi + ping_one "$host" +} + +n=0 +while [ "$n" -lt "$MAX" ]; do + # api 根路径常为 404,用 /api/health(与 yuheng.docker.conf 注释一致) + 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 + n=$((n + 1)) + sleep 1 +done +echo "yh_nginx: timeout waiting for web/admin/api (check 容器是否在同一网络、api 是否监听 8088)" >&2 +exit 1