fix: web API 502 — use Podman-local DNS for gateway proxy
Mount nginx template with NGINX_LOCAL_RESOLVERS and require web→gateway health in deploy checks. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -121,9 +121,11 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# :Z 供 Podman/SELinux 可读;纯 Docker 也兼容
|
# :Z 供 Podman/SELinux 可读;纯 Docker 也兼容
|
||||||
- ./web/dist:/usr/share/nginx/html:ro,Z
|
- ./web/dist:/usr/share/nginx/html:ro,Z
|
||||||
- ./web/nginx.conf:/etc/nginx/conf.d/default.conf:ro,Z
|
# 走官方 templates + envsubst,注入容器 /etc/resolv.conf 里的 DNS
|
||||||
|
- ./web/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro,Z
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
|
NGINX_ENTRYPOINT_LOCAL_RESOLVERS: "1"
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
aliases:
|
aliases:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
| 改什么 | 文件 | 命令 |
|
| 改什么 | 文件 | 命令 |
|
||||||
|--------|------|------|
|
|--------|------|------|
|
||||||
| 容器反代 | `web/nginx.conf` | `./reload-config.sh web` |
|
| 容器反代 | `web/nginx.conf.template`(compose) | `./reload-config.sh web` |
|
||||||
| 公开 URL / 发布回执 | `.env` 的 `AIJZ_PUBLIC_BASE_URL` + `platform/etc/platform.docker.yaml` | `./reload-config.sh platform` |
|
| 公开 URL / 发布回执 | `.env` 的 `AIJZ_PUBLIC_BASE_URL` + `platform/etc/platform.docker.yaml` | `./reload-config.sh platform` |
|
||||||
| Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` |
|
| Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` |
|
||||||
| LLM Key | `.env` | `./reload-config.sh ai` |
|
| LLM Key | `.env` | `./reload-config.sh ai` |
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ AI 建站默认用 **Docker web 容器**(`127.0.0.1:5173`)对外提供页面
|
|||||||
|
|
||||||
| 用途 | 仓库路径 | 生效方式 |
|
| 用途 | 仓库路径 | 生效方式 |
|
||||||
|------|----------|----------|
|
|------|----------|----------|
|
||||||
| 容器 Web 反代 | `web/nginx.conf` | `./reload-config.sh web` |
|
| 容器 Web 反代 | `web/nginx.conf.template` | `./reload-config.sh web` |
|
||||||
| Platform | `platform/etc/platform.docker.yaml` | `./reload-config.sh platform` |
|
| Platform | `platform/etc/platform.docker.yaml` | `./reload-config.sh platform` |
|
||||||
| Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` |
|
| Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` |
|
||||||
| LLM / 视觉 | `.env` | `./reload-config.sh ai` |
|
| LLM / 视觉 | `.env` | `./reload-config.sh ai` |
|
||||||
|
|||||||
@@ -136,18 +136,14 @@ install_host_nginx_site_conf() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reload_web_nginx() {
|
reload_web_nginx() {
|
||||||
local cid
|
# compose 挂的是 templates:改 conf 后需 recreate 才会重新 envsubst
|
||||||
cid="$(compose_cmd ps -q web 2>/dev/null | head -1)"
|
echo "重建 web 容器以应用 nginx 模板 ..."
|
||||||
if [ -z "$cid" ]; then
|
if compose_cmd up -d --force-recreate web; then
|
||||||
echo "web 容器未运行,跳过 reload" >&2
|
echo "web 容器已 recreate(nginx.conf.template)"
|
||||||
|
else
|
||||||
|
echo "web 重建失败" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
run_sudo docker exec "$cid" nginx -t >/dev/null 2>&1 || {
|
|
||||||
echo "错误: 容器内 nginx -t 失败" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
run_sudo docker exec "$cid" nginx -s reload
|
|
||||||
echo "web 容器 nginx 已 reload(web/nginx.conf)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restart_service() {
|
restart_service() {
|
||||||
@@ -362,23 +358,24 @@ healthcheck() {
|
|||||||
local gw_port web_port
|
local gw_port web_port
|
||||||
gw_port="$(publish_host_port "${AIJZ_GATEWAY_PUBLISH:-127.0.0.1:8180}")"
|
gw_port="$(publish_host_port "${AIJZ_GATEWAY_PUBLISH:-127.0.0.1:8180}")"
|
||||||
web_port="$(publish_host_port "${AIJZ_WEB_PUBLISH:-127.0.0.1:5173}")"
|
web_port="$(publish_host_port "${AIJZ_WEB_PUBLISH:-127.0.0.1:5173}")"
|
||||||
echo "等待 gateway(:$gw_port) / web(:$web_port) ..."
|
echo "等待 gateway(:$gw_port) / web(:$web_port) 及 web→gateway 代理 ..."
|
||||||
for i in $(seq 1 60); do
|
for i in $(seq 1 60); do
|
||||||
if curl -fsS --max-time 2 "http://127.0.0.1:${gw_port}/gateway/health" >/dev/null 2>&1 \
|
if curl -fsS --max-time 2 "http://127.0.0.1:${gw_port}/gateway/health" >/dev/null 2>&1 \
|
||||||
&& curl -fsS --max-time 2 "http://127.0.0.1:${web_port}/" >/dev/null 2>&1; then
|
&& curl -fsS --max-time 2 "http://127.0.0.1:${web_port}/" >/dev/null 2>&1 \
|
||||||
|
&& curl -fsS --max-time 2 "http://127.0.0.1:${web_port}/gateway/health" >/dev/null 2>&1; then
|
||||||
ok=1
|
ok=1
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
# 中途补拉 web(常见:nginx 启动时 DNS 未就绪已退出)
|
# 中途补拉 web(常见:nginx 启动时 DNS 未就绪已退出)
|
||||||
if [ $((i % 10)) -eq 0 ]; then
|
if [ $((i % 10)) -eq 0 ]; then
|
||||||
compose_cmd up -d web >/dev/null 2>&1 || true
|
compose_cmd up -d --force-recreate web >/dev/null 2>&1 || compose_cmd up -d web >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
if [ "$ok" -eq 1 ]; then
|
if [ "$ok" -eq 1 ]; then
|
||||||
echo "健康检查通过."
|
echo "健康检查通过."
|
||||||
else
|
else
|
||||||
echo "警告: 健康检查超时,请查看: docker compose -f $ROOT/docker-compose.yml logs" >&2
|
echo "警告: 健康检查超时(含 web 反代 /gateway/health),请查看: docker compose -f $ROOT/docker-compose.yml logs web gateway" >&2
|
||||||
fi
|
fi
|
||||||
compose_cmd exec -T postgres psql -U platform -d platform -c 'ALTER USER platform CREATEDB;' >/dev/null 2>&1 || true
|
compose_cmd exec -T postgres psql -U platform -d platform -c 'ALTER USER platform CREATEDB;' >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Podman/Docker:静态 proxy_pass 会在启动时解析 upstream;gateway 尚未进 DNS 时会 emerg 退出。
|
# Dockerfile / 非 compose 场景:静态 upstream(启动时须能解析 gateway)。
|
||||||
# 变量 + resolver 改为请求时解析;127.0.0.11=Docker 内置 DNS,10.89.0.1=常见 Podman aardvark。
|
# compose 生产请用 nginx.conf.template + NGINX_ENTRYPOINT_LOCAL_RESOLVERS。
|
||||||
resolver 127.0.0.11 10.89.0.1 valid=10s ipv6=off;
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name _;
|
||||||
@@ -9,8 +7,7 @@ server {
|
|||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
location /api/ {
|
location /api/ {
|
||||||
set $gw_upstream gateway:8180;
|
proxy_pass http://gateway:8180;
|
||||||
proxy_pass http://$gw_upstream;
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
@@ -20,8 +17,7 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location /ai/ {
|
location /ai/ {
|
||||||
set $gw_upstream gateway:8180;
|
proxy_pass http://gateway:8180;
|
||||||
proxy_pass http://$gw_upstream;
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header Authorization $http_authorization;
|
proxy_set_header Authorization $http_authorization;
|
||||||
@@ -29,8 +25,7 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location /gateway/ {
|
location /gateway/ {
|
||||||
set $gw_upstream gateway:8180;
|
proxy_pass http://gateway:8180;
|
||||||
proxy_pass http://$gw_upstream;
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
}
|
}
|
||||||
|
|||||||
41
web/nginx.conf.template
Normal file
41
web/nginx.conf.template
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# 请求时解析 gateway(避免启动时 DNS 未就绪导致 emerg)。
|
||||||
|
# ${NGINX_LOCAL_RESOLVERS} 由官方入口在 NGINX_ENTRYPOINT_LOCAL_RESOLVERS 开启时从 /etc/resolv.conf 注入。
|
||||||
|
resolver ${NGINX_LOCAL_RESOLVERS} valid=10s ipv6=off;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
set $gw_upstream gateway:8180;
|
||||||
|
proxy_pass http://$gw_upstream;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Authorization $http_authorization;
|
||||||
|
client_max_body_size 64m;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ai/ {
|
||||||
|
set $gw_upstream gateway:8180;
|
||||||
|
proxy_pass http://$gw_upstream;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header Authorization $http_authorization;
|
||||||
|
client_max_body_size 64m;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /gateway/ {
|
||||||
|
set $gw_upstream gateway:8180;
|
||||||
|
proxy_pass http://$gw_upstream;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user