feat(deploy): 宿主机单 Nginx 方案、compose 覆盖与启动脚本

Made-with: Cursor
This commit is contained in:
whm
2026-03-27 11:15:00 +08:00
parent 2f78fd0d52
commit 38c4c465c5
4 changed files with 209 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# 与 docker-compose.yml 合并使用:宿主机 Nginx 独占 443 时,不要启动容器 yh_nginx。
# 并为 api / web / admin 绑定本机回环端口,供宿主机 Nginx 反代(见 nginx/yuheng.host.conf
#
# docker compose -f docker-compose.yml -f docker-compose.host-nginx.yml up -d
#
# 容器内 Nginx旧方案需显式启用 profile
# docker compose --profile compose-internal-nginx up -d
services:
api:
ports:
- "127.0.0.1:8088:8088"
web:
ports:
- "127.0.0.1:9080:80"
admin:
ports:
- "127.0.0.1:9081:80"
nginx:
profiles:
- compose-internal-nginx

View File

@@ -80,3 +80,35 @@ sudo systemctl start nginx
- **要求**:托管 **web 前台** 的站点必须使用 **`try_files $uri $uri/ /index.html;`**(见仓库 `nginx/web.conf``web/Dockerfile` 内嵌配置)。若你自建 Nginx请对照修改后再 `nginx -t` 并重载。 - **要求**:托管 **web 前台** 的站点必须使用 **`try_files $uri $uri/ /index.html;`**(见仓库 `nginx/web.conf``web/Dockerfile` 内嵌配置)。若你自建 Nginx请对照修改后再 `nginx -t` 并重载。
- **应用内 404**:在 SPA 已正确回退的前提下,未在后台发布的路径会由前端路由进入 **「页面不存在」** 页(`NotFound.vue`),与上述 nginx 404 不同。 - **应用内 404**:在 SPA 已正确回退的前提下,未在后台发布的路径会由前端路由进入 **「页面不存在」** 页(`NotFound.vue`),与上述 nginx 404 不同。
- **Compose 部署**`web` 容器实际加载的是 **`deploy/web/default.conf`**(见 `docker-compose.yml` 挂载)。若线上仍对 `/test` 等返回 **nginx 404**,请把仓库里最新的 `deploy/web/default.conf` 同步到服务器对应路径后,执行 `docker compose restart web`(或重建 `yh_web` 容器)。 - **Compose 部署**`web` 容器实际加载的是 **`deploy/web/default.conf`**(见 `docker-compose.yml` 挂载)。若线上仍对 `/test` 等返回 **nginx 404**,请把仓库里最新的 `deploy/web/default.conf` 同步到服务器对应路径后,执行 `docker compose restart web`(或重建 `yh_web` 容器)。
## 6. 单实例:仅宿主机 Nginx推荐一台机一个 443 入口)
不再使用容器 **`yh_nginx`**,由**宿主机 Nginx** 监听 **443**,把流量转到本机回环上的 **`web` / `admin` / `api` 容器**。
1. **证书**:同上,放在 `/etc/ssl/yh_web/yuheng.yuxindazhineng.com/`
2. **合并 Compose**(为容器绑定回环端口,并禁用 compose 内 Nginx
```bash
docker compose -f docker-compose.yml -f docker-compose.host-nginx.yml up -d mongo api web admin
```
3. **一键脚本**(启动容器 + 写入宿主机站点配置并重载 Nginx
```bash
chmod +x scripts/start-with-host-nginx.sh
./scripts/start-with-host-nginx.sh
```
脚本会把 `nginx/yuheng.host.conf` 中的 `__VERIFY_ROOT__` 替换为项目下 `verify-root` 绝对路径,并写入 `/etc/nginx/conf.d/yuheng.yuxindazhineng.com.conf`(需 **sudo**)。若不想自动改 Nginx`INSTALL_NGINX_CONF=0 ./scripts/start-with-host-nginx.sh`
4. **回环端口约定**(与 `nginx/yuheng.host.conf` 一致):
| 服务 | 本机地址 |
|------|----------|
| API | `127.0.0.1:8088` |
| 前台静态 | `127.0.0.1:9080` |
| 后台静态 | `127.0.0.1:9081` |
5. **若仍要用容器里的 yh_nginx**(旧方案):`docker compose --profile compose-internal-nginx up -d`,此时会与宿主机抢 **443**,二选一。
6. **与「方式 B8443」的区别**:方式 B 是「宿主机 Nginx → 容器 Nginx → 各服务」两层;本节是「宿主机 Nginx → 各服务」**一层**,不再起 `yh_nginx`

105
nginx/yuheng.host.conf Normal file
View File

@@ -0,0 +1,105 @@
# 宿主机 Nginx 单实例443 终止 TLS反代到本机回环上的 Docker 服务(见 docker-compose.host-nginx.yml
# 部署:
# 1. 证书:/etc/ssl/yh_web/yuheng.yuxindazhineng.com/{fullchain.pem,privkey.pem}
# 2. 替换下方 __VERIFY_ROOT__ 为项目内 verify-root 的绝对路径(或由 start-with-host-nginx.sh 生成 .conf
# 3. sudo cp yuheng.host.conf /etc/nginx/conf.d/yuheng.yuxindazhineng.com.conf
# 4. sudo nginx -t && sudo systemctl reload nginx
# HTTP → HTTPS
server {
listen 80;
listen [::]:80;
server_name yuheng.yuxindazhineng.com;
return 301 https://$server_name$request_uri;
}
upstream yh_admin_upstream {
server 127.0.0.1:9081;
keepalive 8;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yuheng.yuxindazhineng.com;
client_max_body_size 800m;
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;
ssl_session_cache shared:SSL:50m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# 域名/证书等验证文件(与 compose 内 yh_nginx 行为一致)
location ~ ^/[A-Za-z0-9._-]+\.(txt|html|xml)$ {
root __VERIFY_ROOT__;
try_files $uri =404;
default_type text/plain;
add_header Cache-Control "no-store";
}
location = /admin {
return 301 /admin/;
}
location /api/web/live/ws {
proxy_pass http://127.0.0.1:8088;
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 X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
location /api/web/live/danmaku/ws {
proxy_pass http://127.0.0.1:8088;
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 X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
location /api/ {
proxy_pass http://127.0.0.1:8088;
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 X-Forwarded-Proto $scheme;
proxy_connect_timeout 75s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffering off;
}
location /admin/ {
proxy_pass http://yh_admin_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 X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://127.0.0.1:9080;
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 X-Forwarded-Proto $scheme;
proxy_connect_timeout 75s;
proxy_send_timeout 75s;
proxy_read_timeout 75s;
}
}

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# 宿主机 Nginx 单实例部署:启动 api/web/admin/mongo不启动容器 yh_nginx并可选安装站点配置后 reload。
# 用法(在项目根目录):
# chmod +x scripts/start-with-host-nginx.sh
# ./scripts/start-with-host-nginx.sh
#
# 依赖:已安装 Docker Compose、宿主机 Nginx、证书目录 /etc/ssl/yh_web/yuheng.yuxindazhineng.com/
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
echo "==> 启动容器mongo api web admin不启动 compose 内 yh_nginx"
docker compose -f docker-compose.yml -f docker-compose.host-nginx.yml up -d mongo api web admin
echo "==> 若曾用旧方案启动过 yh_nginx可手动停止释放 443 docker rm -f yh_nginx 2>/dev/null || true"
docker rm -f yh_nginx 2>/dev/null || true
VERIFY_ROOT="${VERIFY_ROOT:-$ROOT/verify-root}"
mkdir -p "$VERIFY_ROOT"
CONF_OUT="${NGINX_CONF_OUT:-/etc/nginx/conf.d/yuheng.yuxindazhineng.com.conf}"
TEMPLATE="$ROOT/nginx/yuheng.host.conf"
if [[ ! -f "$TEMPLATE" ]]; then
echo "缺少模板:$TEMPLATE" >&2
exit 1
fi
echo "==> 生成宿主机 Nginx 配置VERIFY_ROOT=$VERIFY_ROOT"
if [[ "${INSTALL_NGINX_CONF:-1}" == "1" ]]; then
if ! command -v sudo >/dev/null 2>&1; then
echo "未找到 sudo请手动执行" >&2
echo " sed \"s|__VERIFY_ROOT__|$VERIFY_ROOT|g\" \"$TEMPLATE\" | sudo tee \"$CONF_OUT\"" >&2
echo " sudo nginx -t && sudo systemctl reload nginx" >&2
exit 0
fi
sed "s|__VERIFY_ROOT__|$VERIFY_ROOT|g" "$TEMPLATE" | sudo tee "$CONF_OUT" >/dev/null
sudo nginx -t
sudo systemctl reload nginx
echo "==> 已写入 $CONF_OUT 并重载 Nginx。请确认 443 仅由宿主机占用: ss -tlnp | grep 443"
else
echo "已跳过安装INSTALL_NGINX_CONF=0。可手动"
echo " sed \"s|__VERIFY_ROOT__|$VERIFY_ROOT|g\" nginx/yuheng.host.conf | sudo tee $CONF_OUT"
echo " sudo nginx -t && sudo systemctl reload nginx"
fi
echo "==> 本机回环端口(宿主机 Nginx 应反代到这些地址,与 nginx/yuheng.host.conf 一致):"
echo " API http://127.0.0.1:8088"
echo " 前台 http://127.0.0.1:9080"
echo " 后台 http://127.0.0.1:9081"