build(docker): Private mode deployment test successful

Test steps:
bash docker/scripts/generate-config.sh --mode private [--local-ip 192.168.0.113]
bash ./deploy.sh --mode private

Front-end directly inlines NEXT_PUBLIC_API_URL, directly connecting to the backend.
CORS (production) supports comma-separated multiple origins, with localhost and local network IPs included by default.
This commit is contained in:
david_bai
2025-09-28 15:54:01 +08:00
parent cfcd60145a
commit 2ee6961634
8 changed files with 2274 additions and 4524 deletions
+3 -3
View File
@@ -5,9 +5,9 @@ ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ENV http_proxy=${HTTP_PROXY} \
https_proxy=${HTTPS_PROXY} \
no_proxy=${NO_PROXY}
ENV http_proxy ${HTTP_PROXY} \
https_proxy ${HTTPS_PROXY} \
no_proxy ${NO_PROXY}
WORKDIR /app
COPY package*.json ./
+15 -2
View File
@@ -9,11 +9,24 @@ const DEV_ORIGINS = [
/^http:\/\/192\.168\.\d+\.\d+:3002$/, // LAN addresses with new port
];
// 解析生产环境下的多来源配置(逗号分隔)
const parseProdOrigins = (): string | RegExp | (string | RegExp)[] => {
const v = CONFIG.CORS_ORIGIN?.trim();
if (!v) return DEV_ORIGINS; // 回退到开发白名单
if (v.includes(",")) {
return v
.split(",")
.map((s) => s.trim())
.filter(Boolean);
}
return v;
};
// Configure CORS
export const corsOptions: CorsOptions =
CONFIG.NODE_ENV === "production"
? {
origin: CONFIG.CORS_ORIGIN,
origin: parseProdOrigins(),
methods: ["GET", "POST", "OPTIONS"],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization"],
@@ -28,7 +41,7 @@ export const corsOptions: CorsOptions =
export const corsWSOptions =
CONFIG.NODE_ENV === "production"
? {
origin: CONFIG.CORS_ORIGIN, // Allowed origin, replace with your Next.js application's URL
origin: parseProdOrigins(),
methods: ["GET", "POST"],
credentials: true,
}
+1 -1
View File
@@ -225,7 +225,7 @@ deploy_services() {
# 构建镜像
log_info "构建Docker镜像..."
docker-compose build --no-cache --parallel
docker-compose build --parallel
# 启动服务
log_info "启动服务..."
+7 -3
View File
@@ -45,7 +45,7 @@ services:
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
test: ["CMD", "node", "health-check.js"]
interval: 30s
timeout: 10s
retries: 3
@@ -60,6 +60,10 @@ services:
- HTTP_PROXY=${HTTP_PROXY}
- HTTPS_PROXY=${HTTPS_PROXY}
- NO_PROXY=${NO_PROXY}
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
- NEXT_PUBLIC_TURN_HOST=${NEXT_PUBLIC_TURN_HOST}
- NEXT_PUBLIC_TURN_USERNAME=${NEXT_PUBLIC_TURN_USERNAME}
- NEXT_PUBLIC_TURN_PASSWORD=${NEXT_PUBLIC_TURN_PASSWORD}
container_name: privydrop-frontend
restart: unless-stopped
environment:
@@ -75,11 +79,11 @@ services:
networks:
- privydrop-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3002/api/health"]
test: ["CMD", "node", "health-check.js"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
start_period: 120s
# Nginx反向代理
nginx:
+3 -2
View File
@@ -54,7 +54,8 @@ generate_env_file() {
fi
# 计算不同部署模式下的访问入口
local cors_origin="http://${LOCAL_IP}:3002"
# 同时支持 localhost 与 本机IP,两者都可用于浏览器访问,便于Docker直连或本机调试
local cors_origin="http://${LOCAL_IP}:3002,http://localhost:3002"
local api_url="http://${LOCAL_IP}:3001"
local ssl_mode="self-signed"
local turn_enabled="false"
@@ -66,7 +67,7 @@ generate_env_file() {
local next_public_turn_password=""
if [[ "$DEPLOYMENT_MODE" == "public" ]]; then
cors_origin="http://${DOMAIN_NAME:-$LOCAL_IP}"
cors_origin="http://${DOMAIN_NAME:-$LOCAL_IP},http://localhost"
api_url="$cors_origin"
turn_enabled="true"
elif [[ "$DEPLOYMENT_MODE" == "full" ]]; then
+18 -3
View File
@@ -4,10 +4,20 @@ FROM node:18-alpine AS builder
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_TURN_HOST
ARG NEXT_PUBLIC_TURN_USERNAME
ARG NEXT_PUBLIC_TURN_PASSWORD
ENV http_proxy=${HTTP_PROXY} \
https_proxy=${HTTPS_PROXY} \
no_proxy=${NO_PROXY}
ENV http_proxy ${HTTP_PROXY} \
https_proxy ${HTTPS_PROXY} \
no_proxy ${NO_PROXY}
# 前端构建期注入可公开环境变量(用于客户端直连后端与 TURN)
ENV NEXT_PUBLIC_API_URL ${NEXT_PUBLIC_API_URL}
ENV NEXT_PUBLIC_TURN_HOST ${NEXT_PUBLIC_TURN_HOST}
ENV NEXT_PUBLIC_TURN_USERNAME ${NEXT_PUBLIC_TURN_USERNAME}
ENV NEXT_PUBLIC_TURN_PASSWORD ${NEXT_PUBLIC_TURN_PASSWORD}
WORKDIR /app
# 复制package文件
@@ -62,3 +72,8 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
# 启动应用
CMD ["node", "server.js"]
# 运行期保留公开变量(非必需,但便于服务端渲染读取)
ENV NEXT_PUBLIC_API_URL ${NEXT_PUBLIC_API_URL}
ENV NEXT_PUBLIC_TURN_HOST ${NEXT_PUBLIC_TURN_HOST}
ENV NEXT_PUBLIC_TURN_USERNAME ${NEXT_PUBLIC_TURN_USERNAME}
ENV NEXT_PUBLIC_TURN_PASSWORD ${NEXT_PUBLIC_TURN_PASSWORD}
+9 -9
View File
@@ -24,8 +24,8 @@
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.4",
"@types/negotiator": "^0.6.3",
"@types/node": "^20",
"@types/react-dom": "^18",
"@types/node": "^20.14.13",
"@types/react-dom": "^18.3.0",
"@types/unist": "^3.0.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@@ -39,8 +39,8 @@
"next-mdx-remote": "^5.0.0",
"next-themes": "^0.3.0",
"qrcode.react": "^4.0.1",
"react": "^18",
"react-dom": "^18",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-intersection-observer": "^9.16.0",
"remark-gfm": "^4.0.0",
"sharp": "^0.33.5",
@@ -52,11 +52,11 @@
"zustand": "^5.0.7"
},
"devDependencies": {
"@types/react": "^18.3.18",
"eslint": "^8",
"@types/react": "^18.3.22",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.5",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"postcss": "^8.4.40",
"tailwindcss": "^3.4.7",
"typescript": "^5.5.4"
}
}
+2218 -4501
View File
File diff suppressed because it is too large Load Diff