部署脚本

This commit is contained in:
wanghai
2026-07-20 13:46:08 +08:00
parent ba4d74a23f
commit 5cc55f7f03
6 changed files with 541 additions and 162 deletions

View File

@@ -30,6 +30,7 @@ http {
fastcgi_temp_path /var/lib/nginx/tmp/fastcgi;
uwsgi_temp_path /var/lib/nginx/tmp/uwsgi;
scgi_temp_path /var/lib/nginx/tmp/scgi;
resolver 127.0.0.11 valid=10s ipv6=off;
gzip on;
gzip_vary on;
@@ -172,7 +173,8 @@ http {
# 代理到独立的 Web 前端 Nuxt 服务监听3000端口
location / {
proxy_pass http://ecshopx-web-frontend:3000;
set $web_frontend http://ecshopx-web-frontend:3000;
proxy_pass $web_frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';

View File

@@ -6,6 +6,8 @@ APP_DIR="/data/httpd/ECShopX_web-frontend"
BUILD_FILE="$APP_DIR/.output/server/index.mjs"
LOG_FILE="/var/log/nuxt.log"
WAIT_INTERVAL="${NUXT_WAIT_INTERVAL:-10}"
PUBLIC_API_BASE="${NUXT_PUBLIC_API_BASE:-http://localhost:8080/api/h5app}"
INTERNAL_API_BASE="${NUXT_INTERNAL_API_BASE:-${NUXT_API_BASE:-http://ecshopx-dev:8080/api/h5app}}"
export TZ="${TZ:-Asia/Shanghai}"
export NITRO_HOST=0.0.0.0
@@ -18,6 +20,93 @@ cd "$APP_DIR" || {
exit 1
}
start_local_api_proxy() {
node <<'NODE_PROXY' &
const http = require('http')
const https = require('https')
const publicBase = process.env.NUXT_PUBLIC_API_BASE || 'http://localhost:8080/api/h5app'
const internalBase =
process.env.NUXT_INTERNAL_API_BASE ||
process.env.NUXT_API_BASE ||
'http://ecshopx-dev:8080/api/h5app'
let publicUrl
let internalUrl
try {
publicUrl = new URL(publicBase)
internalUrl = new URL(internalBase)
} catch (error) {
console.error(`[SSR API Proxy] API URL 解析失败: ${error.message}`)
process.exit(0)
}
const localHosts = new Set(['localhost', '127.0.0.1', '::1'])
if (!localHosts.has(publicUrl.hostname)) {
console.log(`[SSR API Proxy] NUXT_PUBLIC_API_BASE=${publicBase} 不是本机地址,跳过本地转发`)
process.exit(0)
}
const listenHost = publicUrl.hostname === '::1' ? '::1' : '127.0.0.1'
const listenPort = Number(publicUrl.port || (publicUrl.protocol === 'https:' ? 443 : 80))
const publicPath = publicUrl.pathname.replace(/\/+$/, '') || '/'
const internalPath = internalUrl.pathname.replace(/\/+$/, '') || '/'
const transport = internalUrl.protocol === 'https:' ? https : http
function joinTargetPath(requestPath) {
const suffix = requestPath.startsWith(publicPath) ? requestPath.slice(publicPath.length) : requestPath
const normalizedSuffix = suffix.startsWith('/') ? suffix : `/${suffix}`
return `${internalPath}${normalizedSuffix}`.replace(/\/{2,}/g, '/')
}
const server = http.createServer((req, res) => {
const incomingUrl = new URL(req.url || '/', publicUrl)
const headers = { ...req.headers, host: internalUrl.host }
const targetPath = `${joinTargetPath(incomingUrl.pathname)}${incomingUrl.search}`
const proxyReq = transport.request(
{
protocol: internalUrl.protocol,
hostname: internalUrl.hostname,
port: internalUrl.port || (internalUrl.protocol === 'https:' ? 443 : 80),
method: req.method,
path: targetPath,
headers,
},
(proxyRes) => {
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers)
proxyRes.pipe(res)
}
)
proxyReq.on('error', (error) => {
console.error(`[SSR API Proxy] ${req.method} ${targetPath} -> ${error.message}`)
if (!res.headersSent) {
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' })
}
res.end('Bad Gateway')
})
req.pipe(proxyReq)
})
server.on('error', (error) => {
if (error.code === 'EADDRINUSE') {
console.log(`[SSR API Proxy] ${listenHost}:${listenPort} 已被占用,跳过本地转发`)
return
}
console.error(`[SSR API Proxy] 启动失败: ${error.message}`)
})
server.listen(listenPort, listenHost, () => {
console.log(`[SSR API Proxy] http://${listenHost}:${listenPort}${publicPath} -> ${internalBase}`)
})
NODE_PROXY
}
export NUXT_PUBLIC_API_BASE="$PUBLIC_API_BASE"
export NUXT_INTERNAL_API_BASE="$INTERNAL_API_BASE"
start_local_api_proxy
echo "等待 Nuxt 生产构建产物: $BUILD_FILE"
while [ ! -f "$BUILD_FILE" ]; do
echo "未找到构建产物,${WAIT_INTERVAL} 秒后重试(可先运行 dev-setup.sh 完成编译)..."