fix(nginx): 启动时从 resolv.conf 注入 resolver + tpl 生成配置,修复 Podman host not found api

Made-with: Cursor
This commit is contained in:
whm
2026-03-22 01:34:23 +08:00
parent 7c9649356a
commit 948494bca0
6 changed files with 102 additions and 65 deletions

View File

@@ -1,8 +1,6 @@
#!/bin/sh
# yh_nginx 容器:在官方 entrypoint 之前等待 Compose/Podman 网络内 web/admin/api 可访问。
# 解决 1) 启动瞬间 host not found2) Podman 无 127.0.0.11 时勿用 resolver+变量 proxy_pass否则 502/超时)
#
# 探测顺序HTTP(wget) → TCP(nc) → ICMP(ping)。部分环境禁 ping 或 busybox wget 异常时nc 仍可判定「能连上端口」。
# yh_nginx1) 等 web/admin/api 就绪 2) 从 /etc/resolv.conf 取 nameserver 写入 resolver
# 3) 由 tpl 生成 default.conf变量 proxy_pass避免 Podman 在「探测已通过」后仍 host not found in upstream "api"
set -e
MAX="${NGINX_WAIT_UPSTREAM_SEC:-120}"
DEBUG="${NGINX_WAIT_DEBUG:-0}"
@@ -23,7 +21,6 @@ ping_one() {
ping -c1 -w3 "$host" >/dev/null 2>&1
}
# 仅测端口是否打开(不依赖 HTTP 状态码)
tcp_open() {
host="$1"
port="$2"
@@ -33,7 +30,6 @@ tcp_open() {
nc -z -w3 "$host" "$port" 2>/dev/null
}
# HTTP 成功2xx/3xxbusybox wget 遇 404 会非 0故 API 必须用会返回 200 的路径
http_ok() {
host="$1"
port="$2"
@@ -41,7 +37,6 @@ http_ok() {
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
@@ -70,21 +65,53 @@ upstream_ok() {
n=0
while [ "$n" -lt "$MAX" ]; do
# 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;'
break
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 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
if [ "$n" -ge "$MAX" ]; then
echo "yh_nginx: timeout after ${MAX}s." >&2
exit 1
fi
echo "yh_nginx: upstream OK, generating nginx config..."
# 与容器内实际 DNS 一致Podman 常非 127.0.0.11);多个 nameserver 空格分隔(兼容 IPv6
NSLINE=""
while read -r line; do
case "$line" in
nameserver\ *)
ip=${line#nameserver }
ip=${ip%%#*}
# trim
ip=$(echo "$ip" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[ -z "$ip" ] && continue
NSLINE="${NSLINE}${NSLINE:+ }${ip}"
;;
esac
done < /etc/resolv.conf
if [ -z "$NSLINE" ]; then
NSLINE="127.0.0.11"
echo "yh_nginx: warn: no nameserver in resolv.conf, fallback ${NSLINE}" >&2
else
echo "yh_nginx: resolver from resolv.conf: ${NSLINE}" >&2
fi
if [ ! -r /yuheng.docker.conf.tpl ]; then
echo "yh_nginx: error: /yuheng.docker.conf.tpl not mounted" >&2
exit 1
fi
# sed 用 | 分隔,避免 IPv6 里 : 干扰(当前仍支持多 IPv4 nameserver
sed "s|@@NGINX_RESOLVER@@|${NSLINE}|g" /yuheng.docker.conf.tpl > /etc/nginx/conf.d/default.conf
nginx -t
echo "yh_nginx: starting nginx..."
exec nginx -g 'daemon off;'