diff --git a/docker-compose.yml b/docker-compose.yml index eb68330..ec7664d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -121,9 +121,11 @@ services: volumes: # :Z 供 Podman/SELinux 可读;纯 Docker 也兼容 - ./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: TZ: Asia/Shanghai + NGINX_ENTRYPOINT_LOCAL_RESOLVERS: "1" networks: default: aliases: diff --git a/docs/README.md b/docs/README.md index b2b9dba..b4425c9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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` | | Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` | | LLM Key | `.env` | `./reload-config.sh ai` | diff --git a/nginx/README.md b/nginx/README.md index 5a34e9c..59323b6 100644 --- a/nginx/README.md +++ b/nginx/README.md @@ -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` | | Gateway | `gateway/etc/gateway.docker.yaml` | `./reload-config.sh gateway` | | LLM / 视觉 | `.env` | `./reload-config.sh ai` | diff --git a/scripts/lib-aijz-deploy.sh b/scripts/lib-aijz-deploy.sh index 9823d90..94dcf21 100755 --- a/scripts/lib-aijz-deploy.sh +++ b/scripts/lib-aijz-deploy.sh @@ -136,18 +136,14 @@ install_host_nginx_site_conf() { } reload_web_nginx() { - local cid - cid="$(compose_cmd ps -q web 2>/dev/null | head -1)" - if [ -z "$cid" ]; then - echo "web 容器未运行,跳过 reload" >&2 + # compose 挂的是 templates:改 conf 后需 recreate 才会重新 envsubst + echo "重建 web 容器以应用 nginx 模板 ..." + if compose_cmd up -d --force-recreate web; then + echo "web 容器已 recreate(nginx.conf.template)" + else + echo "web 重建失败" >&2 return 1 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() { @@ -362,23 +358,24 @@ healthcheck() { local gw_port web_port 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}")" - echo "等待 gateway(:$gw_port) / web(:$web_port) ..." + echo "等待 gateway(:$gw_port) / web(:$web_port) 及 web→gateway 代理 ..." 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 \ - && 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 break fi # 中途补拉 web(常见:nginx 启动时 DNS 未就绪已退出) 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 sleep 2 done if [ "$ok" -eq 1 ]; then echo "健康检查通过." 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 compose_cmd exec -T postgres psql -U platform -d platform -c 'ALTER USER platform CREATEDB;' >/dev/null 2>&1 || true } diff --git a/web/nginx.conf b/web/nginx.conf index dd03a98..99af148 100644 --- a/web/nginx.conf +++ b/web/nginx.conf @@ -1,7 +1,5 @@ -# Podman/Docker:静态 proxy_pass 会在启动时解析 upstream;gateway 尚未进 DNS 时会 emerg 退出。 -# 变量 + resolver 改为请求时解析;127.0.0.11=Docker 内置 DNS,10.89.0.1=常见 Podman aardvark。 -resolver 127.0.0.11 10.89.0.1 valid=10s ipv6=off; - +# Dockerfile / 非 compose 场景:静态 upstream(启动时须能解析 gateway)。 +# compose 生产请用 nginx.conf.template + NGINX_ENTRYPOINT_LOCAL_RESOLVERS。 server { listen 80; server_name _; @@ -9,8 +7,7 @@ server { index index.html; location /api/ { - set $gw_upstream gateway:8180; - proxy_pass http://$gw_upstream; + proxy_pass http://gateway:8180; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -20,8 +17,7 @@ server { } location /ai/ { - set $gw_upstream gateway:8180; - proxy_pass http://$gw_upstream; + proxy_pass http://gateway:8180; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Authorization $http_authorization; @@ -29,8 +25,7 @@ server { } location /gateway/ { - set $gw_upstream gateway:8180; - proxy_pass http://$gw_upstream; + proxy_pass http://gateway:8180; proxy_http_version 1.1; proxy_set_header Host $host; } diff --git a/web/nginx.conf.template b/web/nginx.conf.template new file mode 100644 index 0000000..012a165 --- /dev/null +++ b/web/nginx.conf.template @@ -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; + } +}