build: refresh docker deployment workflow
This commit is contained in:
+7
-1
@@ -60,6 +60,12 @@ next-env.d.ts
|
||||
# Build output
|
||||
dist/
|
||||
|
||||
# Generated docker assets
|
||||
docker/ssl/
|
||||
docker/nginx/
|
||||
docker/coturn/
|
||||
logs/
|
||||
|
||||
# Temporary files
|
||||
.temp/
|
||||
.tmp/
|
||||
.tmp/
|
||||
|
||||
+6
-5
@@ -41,7 +41,7 @@ PrivyDrop (原 SecureShare) 是一个基于 WebRTC 的开源点对点(P2P)
|
||||
|
||||
### 🐳 Docker 一键部署 (推荐)
|
||||
|
||||
**零配置,5分钟完成部署!支持内网使用,无需公网IP。**
|
||||
**零配置,5 分钟完成部署!支持内网使用,无需公网 IP。**
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
@@ -52,13 +52,14 @@ cd PrivyDrop
|
||||
bash deploy.sh
|
||||
|
||||
# 访问应用
|
||||
# http://localhost:3000
|
||||
# http://localhost:3002
|
||||
```
|
||||
|
||||
**部署优势**:
|
||||
- ✅ 部署时间: 60分钟 → 5分钟
|
||||
- ✅ 技术门槛: Linux运维 → 会用Docker即可
|
||||
- ✅ 环境要求: 公网IP → 内网即可使用
|
||||
|
||||
- ✅ 部署时间: 60 分钟 → 5 分钟
|
||||
- ✅ 技术门槛: Linux 运维 → 会用 Docker 即可
|
||||
- ✅ 环境要求: 公网 IP → 内网即可使用
|
||||
- ✅ 成功率: 70% → 95%+
|
||||
|
||||
详见: [Docker 部署指南](./docs/DEPLOYMENT_docker.zh-CN.md)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
.npm
|
||||
.env*
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
coverage
|
||||
.nyc_output
|
||||
logs
|
||||
*.log
|
||||
+28
-31
@@ -1,44 +1,41 @@
|
||||
# 使用官方Node.js 18 Alpine镜像作为基础镜像
|
||||
FROM node:18-alpine AS base
|
||||
# 构建阶段
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
ARG HTTP_PROXY
|
||||
ARG HTTPS_PROXY
|
||||
ARG NO_PROXY
|
||||
|
||||
ENV http_proxy=${HTTP_PROXY} \
|
||||
https_proxy=${HTTPS_PROXY} \
|
||||
no_proxy=${NO_PROXY}
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 安装构建依赖和运行时工具
|
||||
RUN apk add --no-cache \
|
||||
curl \
|
||||
dumb-init \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# 复制package文件
|
||||
COPY package*.json ./
|
||||
|
||||
# 安装依赖
|
||||
RUN npm ci --only=production && npm cache clean --force
|
||||
|
||||
# 复制源代码
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
|
||||
# 构建TypeScript代码
|
||||
RUN npm run build
|
||||
|
||||
# 创建非root用户
|
||||
# 运行阶段
|
||||
FROM node:18-alpine AS runtime
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 复制预构建的文件
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/package.json ./
|
||||
COPY health-check.js ./
|
||||
|
||||
# 创建用户并设置权限
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S backend -u 1001 -G nodejs
|
||||
adduser -S backend -u 1001 -G nodejs && \
|
||||
chown -R backend:nodejs /app
|
||||
|
||||
# 更改文件所有权
|
||||
RUN chown -R backend:nodejs /app
|
||||
USER backend
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 3001
|
||||
|
||||
# 健康检查
|
||||
# 使用Node.js脚本做健康检查(替代curl)
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:3001/health || exit 1
|
||||
CMD node health-check.js
|
||||
|
||||
# 使用dumb-init作为PID 1,处理信号
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
|
||||
# 启动应用
|
||||
CMD ["npm", "start"]
|
||||
CMD ["node", "dist/server.js"]
|
||||
|
||||
@@ -88,7 +88,7 @@ server {
|
||||
}
|
||||
# Next.js Image Optimization Service (usually handled by the Next.js application)
|
||||
location /_next/image {
|
||||
proxy_pass http://localhost:3000; # Point to the Next.js application
|
||||
proxy_pass http://localhost:3002; # Point to the Next.js application
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
@@ -110,7 +110,7 @@ server {
|
||||
}
|
||||
# Named location, used to proxy requests to the Next.js application
|
||||
location @nextjs_app {
|
||||
proxy_pass http://localhost:3000; # Point to the Next.js application
|
||||
proxy_pass http://localhost:3002; # Point to the Next.js application
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const http = require('http');
|
||||
|
||||
const options = {
|
||||
host: 'localhost',
|
||||
port: process.env.BACKEND_PORT || 3001,
|
||||
path: '/health',
|
||||
timeout: 2000,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
console.log('Health check passed');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log(`Health check failed with status: ${res.statusCode}`);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
console.log(`Health check failed: ${err.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
req.on('timeout', () => {
|
||||
console.log('Health check timeout');
|
||||
req.destroy();
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
req.end();
|
||||
Generated
+156
-156
@@ -19,7 +19,7 @@ importers:
|
||||
version: 4.21.2
|
||||
ioredis:
|
||||
specifier: ^5.4.1
|
||||
version: 5.7.0
|
||||
version: 5.8.0
|
||||
socket.io:
|
||||
specifier: ^4.8.1
|
||||
version: 4.8.1
|
||||
@@ -32,7 +32,7 @@ importers:
|
||||
version: 5.0.3
|
||||
'@types/node':
|
||||
specifier: ^22.13.4
|
||||
version: 22.17.2
|
||||
version: 22.18.6
|
||||
cross-env:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
@@ -41,10 +41,10 @@ importers:
|
||||
version: 6.0.1
|
||||
ts-node:
|
||||
specifier: ^10.9.2
|
||||
version: 10.9.2(@types/node@22.17.2)(typescript@5.9.2)
|
||||
version: 10.9.2(@types/node@22.18.6)(typescript@5.9.2)
|
||||
tsx:
|
||||
specifier: ^4.19.2
|
||||
version: 4.20.4
|
||||
version: 4.20.5
|
||||
typescript:
|
||||
specifier: ^5.7.3
|
||||
version: 5.9.2
|
||||
@@ -55,164 +55,164 @@ packages:
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.9':
|
||||
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==}
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.25.9':
|
||||
resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==}
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.25.9':
|
||||
resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==}
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==}
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.25.9':
|
||||
resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==}
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==}
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.9':
|
||||
resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==}
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==}
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.25.9':
|
||||
resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==}
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.25.9':
|
||||
resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==}
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.25.9':
|
||||
resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==}
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.9':
|
||||
resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==}
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.9':
|
||||
resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==}
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.9':
|
||||
resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==}
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.25.9':
|
||||
resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==}
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.25.9':
|
||||
resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==}
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==}
|
||||
'@esbuild/netbsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.9':
|
||||
resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==}
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==}
|
||||
'@esbuild/openbsd-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.9':
|
||||
resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==}
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==}
|
||||
'@esbuild/openharmony-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.25.9':
|
||||
resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==}
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.25.9':
|
||||
resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==}
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.25.9':
|
||||
resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==}
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.25.9':
|
||||
resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==}
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@ioredis/commands@1.3.0':
|
||||
resolution: {integrity: sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==}
|
||||
'@ioredis/commands@1.4.0':
|
||||
resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==}
|
||||
|
||||
'@isaacs/balanced-match@4.0.1':
|
||||
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
|
||||
@@ -272,8 +272,8 @@ packages:
|
||||
'@types/mime@1.3.5':
|
||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||
|
||||
'@types/node@22.17.2':
|
||||
resolution: {integrity: sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==}
|
||||
'@types/node@22.18.6':
|
||||
resolution: {integrity: sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==}
|
||||
|
||||
'@types/qs@6.14.0':
|
||||
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||
@@ -304,16 +304,16 @@ packages:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@6.2.0:
|
||||
resolution: {integrity: sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==}
|
||||
ansi-regex@6.2.2:
|
||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.1:
|
||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||
ansi-styles@6.2.3:
|
||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
arg@4.1.3:
|
||||
@@ -405,8 +405,8 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.4.1:
|
||||
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
@@ -478,8 +478,8 @@ packages:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild@0.25.9:
|
||||
resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==}
|
||||
esbuild@0.25.10:
|
||||
resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
@@ -557,8 +557,8 @@ packages:
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
ioredis@5.7.0:
|
||||
resolution: {integrity: sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==}
|
||||
ioredis@5.8.0:
|
||||
resolution: {integrity: sha512-AUXbKn9gvo9hHKvk6LbZJQSKn/qIfkWXrnsyL9Yrf+oeXmla9Nmf6XEumOddyhM8neynpK5oAV6r9r99KBuwzA==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
@@ -582,8 +582,8 @@ packages:
|
||||
lodash.isarguments@3.1.0:
|
||||
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
|
||||
|
||||
lru-cache@11.1.0:
|
||||
resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==}
|
||||
lru-cache@11.2.1:
|
||||
resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==}
|
||||
engines: {node: 20 || >=22}
|
||||
|
||||
make-error@1.3.6:
|
||||
@@ -772,8 +772,8 @@ packages:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@7.1.0:
|
||||
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
|
||||
strip-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
toidentifier@1.0.1:
|
||||
@@ -794,8 +794,8 @@ packages:
|
||||
'@swc/wasm':
|
||||
optional: true
|
||||
|
||||
tsx@4.20.4:
|
||||
resolution: {integrity: sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg==}
|
||||
tsx@4.20.5:
|
||||
resolution: {integrity: sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -861,85 +861,85 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.9':
|
||||
'@esbuild/aix-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.25.9':
|
||||
'@esbuild/android-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.25.9':
|
||||
'@esbuild/android-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.25.9':
|
||||
'@esbuild/android-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.9':
|
||||
'@esbuild/darwin-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.25.9':
|
||||
'@esbuild/darwin-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.9':
|
||||
'@esbuild/freebsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.9':
|
||||
'@esbuild/freebsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.25.9':
|
||||
'@esbuild/linux-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.25.9':
|
||||
'@esbuild/linux-arm@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.25.9':
|
||||
'@esbuild/linux-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.25.9':
|
||||
'@esbuild/linux-loong64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.9':
|
||||
'@esbuild/linux-mips64el@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.9':
|
||||
'@esbuild/linux-ppc64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.9':
|
||||
'@esbuild/linux-riscv64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.25.9':
|
||||
'@esbuild/linux-s390x@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.25.9':
|
||||
'@esbuild/linux-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.9':
|
||||
'@esbuild/netbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.9':
|
||||
'@esbuild/netbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.9':
|
||||
'@esbuild/openbsd-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.9':
|
||||
'@esbuild/openbsd-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.25.9':
|
||||
'@esbuild/openharmony-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.25.9':
|
||||
'@esbuild/sunos-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.25.9':
|
||||
'@esbuild/win32-arm64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.25.9':
|
||||
'@esbuild/win32-ia32@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.25.9':
|
||||
'@esbuild/win32-x64@0.25.10':
|
||||
optional: true
|
||||
|
||||
'@ioredis/commands@1.3.0': {}
|
||||
'@ioredis/commands@1.4.0': {}
|
||||
|
||||
'@isaacs/balanced-match@4.0.1': {}
|
||||
|
||||
@@ -951,7 +951,7 @@ snapshots:
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
string-width-cjs: string-width@4.2.3
|
||||
strip-ansi: 7.1.0
|
||||
strip-ansi: 7.1.2
|
||||
strip-ansi-cjs: strip-ansi@6.0.1
|
||||
wrap-ansi: 8.1.0
|
||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||
@@ -978,19 +978,19 @@ snapshots:
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
|
||||
'@types/express-serve-static-core@5.0.7':
|
||||
dependencies:
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 0.17.5
|
||||
@@ -1005,7 +1005,7 @@ snapshots:
|
||||
|
||||
'@types/mime@1.3.5': {}
|
||||
|
||||
'@types/node@22.17.2':
|
||||
'@types/node@22.18.6':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
@@ -1016,12 +1016,12 @@ snapshots:
|
||||
'@types/send@0.17.5':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
|
||||
'@types/serve-static@1.15.8':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
'@types/send': 0.17.5
|
||||
|
||||
accepts@1.3.8:
|
||||
@@ -1037,13 +1037,13 @@ snapshots:
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.2.0: {}
|
||||
ansi-regex@6.2.2: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.1: {}
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
arg@4.1.3: {}
|
||||
|
||||
@@ -1125,7 +1125,7 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@4.4.1:
|
||||
debug@4.4.3:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
@@ -1162,7 +1162,7 @@ snapshots:
|
||||
engine.io@6.6.4:
|
||||
dependencies:
|
||||
'@types/cors': 2.8.19
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.7.2
|
||||
@@ -1183,34 +1183,34 @@ snapshots:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
esbuild@0.25.9:
|
||||
esbuild@0.25.10:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.9
|
||||
'@esbuild/android-arm': 0.25.9
|
||||
'@esbuild/android-arm64': 0.25.9
|
||||
'@esbuild/android-x64': 0.25.9
|
||||
'@esbuild/darwin-arm64': 0.25.9
|
||||
'@esbuild/darwin-x64': 0.25.9
|
||||
'@esbuild/freebsd-arm64': 0.25.9
|
||||
'@esbuild/freebsd-x64': 0.25.9
|
||||
'@esbuild/linux-arm': 0.25.9
|
||||
'@esbuild/linux-arm64': 0.25.9
|
||||
'@esbuild/linux-ia32': 0.25.9
|
||||
'@esbuild/linux-loong64': 0.25.9
|
||||
'@esbuild/linux-mips64el': 0.25.9
|
||||
'@esbuild/linux-ppc64': 0.25.9
|
||||
'@esbuild/linux-riscv64': 0.25.9
|
||||
'@esbuild/linux-s390x': 0.25.9
|
||||
'@esbuild/linux-x64': 0.25.9
|
||||
'@esbuild/netbsd-arm64': 0.25.9
|
||||
'@esbuild/netbsd-x64': 0.25.9
|
||||
'@esbuild/openbsd-arm64': 0.25.9
|
||||
'@esbuild/openbsd-x64': 0.25.9
|
||||
'@esbuild/openharmony-arm64': 0.25.9
|
||||
'@esbuild/sunos-x64': 0.25.9
|
||||
'@esbuild/win32-arm64': 0.25.9
|
||||
'@esbuild/win32-ia32': 0.25.9
|
||||
'@esbuild/win32-x64': 0.25.9
|
||||
'@esbuild/aix-ppc64': 0.25.10
|
||||
'@esbuild/android-arm': 0.25.10
|
||||
'@esbuild/android-arm64': 0.25.10
|
||||
'@esbuild/android-x64': 0.25.10
|
||||
'@esbuild/darwin-arm64': 0.25.10
|
||||
'@esbuild/darwin-x64': 0.25.10
|
||||
'@esbuild/freebsd-arm64': 0.25.10
|
||||
'@esbuild/freebsd-x64': 0.25.10
|
||||
'@esbuild/linux-arm': 0.25.10
|
||||
'@esbuild/linux-arm64': 0.25.10
|
||||
'@esbuild/linux-ia32': 0.25.10
|
||||
'@esbuild/linux-loong64': 0.25.10
|
||||
'@esbuild/linux-mips64el': 0.25.10
|
||||
'@esbuild/linux-ppc64': 0.25.10
|
||||
'@esbuild/linux-riscv64': 0.25.10
|
||||
'@esbuild/linux-s390x': 0.25.10
|
||||
'@esbuild/linux-x64': 0.25.10
|
||||
'@esbuild/netbsd-arm64': 0.25.10
|
||||
'@esbuild/netbsd-x64': 0.25.10
|
||||
'@esbuild/openbsd-arm64': 0.25.10
|
||||
'@esbuild/openbsd-x64': 0.25.10
|
||||
'@esbuild/openharmony-arm64': 0.25.10
|
||||
'@esbuild/sunos-x64': 0.25.10
|
||||
'@esbuild/win32-arm64': 0.25.10
|
||||
'@esbuild/win32-ia32': 0.25.10
|
||||
'@esbuild/win32-x64': 0.25.10
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
|
||||
@@ -1331,11 +1331,11 @@ snapshots:
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
ioredis@5.7.0:
|
||||
ioredis@5.8.0:
|
||||
dependencies:
|
||||
'@ioredis/commands': 1.3.0
|
||||
'@ioredis/commands': 1.4.0
|
||||
cluster-key-slot: 1.1.2
|
||||
debug: 4.4.1
|
||||
debug: 4.4.3
|
||||
denque: 2.1.0
|
||||
lodash.defaults: 4.2.0
|
||||
lodash.isarguments: 3.1.0
|
||||
@@ -1359,7 +1359,7 @@ snapshots:
|
||||
|
||||
lodash.isarguments@3.1.0: {}
|
||||
|
||||
lru-cache@11.1.0: {}
|
||||
lru-cache@11.2.1: {}
|
||||
|
||||
make-error@1.3.6: {}
|
||||
|
||||
@@ -1407,7 +1407,7 @@ snapshots:
|
||||
|
||||
path-scurry@2.0.0:
|
||||
dependencies:
|
||||
lru-cache: 11.1.0
|
||||
lru-cache: 11.2.1
|
||||
minipass: 7.1.2
|
||||
|
||||
path-to-regexp@0.1.12: {}
|
||||
@@ -1556,26 +1556,26 @@ snapshots:
|
||||
dependencies:
|
||||
eastasianwidth: 0.2.0
|
||||
emoji-regex: 9.2.2
|
||||
strip-ansi: 7.1.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-ansi@7.1.0:
|
||||
strip-ansi@7.1.2:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.0
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
toidentifier@1.0.1: {}
|
||||
|
||||
ts-node@10.9.2(@types/node@22.17.2)(typescript@5.9.2):
|
||||
ts-node@10.9.2(@types/node@22.18.6)(typescript@5.9.2):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.11
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 22.17.2
|
||||
'@types/node': 22.18.6
|
||||
acorn: 8.15.0
|
||||
acorn-walk: 8.3.4
|
||||
arg: 4.1.3
|
||||
@@ -1586,9 +1586,9 @@ snapshots:
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
|
||||
tsx@4.20.4:
|
||||
tsx@4.20.5:
|
||||
dependencies:
|
||||
esbuild: 0.25.9
|
||||
esbuild: 0.25.10
|
||||
get-tsconfig: 4.10.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
@@ -1622,9 +1622,9 @@ snapshots:
|
||||
|
||||
wrap-ansi@8.1.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
ws@8.17.1: {}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import { CONFIG } from "./env";
|
||||
|
||||
// Define the sources allowed in the development environment
|
||||
const DEV_ORIGINS = [
|
||||
CONFIG.CORS_ORIGIN, // http://localhost:3002
|
||||
'http://localhost:3000', // alternate port
|
||||
/^http:\/\/192\.168\.\d+\.\d+:3000$/, // LAN addresses
|
||||
/^http:\/\/192\.168\.\d+\.\d+:3002$/ // LAN addresses with new port
|
||||
CONFIG.CORS_ORIGIN, // http://localhost:3002
|
||||
"http://localhost:3002", // alternate port
|
||||
/^http:\/\/192\.168\.\d+\.\d+:3002$/, // LAN addresses
|
||||
/^http:\/\/192\.168\.\d+\.\d+:3002$/, // LAN addresses with new port
|
||||
];
|
||||
|
||||
// Configure CORS
|
||||
|
||||
@@ -39,13 +39,12 @@ PrivyDrop Docker 一键部署脚本
|
||||
|
||||
选项:
|
||||
--domain DOMAIN 指定域名 (用于HTTPS部署)
|
||||
--mode MODE 部署模式: basic|public|full
|
||||
basic: 内网HTTP部署 (默认)
|
||||
--mode MODE 部署模式: basic|public|full|private
|
||||
basic/private: 内网HTTP部署 (默认,private 将跳过网络检测)
|
||||
public: 公网HTTP部署 + TURN服务器
|
||||
full: 完整HTTPS部署 + TURN服务器
|
||||
--with-nginx 启用Nginx反向代理
|
||||
--with-turn 启用TURN服务器
|
||||
--dev 开发模式部署
|
||||
--clean 清理现有容器和数据
|
||||
--help 显示帮助信息
|
||||
|
||||
@@ -53,7 +52,6 @@ PrivyDrop Docker 一键部署脚本
|
||||
$0 # 基础部署
|
||||
$0 --mode public --with-turn # 公网部署 + TURN服务器
|
||||
$0 --domain example.com --mode full # 完整HTTPS部署
|
||||
$0 --dev # 开发模式部署
|
||||
$0 --clean # 清理部署
|
||||
|
||||
EOF
|
||||
@@ -65,7 +63,6 @@ parse_arguments() {
|
||||
DEPLOYMENT_MODE=""
|
||||
WITH_NGINX=false
|
||||
WITH_TURN=false
|
||||
DEV_MODE=false
|
||||
CLEAN_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@@ -86,10 +83,6 @@ parse_arguments() {
|
||||
WITH_TURN=true
|
||||
shift
|
||||
;;
|
||||
--dev)
|
||||
DEV_MODE=true
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN_MODE=true
|
||||
shift
|
||||
@@ -111,7 +104,6 @@ parse_arguments() {
|
||||
export DEPLOYMENT_MODE
|
||||
export WITH_NGINX
|
||||
export WITH_TURN
|
||||
export DEV_MODE
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
@@ -204,7 +196,7 @@ setup_environment() {
|
||||
fi
|
||||
|
||||
# 生成配置文件
|
||||
if ! bash "$DOCKER_SCRIPTS_DIR/generate-config.sh"; then
|
||||
if ! bash "$DOCKER_SCRIPTS_DIR/generate-config.sh" $detect_args; then
|
||||
log_error "配置生成失败"
|
||||
exit 1
|
||||
fi
|
||||
@@ -222,13 +214,6 @@ deploy_services() {
|
||||
docker-compose down
|
||||
fi
|
||||
|
||||
# 确定compose文件
|
||||
local compose_files="-f docker-compose.yml"
|
||||
if [[ "$DEV_MODE" == "true" ]]; then
|
||||
compose_files="$compose_files -f docker-compose.dev.yml"
|
||||
log_info "使用开发模式配置"
|
||||
fi
|
||||
|
||||
# 确定启用的服务
|
||||
local profiles=""
|
||||
if [[ "$WITH_NGINX" == "true" ]]; then
|
||||
@@ -240,15 +225,11 @@ deploy_services() {
|
||||
|
||||
# 构建镜像
|
||||
log_info "构建Docker镜像..."
|
||||
if [[ "$DEV_MODE" == "true" ]]; then
|
||||
docker-compose $compose_files build --parallel
|
||||
else
|
||||
docker-compose $compose_files build --no-cache --parallel
|
||||
fi
|
||||
docker-compose build --no-cache --parallel
|
||||
|
||||
# 启动服务
|
||||
log_info "启动服务..."
|
||||
docker-compose $compose_files up -d $profiles
|
||||
docker-compose up -d $profiles
|
||||
|
||||
log_success "服务启动完成"
|
||||
}
|
||||
@@ -271,7 +252,7 @@ wait_for_services() {
|
||||
fi
|
||||
|
||||
# 检查前端健康状态
|
||||
if curl -f http://localhost:3000/api/health &> /dev/null; then
|
||||
if curl -f http://localhost:3002/api/health &> /dev/null; then
|
||||
frontend_ready=true
|
||||
fi
|
||||
|
||||
@@ -337,13 +318,13 @@ show_deployment_info() {
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}📋 访问信息:${NC}"
|
||||
echo " 前端应用: http://localhost:${frontend_port:-3000}"
|
||||
echo " 前端应用: http://localhost:${frontend_port:-3002}"
|
||||
echo " 后端API: http://localhost:${backend_port:-3001}"
|
||||
|
||||
if [[ -n "$local_ip" ]] && [[ "$local_ip" != "127.0.0.1" ]]; then
|
||||
echo ""
|
||||
echo -e "${BLUE}🌐 局域网访问:${NC}"
|
||||
echo " 前端应用: http://$local_ip:${frontend_port:-3000}"
|
||||
echo " 前端应用: http://$local_ip:${frontend_port:-3002}"
|
||||
echo " 后端API: http://$local_ip:${backend_port:-3001}"
|
||||
fi
|
||||
|
||||
@@ -431,4 +412,4 @@ main() {
|
||||
trap 'log_warning "部署被中断"; exit 1' INT TERM
|
||||
|
||||
# 运行主函数
|
||||
main "$@"
|
||||
main "$@"
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# 开发环境后端配置
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
target: base
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- BACKEND_PORT=3001
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- CORS_ORIGIN=http://localhost:3000
|
||||
volumes:
|
||||
- ./backend/src:/app/src
|
||||
- ./backend/package.json:/app/package.json
|
||||
- ./logs:/app/logs
|
||||
command: ["npm", "run", "dev"]
|
||||
|
||||
# 开发环境前端配置
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
target: builder
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- NEXT_PUBLIC_API_URL=http://localhost:3001
|
||||
- WATCHPACK_POLLING=true
|
||||
volumes:
|
||||
- ./frontend:/app
|
||||
- frontend_node_modules:/app/node_modules
|
||||
- frontend_next:/app/.next
|
||||
command: ["pnpm", "dev"]
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
# 开发环境Redis配置
|
||||
redis:
|
||||
ports:
|
||||
- "6379:6379"
|
||||
command: redis-server --appendonly yes
|
||||
|
||||
volumes:
|
||||
frontend_node_modules:
|
||||
frontend_next:
|
||||
+14
-21
@@ -1,4 +1,4 @@
|
||||
version: '3.8'
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
# Redis缓存服务
|
||||
@@ -23,6 +23,10 @@ services:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- HTTP_PROXY=${HTTP_PROXY}
|
||||
- HTTPS_PROXY=${HTTPS_PROXY}
|
||||
- NO_PROXY=${NO_PROXY}
|
||||
container_name: privydrop-backend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@@ -52,22 +56,26 @@ services:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- HTTP_PROXY=${HTTP_PROXY}
|
||||
- HTTPS_PROXY=${HTTPS_PROXY}
|
||||
- NO_PROXY=${NO_PROXY}
|
||||
container_name: privydrop-frontend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-http://localhost:3001}
|
||||
- PORT=3000
|
||||
- PORT=3002
|
||||
- HOSTNAME=0.0.0.0
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-3000}:3000"
|
||||
- "${FRONTEND_PORT:-3002}:3002"
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- privydrop-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3002/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
@@ -101,7 +109,7 @@ services:
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3478:3478/tcp"
|
||||
- "3478:3478/udp"
|
||||
- "3478:3478/udp"
|
||||
- "5349:5349/tcp"
|
||||
- "5349:5349/udp"
|
||||
- "49152-65535:49152-65535/udp"
|
||||
@@ -115,21 +123,6 @@ services:
|
||||
- turn
|
||||
command: ["-c", "/etc/coturn/turnserver.conf"]
|
||||
|
||||
# 自动更新服务 (可选)
|
||||
watchtower:
|
||||
image: containrrr/watchtower:latest
|
||||
container_name: privydrop-watchtower
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- WATCHTOWER_CLEANUP=true
|
||||
- WATCHTOWER_POLL_INTERVAL=86400 # 24小时检查一次
|
||||
- WATCHTOWER_INCLUDE_STOPPED=true
|
||||
- WATCHTOWER_REVIVE_STOPPED=false
|
||||
profiles:
|
||||
- auto-update
|
||||
|
||||
networks:
|
||||
privydrop-network:
|
||||
driver: bridge
|
||||
@@ -139,4 +132,4 @@ networks:
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
driver: local
|
||||
driver: local
|
||||
|
||||
Regular → Executable
+246
-17
@@ -12,6 +12,174 @@ NETWORK_MODE=""
|
||||
LOCAL_IP=""
|
||||
PUBLIC_IP=""
|
||||
DEPLOYMENT_MODE="basic"
|
||||
FORCED_MODE=""
|
||||
LOCAL_IP_OVERRIDE=""
|
||||
|
||||
declare -a IP_CANDIDATES=()
|
||||
declare -A __SEEN_IPS=()
|
||||
|
||||
add_ip_candidate() {
|
||||
local ip="$1"
|
||||
[[ -z "$ip" ]] && return
|
||||
[[ "$ip" == "127."* ]] && return
|
||||
[[ "$ip" == "0.0.0.0" ]] && return
|
||||
if [[ -z "${__SEEN_IPS[$ip]}" ]]; then
|
||||
IP_CANDIDATES+=("$ip")
|
||||
__SEEN_IPS[$ip]=1
|
||||
fi
|
||||
}
|
||||
|
||||
is_rfc1918_ip() {
|
||||
local ip="$1"
|
||||
case "$ip" in
|
||||
10.*|192.168.*|172.1[6-9].*|172.2[0-9].*|172.3[0-1].*)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_cgnat_ip() {
|
||||
local ip="$1"
|
||||
case "$ip" in
|
||||
100.*)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_reserved_benchmark_ip() {
|
||||
local ip="$1"
|
||||
case "$ip" in
|
||||
198.18.*|198.19.*)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_link_local_ip() {
|
||||
local ip="$1"
|
||||
case "$ip" in
|
||||
169.254.*)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_routable_public_ip() {
|
||||
local ip="$1"
|
||||
if [[ -z "$ip" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if is_rfc1918_ip "$ip"; then
|
||||
return 1
|
||||
fi
|
||||
if is_cgnat_ip "$ip"; then
|
||||
return 1
|
||||
fi
|
||||
if is_reserved_benchmark_ip "$ip"; then
|
||||
return 1
|
||||
fi
|
||||
case "$ip" in
|
||||
127.*|169.254.*)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
collect_ip_candidates() {
|
||||
IP_CANDIDATES=()
|
||||
unset __SEEN_IPS
|
||||
declare -A __SEEN_IPS=()
|
||||
|
||||
if command -v hostname >/dev/null 2>&1; then
|
||||
local host_ips
|
||||
host_ips=$(hostname -I 2>/dev/null || true)
|
||||
for ip in $host_ips; do
|
||||
add_ip_candidate "$ip"
|
||||
done
|
||||
fi
|
||||
|
||||
if command -v ip >/dev/null 2>&1; then
|
||||
while IFS= read -r ip; do
|
||||
add_ip_candidate "$ip"
|
||||
done < <(ip -o -4 addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1)
|
||||
fi
|
||||
|
||||
if command -v ifconfig >/dev/null 2>&1; then
|
||||
while IFS= read -r ip; do
|
||||
add_ip_candidate "$ip"
|
||||
done < <(ifconfig 2>/dev/null | awk '/inet / {print $2}' | grep -E '^[0-9]+(\.[0-9]+){3}$')
|
||||
fi
|
||||
|
||||
if command -v ip >/dev/null 2>&1; then
|
||||
local route_ip
|
||||
route_ip=$(ip route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')
|
||||
add_ip_candidate "$route_ip"
|
||||
fi
|
||||
|
||||
if [[ ${#IP_CANDIDATES[@]} -eq 0 ]]; then
|
||||
local fallback
|
||||
fallback=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||
add_ip_candidate "$fallback"
|
||||
fi
|
||||
}
|
||||
|
||||
resolve_local_ip() {
|
||||
if [[ -n "$LOCAL_IP_OVERRIDE" ]]; then
|
||||
LOCAL_IP="$LOCAL_IP_OVERRIDE"
|
||||
return
|
||||
fi
|
||||
|
||||
collect_ip_candidates
|
||||
|
||||
if [[ ${#IP_CANDIDATES[@]} -eq 0 ]]; then
|
||||
LOCAL_IP=""
|
||||
return
|
||||
fi
|
||||
|
||||
local ip
|
||||
for ip in "${IP_CANDIDATES[@]}"; do
|
||||
if is_rfc1918_ip "$ip"; then
|
||||
LOCAL_IP="$ip"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
for ip in "${IP_CANDIDATES[@]}"; do
|
||||
if is_cgnat_ip "$ip"; then
|
||||
LOCAL_IP="$ip"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
for ip in "${IP_CANDIDATES[@]}"; do
|
||||
if is_reserved_benchmark_ip "$ip"; then
|
||||
continue
|
||||
fi
|
||||
if is_link_local_ip "$ip"; then
|
||||
continue
|
||||
fi
|
||||
LOCAL_IP="$ip"
|
||||
return
|
||||
done
|
||||
|
||||
LOCAL_IP="${IP_CANDIDATES[0]}"
|
||||
}
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
@@ -33,35 +201,80 @@ log_error() {
|
||||
# 检测网络环境
|
||||
detect_network_environment() {
|
||||
log_info "检测网络环境..."
|
||||
|
||||
# 获取本机IP
|
||||
LOCAL_IP=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7}' | head -1)
|
||||
if [[ -z "$LOCAL_IP" ]]; then
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
fi
|
||||
|
||||
|
||||
resolve_local_ip
|
||||
|
||||
if [[ -z "$LOCAL_IP" ]]; then
|
||||
LOCAL_IP="127.0.0.1"
|
||||
log_warning "无法自动检测本机IP,使用默认值: $LOCAL_IP"
|
||||
fi
|
||||
|
||||
# 检测公网连接
|
||||
|
||||
if [[ "$FORCED_MODE" == "private" ]]; then
|
||||
NETWORK_MODE="private"
|
||||
PUBLIC_IP=""
|
||||
log_info "已通过参数指定网络模式: $NETWORK_MODE"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local mode_guess="private"
|
||||
local printed_prompt_info="false"
|
||||
PUBLIC_IP=""
|
||||
|
||||
if curl -s --connect-timeout 5 --max-time 10 ifconfig.me > /dev/null 2>&1; then
|
||||
PUBLIC_IP=$(curl -s --connect-timeout 5 --max-time 10 ifconfig.me 2>/dev/null || echo "")
|
||||
if [[ -n "$PUBLIC_IP" ]]; then
|
||||
NETWORK_MODE="public"
|
||||
log_success "检测到公网环境"
|
||||
if is_routable_public_ip "$PUBLIC_IP"; then
|
||||
mode_guess="public"
|
||||
else
|
||||
log_warning "检测到测试或保留网段公网IP,按内网环境处理"
|
||||
fi
|
||||
else
|
||||
log_warning "公网连接不稳定,按内网环境处理"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$FORCED_MODE" ]]; then
|
||||
if [[ "$mode_guess" == "public" ]]; then
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
echo " 公网IP: $PUBLIC_IP"
|
||||
printed_prompt_info="true"
|
||||
read -r -p "是否按公网模式继续?(Y/n): " confirm </dev/tty 2>/dev/null || confirm="Y"
|
||||
confirm=${confirm:-Y}
|
||||
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
||||
NETWORK_MODE="public"
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
PUBLIC_IP=""
|
||||
log_warning "按用户选择,已切换为内网模式"
|
||||
fi
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
log_warning "公网连接不稳定,按内网环境处理"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
fi
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
NETWORK_MODE="$FORCED_MODE"
|
||||
if [[ "$FORCED_MODE" == "public" && -z "$PUBLIC_IP" ]]; then
|
||||
log_warning "未能检测到公网IP,仍按公网模式继续,请确认网络配置"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$NETWORK_MODE" != "public" ]]; then
|
||||
PUBLIC_IP=""
|
||||
fi
|
||||
|
||||
if [[ "$FORCED_MODE" == "public" ]]; then
|
||||
log_info "已通过参数指定网络模式: $NETWORK_MODE"
|
||||
elif [[ "$NETWORK_MODE" == "public" ]]; then
|
||||
log_success "检测到公网环境"
|
||||
else
|
||||
log_success "检测到内网环境"
|
||||
fi
|
||||
|
||||
if [[ "$printed_prompt_info" == "false" ]]; then
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
if [[ "$NETWORK_MODE" == "public" && -n "$PUBLIC_IP" ]]; then
|
||||
echo " 公网IP: $PUBLIC_IP"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -181,7 +394,7 @@ check_port_availability() {
|
||||
|
||||
if [[ ${#occupied_ports[@]} -gt 0 ]]; then
|
||||
log_warning "以下端口已被占用: ${occupied_ports[*]}"
|
||||
log_info "可以通过修改.env文件中的端口配置来解决冲突"
|
||||
log_info "可以通过修改 .env 中的端口,或先执行 './deploy.sh --clean' / 'docker-compose down' 清理旧容器"
|
||||
else
|
||||
log_success "所有端口都可用"
|
||||
fi
|
||||
@@ -216,6 +429,21 @@ main() {
|
||||
;;
|
||||
--mode)
|
||||
DEPLOYMENT_MODE="$2"
|
||||
case "$2" in
|
||||
private|basic)
|
||||
FORCED_MODE="private"
|
||||
;;
|
||||
public|full)
|
||||
FORCED_MODE="public"
|
||||
;;
|
||||
*)
|
||||
FORCED_MODE=""
|
||||
;;
|
||||
esac
|
||||
shift 2
|
||||
;;
|
||||
--local-ip)
|
||||
LOCAL_IP_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
@@ -240,7 +468,7 @@ main() {
|
||||
fi
|
||||
echo ""
|
||||
|
||||
check_port_availability "80,443,3000,3001,3478,5349,6379"
|
||||
check_port_availability "80,443,3002,3001,3478,5349,6379"
|
||||
echo ""
|
||||
|
||||
detect_deployment_mode
|
||||
@@ -259,6 +487,7 @@ main() {
|
||||
export PUBLIC_IP
|
||||
export DEPLOYMENT_MODE
|
||||
export DOMAIN_NAME
|
||||
export LOCAL_IP_OVERRIDE
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -266,4 +495,4 @@ main() {
|
||||
# 如果脚本被直接执行
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
Regular → Executable
+114
-23
@@ -33,10 +33,75 @@ generate_env_file() {
|
||||
log_info "生成环境变量配置..."
|
||||
|
||||
local env_file=".env"
|
||||
|
||||
# 生成随机密码
|
||||
local turn_password=$(openssl rand -base64 32 2>/dev/null || echo "privydrop$(date +%s)")
|
||||
|
||||
|
||||
# 读取已有配置以保留用户自定义字段(如代理、TURN)
|
||||
declare -A existing_env=()
|
||||
if [[ -f "$env_file" ]]; then
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" || "${line:0:1}" == "#" ]] && continue
|
||||
if [[ "$line" == *=* ]]; then
|
||||
local key="${line%%=*}"
|
||||
local value="${line#*=}"
|
||||
existing_env[$key]="$value"
|
||||
fi
|
||||
done < "$env_file"
|
||||
fi
|
||||
|
||||
# 生成随机密码(同时保存到全局变量,供后续生成 TURN 配置使用)
|
||||
local turn_password="${existing_env[TURN_PASSWORD]}"
|
||||
if [[ -z "$turn_password" ]]; then
|
||||
turn_password=$(openssl rand -base64 32 2>/dev/null || echo "privydrop$(date +%s)")
|
||||
fi
|
||||
|
||||
# 计算不同部署模式下的访问入口
|
||||
local cors_origin="http://${LOCAL_IP}:3002"
|
||||
local api_url="http://${LOCAL_IP}:3001"
|
||||
local ssl_mode="self-signed"
|
||||
local turn_enabled="false"
|
||||
local turn_host_value=""
|
||||
local turn_realm_value="${existing_env[TURN_REALM]:-turn.local}"
|
||||
local turn_username_value="${existing_env[TURN_USERNAME]:-privydrop}"
|
||||
local next_public_turn_host=""
|
||||
local next_public_turn_username=""
|
||||
local next_public_turn_password=""
|
||||
|
||||
if [[ "$DEPLOYMENT_MODE" == "public" ]]; then
|
||||
cors_origin="http://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
api_url="$cors_origin"
|
||||
turn_enabled="true"
|
||||
elif [[ "$DEPLOYMENT_MODE" == "full" ]]; then
|
||||
cors_origin="https://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
api_url="$cors_origin"
|
||||
ssl_mode="letsencrypt"
|
||||
turn_enabled="true"
|
||||
fi
|
||||
|
||||
if [[ "$turn_enabled" == "true" ]]; then
|
||||
if [[ -n "$DOMAIN_NAME" ]]; then
|
||||
turn_host_value="turn.${DOMAIN_NAME}"
|
||||
turn_realm_value="turn.${DOMAIN_NAME}"
|
||||
else
|
||||
turn_host_value="$LOCAL_IP"
|
||||
turn_realm_value="turn.local"
|
||||
fi
|
||||
|
||||
next_public_turn_host="$turn_host_value"
|
||||
next_public_turn_username="$turn_username_value"
|
||||
next_public_turn_password="$turn_password"
|
||||
fi
|
||||
|
||||
local default_no_proxy="localhost,127.0.0.1,backend,frontend,redis,coturn"
|
||||
local http_proxy_value="${HTTP_PROXY:-${existing_env[HTTP_PROXY]}}"
|
||||
local https_proxy_value="${HTTPS_PROXY:-${existing_env[HTTPS_PROXY]}}"
|
||||
local no_proxy_value="${NO_PROXY:-${existing_env[NO_PROXY]:-$default_no_proxy}}"
|
||||
|
||||
# 将关键 TURN 参数暴露给后续步骤
|
||||
TURN_ENABLED="$turn_enabled"
|
||||
TURN_USERNAME="$turn_username_value"
|
||||
TURN_PASSWORD="$turn_password"
|
||||
TURN_REALM="$turn_realm_value"
|
||||
TURN_HOST="$turn_host_value"
|
||||
|
||||
cat > "$env_file" << EOF
|
||||
# PrivyDrop Docker 配置文件
|
||||
# 自动生成时间: $(date)
|
||||
@@ -46,13 +111,16 @@ generate_env_file() {
|
||||
# =============================================================================
|
||||
# 网络配置
|
||||
# =============================================================================
|
||||
CORS_ORIGIN=http://${LOCAL_IP}
|
||||
NEXT_PUBLIC_API_URL=http://${LOCAL_IP}:3001
|
||||
CORS_ORIGIN=${cors_origin}
|
||||
NEXT_PUBLIC_API_URL=${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}
|
||||
|
||||
# =============================================================================
|
||||
# 端口配置
|
||||
# =============================================================================
|
||||
FRONTEND_PORT=3000
|
||||
FRONTEND_PORT=3002
|
||||
BACKEND_PORT=3001
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
@@ -74,16 +142,16 @@ PUBLIC_IP=${PUBLIC_IP:-}
|
||||
# =============================================================================
|
||||
# SSL配置
|
||||
# =============================================================================
|
||||
SSL_MODE=self-signed
|
||||
SSL_MODE=${ssl_mode}
|
||||
DOMAIN_NAME=${DOMAIN_NAME:-}
|
||||
|
||||
# =============================================================================
|
||||
# TURN服务器配置 (可选)
|
||||
# =============================================================================
|
||||
TURN_ENABLED=${TURN_ENABLED:-false}
|
||||
TURN_USERNAME=privydrop
|
||||
TURN_ENABLED=${turn_enabled}
|
||||
TURN_USERNAME=${turn_username_value}
|
||||
TURN_PASSWORD=${turn_password}
|
||||
TURN_REALM=${DOMAIN_NAME:-turn.local}
|
||||
TURN_REALM=${turn_realm_value}
|
||||
|
||||
# =============================================================================
|
||||
# Nginx配置
|
||||
@@ -94,18 +162,15 @@ NGINX_SERVER_NAME=${DOMAIN_NAME:-${LOCAL_IP}}
|
||||
# 日志配置
|
||||
# =============================================================================
|
||||
LOG_LEVEL=info
|
||||
|
||||
# =============================================================================
|
||||
# 代理配置 (可选)
|
||||
# =============================================================================
|
||||
HTTP_PROXY=${http_proxy_value}
|
||||
HTTPS_PROXY=${https_proxy_value}
|
||||
NO_PROXY=${no_proxy_value}
|
||||
EOF
|
||||
|
||||
# 根据部署模式调整配置
|
||||
if [[ "$DEPLOYMENT_MODE" == "full" ]]; then
|
||||
sed -i "s|CORS_ORIGIN=http://|CORS_ORIGIN=https://|g" "$env_file"
|
||||
sed -i "s|NEXT_PUBLIC_API_URL=http://|NEXT_PUBLIC_API_URL=https://|g" "$env_file"
|
||||
sed -i "s|SSL_MODE=self-signed|SSL_MODE=letsencrypt|g" "$env_file"
|
||||
sed -i "s|TURN_ENABLED=false|TURN_ENABLED=true|g" "$env_file"
|
||||
elif [[ "$DEPLOYMENT_MODE" == "public" ]]; then
|
||||
sed -i "s|TURN_ENABLED=false|TURN_ENABLED=true|g" "$env_file"
|
||||
fi
|
||||
|
||||
log_success "环境变量配置已生成: $env_file"
|
||||
}
|
||||
|
||||
@@ -117,7 +182,7 @@ generate_nginx_config() {
|
||||
|
||||
local server_name="${DOMAIN_NAME:-${LOCAL_IP} localhost}"
|
||||
local upstream_backend="backend:3001"
|
||||
local upstream_frontend="frontend:3000"
|
||||
local upstream_frontend="frontend:3002"
|
||||
|
||||
# 生成主Nginx配置
|
||||
cat > docker/nginx/nginx.conf << 'EOF'
|
||||
@@ -548,6 +613,32 @@ main() {
|
||||
echo -e "${BLUE}=== PrivyDrop 配置生成 ===${NC}"
|
||||
echo ""
|
||||
|
||||
# 解析参数(与环境检测脚本保持一致)
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--domain)
|
||||
DOMAIN_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--mode)
|
||||
DEPLOYMENT_MODE="$2"
|
||||
if [[ "$2" == "private" || "$2" == "basic" ]]; then
|
||||
FORCED_MODE="private"
|
||||
elif [[ "$2" == "public" || "$2" == "full" ]]; then
|
||||
FORCED_MODE="public"
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
--local-ip)
|
||||
LOCAL_IP_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 首先运行环境检测
|
||||
if ! detect_network_environment; then
|
||||
log_error "环境检测失败"
|
||||
@@ -597,4 +688,4 @@ main() {
|
||||
# 如果脚本被直接执行
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
Regular → Executable
+5
-5
@@ -92,7 +92,7 @@ test_network_connectivity() {
|
||||
echo -e "${BLUE}=== 网络连接测试 ===${NC}"
|
||||
|
||||
# 测试端口连通性
|
||||
local ports=("3000:前端" "3001:后端" "6379:Redis")
|
||||
local ports=("3002:前端" "3001:后端" "6379:Redis")
|
||||
|
||||
for port_info in "${ports[@]}"; do
|
||||
local port=$(echo "$port_info" | cut -d':' -f1)
|
||||
@@ -114,7 +114,7 @@ test_api_functionality() {
|
||||
|
||||
# 健康检查API
|
||||
run_test "后端健康检查API" "curl -f http://localhost:3001/health"
|
||||
run_test "前端健康检查API" "curl -f http://localhost:3000/api/health"
|
||||
run_test "前端健康检查API" "curl -f http://localhost:3002/api/health"
|
||||
|
||||
# 后端详细健康检查
|
||||
if curl -f http://localhost:3001/health/detailed >/dev/null 2>&1; then
|
||||
@@ -144,7 +144,7 @@ test_webrtc_functionality() {
|
||||
echo -e "${BLUE}=== WebRTC功能测试 ===${NC}"
|
||||
|
||||
# 测试前端页面加载
|
||||
if curl -f http://localhost:3000 >/dev/null 2>&1; then
|
||||
if curl -f http://localhost:3002 >/dev/null 2>&1; then
|
||||
log_success "前端页面可访问"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
@@ -350,7 +350,7 @@ generate_report() {
|
||||
echo -e "${GREEN}🎉 所有测试通过!PrivyDrop 部署成功!${NC}"
|
||||
echo ""
|
||||
echo "🔗 访问链接:"
|
||||
echo " 前端应用: http://localhost:3000"
|
||||
echo " 前端应用: http://localhost:3002"
|
||||
echo " 后端API: http://localhost:3001"
|
||||
|
||||
# 显示局域网访问地址
|
||||
@@ -359,7 +359,7 @@ generate_report() {
|
||||
if [[ -n "$local_ip" && "$local_ip" != "127.0.0.1" ]]; then
|
||||
echo ""
|
||||
echo "🌐 局域网访问:"
|
||||
echo " 前端应用: http://$local_ip:3000"
|
||||
echo " 前端应用: http://$local_ip:3002"
|
||||
echo " 后端API: http://$local_ip:3001"
|
||||
fi
|
||||
fi
|
||||
|
||||
+80
-30
@@ -6,30 +6,33 @@ This guide provides a one-click Docker deployment solution for PrivyDrop, suppor
|
||||
|
||||
Compared to traditional deployment methods, Docker deployment offers the following advantages:
|
||||
|
||||
| Comparison | Traditional Deployment | Docker Deployment |
|
||||
|-----------|----------------------|------------------|
|
||||
| **Deploy Time** | 30-60 minutes | 5 minutes |
|
||||
| **Technical Requirements** | Linux ops experience | Basic Docker knowledge |
|
||||
| **Environment Requirements** | Public IP + Domain | Works on private networks |
|
||||
| **Configuration Complexity** | 10+ manual steps | One-click auto configuration |
|
||||
| **Success Rate** | ~70% | >95% |
|
||||
| **Maintenance Difficulty** | Manual multi-service management | Automatic container management |
|
||||
| Comparison | Traditional Deployment | Docker Deployment |
|
||||
| ---------------------------- | ------------------------------- | ------------------------------ |
|
||||
| **Deploy Time** | 30-60 minutes | 5 minutes |
|
||||
| **Technical Requirements** | Linux ops experience | Basic Docker knowledge |
|
||||
| **Environment Requirements** | Public IP + Domain | Works on private networks |
|
||||
| **Configuration Complexity** | 10+ manual steps | One-click auto configuration |
|
||||
| **Success Rate** | ~70% | >95% |
|
||||
| **Maintenance Difficulty** | Manual multi-service management | Automatic container management |
|
||||
|
||||
## 📋 System Requirements
|
||||
|
||||
### Minimum Configuration
|
||||
|
||||
- **CPU**: 1 core
|
||||
- **Memory**: 512MB
|
||||
- **Disk**: 2GB available space
|
||||
- **Network**: Any network environment (private/public)
|
||||
|
||||
### Recommended Configuration
|
||||
|
||||
- **CPU**: 2+ cores
|
||||
- **Memory**: 1GB+
|
||||
- **Memory**: 1GB+
|
||||
- **Disk**: 5GB+ available space
|
||||
- **Network**: 100Mbps+
|
||||
|
||||
### Software Dependencies
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+ (or docker-compose 1.27+)
|
||||
- curl (for health checks)
|
||||
@@ -52,7 +55,7 @@ cd PrivyDrop
|
||||
bash deploy.sh
|
||||
|
||||
# After deployment completes, visit:
|
||||
# http://localhost:3000
|
||||
# http://localhost:3002
|
||||
```
|
||||
|
||||
That's it! 🎉
|
||||
@@ -60,6 +63,7 @@ That's it! 🎉
|
||||
## 📚 Deployment Modes
|
||||
|
||||
### Basic Mode (Default)
|
||||
|
||||
**Use Case**: Private network file transfer, personal use, testing environment
|
||||
|
||||
```bash
|
||||
@@ -67,12 +71,14 @@ bash deploy.sh
|
||||
```
|
||||
|
||||
**Features**:
|
||||
|
||||
- ✅ HTTP access
|
||||
- ✅ Private network P2P transfer
|
||||
- ✅ Uses public STUN servers
|
||||
- ✅ Uses public STUN servers
|
||||
- ✅ Zero configuration startup
|
||||
|
||||
### Public Mode
|
||||
|
||||
**Use Case**: Servers with public IP but no domain
|
||||
|
||||
```bash
|
||||
@@ -80,12 +86,14 @@ bash deploy.sh --mode public --with-turn
|
||||
```
|
||||
|
||||
**Features**:
|
||||
|
||||
- ✅ HTTP access
|
||||
- ✅ Built-in TURN server
|
||||
- ✅ Supports complex network environments
|
||||
- ✅ Automatic NAT traversal configuration
|
||||
|
||||
### Full Mode
|
||||
|
||||
**Use Case**: Production environment, public servers with domain
|
||||
|
||||
```bash
|
||||
@@ -93,12 +101,15 @@ bash deploy.sh --domain your-domain.com --mode full --with-nginx --with-turn
|
||||
```
|
||||
|
||||
**Features**:
|
||||
|
||||
- ✅ HTTPS secure access
|
||||
- ✅ Self-signed SSL certificates
|
||||
- ✅ Nginx reverse proxy
|
||||
- ✅ Built-in TURN server
|
||||
- ✅ Complete production environment configuration
|
||||
|
||||
> Tip: If your network uses carrier-grade NAT or proxy and is mis-detected as public, append `--mode private` to skip public-IP probing and force basic mode. When the detected LAN IP is not the one you expect, append `--local-ip 192.168.x.x` to override it explicitly.
|
||||
|
||||
## 🔧 Advanced Configuration
|
||||
|
||||
### Custom Ports
|
||||
@@ -110,6 +121,18 @@ BACKEND_PORT=8081
|
||||
HTTP_PORT=8000
|
||||
```
|
||||
|
||||
### Build-Time Proxy (optional)
|
||||
|
||||
Set the following variables in `.env` (or export them before running `deploy.sh`) when the build needs to go through a proxy. The configuration generator now preserves these fields on subsequent runs.
|
||||
|
||||
```bash
|
||||
HTTP_PROXY=http://your-proxy:7890
|
||||
HTTPS_PROXY=http://your-proxy:7890
|
||||
NO_PROXY=localhost,127.0.0.1,backend,frontend,redis,coturn
|
||||
```
|
||||
|
||||
`docker-compose` passes these values as build args; the Dockerfiles expose them as environment variables so `npm`/`pnpm` automatically reuse the proxy. Leave them blank if you don't need a proxy.
|
||||
|
||||
### Enable Specific Services
|
||||
|
||||
```bash
|
||||
@@ -123,44 +146,44 @@ bash deploy.sh --with-turn
|
||||
bash deploy.sh --with-nginx --with-turn
|
||||
```
|
||||
|
||||
### Development Mode Deployment
|
||||
|
||||
```bash
|
||||
# Enable development mode (supports hot code reloading)
|
||||
bash deploy.sh --dev
|
||||
```
|
||||
|
||||
## 🌐 Access Methods
|
||||
|
||||
### Local Access
|
||||
- **Frontend App**: http://localhost:3000
|
||||
|
||||
- **Frontend App**: http://localhost:3002
|
||||
- **API Interface**: http://localhost:3001
|
||||
- **Health Check**: http://localhost:3001/health
|
||||
|
||||
### LAN Access
|
||||
|
||||
After deployment, the script automatically displays LAN access addresses:
|
||||
|
||||
```
|
||||
🌐 LAN Access:
|
||||
Frontend App: http://192.168.1.100:3000
|
||||
Frontend App: http://192.168.1.100:3002
|
||||
Backend API: http://192.168.1.100:3001
|
||||
```
|
||||
|
||||
### HTTPS Access (if enabled)
|
||||
|
||||
- **Secure Access**: https://localhost
|
||||
- **Certificate Location**: `docker/ssl/ca-cert.pem`
|
||||
|
||||
**Note**: When first accessing HTTPS, the browser will warn about an untrusted certificate. This is normal. You can:
|
||||
|
||||
1. Click "Advanced" → "Continue to site"
|
||||
2. Or import the `docker/ssl/ca-cert.pem` certificate into your browser
|
||||
|
||||
## 🔍 Management Commands
|
||||
|
||||
### View Service Status
|
||||
|
||||
```bash
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
### View Service Logs
|
||||
|
||||
```bash
|
||||
# View all service logs
|
||||
docker-compose logs -f
|
||||
@@ -172,6 +195,7 @@ docker-compose logs -f redis
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
# Restart all services
|
||||
docker-compose restart
|
||||
@@ -181,6 +205,7 @@ docker-compose restart backend
|
||||
```
|
||||
|
||||
### Stop Services
|
||||
|
||||
```bash
|
||||
# Stop services but keep data
|
||||
docker-compose stop
|
||||
@@ -190,6 +215,7 @@ docker-compose down
|
||||
```
|
||||
|
||||
### Complete Cleanup
|
||||
|
||||
```bash
|
||||
# Clean all containers, images and data
|
||||
bash deploy.sh --clean
|
||||
@@ -200,26 +226,33 @@ bash deploy.sh --clean
|
||||
### Common Issues
|
||||
|
||||
#### 1. Port Already in Use
|
||||
|
||||
**Symptom**: Deployment shows port occupation warning
|
||||
|
||||
```
|
||||
⚠️ The following ports are already in use: 3000, 3001
|
||||
⚠️ The following ports are already in use: 3002, 3001
|
||||
```
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
# Method 1: Modify port configuration
|
||||
echo "FRONTEND_PORT=8080" >> .env
|
||||
echo "BACKEND_PORT=8081" >> .env
|
||||
|
||||
# Method 2: Stop programs using the ports
|
||||
sudo ss -tulpn | grep :3000
|
||||
```bash
|
||||
# First try cleaning previous containers
|
||||
bash deploy.sh --clean # or docker-compose down
|
||||
|
||||
# If the port is still occupied, locate the process
|
||||
sudo ss -tulpn | grep :3002
|
||||
sudo kill -9 <PID>
|
||||
|
||||
# Finally, adjust the exposed ports in .env if necessary
|
||||
vim .env # Update FRONTEND_PORT / BACKEND_PORT
|
||||
```
|
||||
|
||||
#### 2. Insufficient Memory
|
||||
|
||||
**Symptom**: Containers fail to start or restart frequently
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Check memory usage
|
||||
free -h
|
||||
@@ -232,9 +265,11 @@ sudo swapon /swapfile
|
||||
```
|
||||
|
||||
#### 3. Docker Permission Issues
|
||||
|
||||
**Symptom**: Permission denied errors
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Add user to docker group
|
||||
sudo usermod -aG docker $USER
|
||||
@@ -244,16 +279,18 @@ newgrp docker
|
||||
```
|
||||
|
||||
#### 4. Service Inaccessible
|
||||
|
||||
**Symptom**: Browser cannot open pages
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# 1. Check service status
|
||||
docker-compose ps
|
||||
|
||||
# 2. Check health status
|
||||
curl http://localhost:3001/health
|
||||
curl http://localhost:3000/api/health
|
||||
curl http://localhost:3002/api/health
|
||||
|
||||
# 3. View detailed logs
|
||||
docker-compose logs -f
|
||||
@@ -263,9 +300,11 @@ sudo ufw status
|
||||
```
|
||||
|
||||
#### 5. WebRTC Connection Failure
|
||||
|
||||
**Symptom**: Cannot establish P2P connections
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Enable TURN server
|
||||
bash deploy.sh --with-turn
|
||||
@@ -285,7 +324,7 @@ bash test-health-apis.sh
|
||||
# Manual service checks
|
||||
curl http://localhost:3001/health # Backend basic check
|
||||
curl http://localhost:3001/health/detailed # Backend detailed check
|
||||
curl http://localhost:3000/api/health # Frontend check
|
||||
curl http://localhost:3002/api/health # Frontend check
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
@@ -306,11 +345,13 @@ docker system prune -f
|
||||
### Production Environment Optimization
|
||||
|
||||
1. **Enable Nginx Caching**:
|
||||
|
||||
```bash
|
||||
bash deploy.sh --with-nginx
|
||||
```
|
||||
|
||||
2. **Configure Resource Limits**:
|
||||
|
||||
```yaml
|
||||
# Add to docker-compose.yml
|
||||
services:
|
||||
@@ -324,6 +365,7 @@ services:
|
||||
```
|
||||
|
||||
3. **Enable Log Rotation**:
|
||||
|
||||
```bash
|
||||
# Configure log size limits
|
||||
echo '{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}' | sudo tee /etc/docker/daemon.json
|
||||
@@ -333,6 +375,7 @@ sudo systemctl restart docker
|
||||
### Network Optimization
|
||||
|
||||
1. **Use Dedicated Network**:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
privydrop-network:
|
||||
@@ -343,6 +386,7 @@ networks:
|
||||
```
|
||||
|
||||
2. **Enable HTTP/2**:
|
||||
|
||||
```bash
|
||||
# Auto-enabled (requires HTTPS)
|
||||
bash deploy.sh --mode full --with-nginx
|
||||
@@ -353,6 +397,7 @@ bash deploy.sh --mode full --with-nginx
|
||||
### SSL/TLS Configuration
|
||||
|
||||
1. **Self-signed Certificates** (default):
|
||||
|
||||
- Automatically generated and configured
|
||||
- Suitable for private networks and testing
|
||||
- Certificate location: `docker/ssl/`
|
||||
@@ -364,6 +409,7 @@ bash deploy.sh --mode full --with-nginx
|
||||
### Network Security
|
||||
|
||||
1. **Firewall Configuration**:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo ufw allow 80/tcp
|
||||
@@ -438,16 +484,19 @@ docker-compose up -d
|
||||
## 🆘 Getting Help
|
||||
|
||||
### Command Line Help
|
||||
|
||||
```bash
|
||||
bash deploy.sh --help
|
||||
```
|
||||
|
||||
### Online Resources
|
||||
|
||||
- [Project Homepage](https://github.com/david-bai00/PrivyDrop)
|
||||
- [Live Demo](https://www.privydrop.app/)
|
||||
- [Issue Reporting](https://github.com/david-bai00/PrivyDrop/issues)
|
||||
|
||||
### Community Support
|
||||
|
||||
- GitHub Issues: Technical questions and bug reports
|
||||
- GitHub Discussions: Usage discussions and feature suggestions
|
||||
|
||||
@@ -456,6 +505,7 @@ bash deploy.sh --help
|
||||
## 📝 Changelog
|
||||
|
||||
### v1.0.0 (Docker Version)
|
||||
|
||||
- ✅ Added Docker one-click deployment support
|
||||
- ✅ Added health check APIs
|
||||
- ✅ Added automatic environment detection and configuration generation
|
||||
@@ -465,4 +515,4 @@ bash deploy.sh --help
|
||||
|
||||
---
|
||||
|
||||
**🎉 Congratulations! You have successfully deployed PrivyDrop. Start enjoying secure, private file sharing!**
|
||||
**🎉 Congratulations! You have successfully deployed PrivyDrop. Start enjoying secure, private file sharing!**
|
||||
|
||||
@@ -6,34 +6,37 @@
|
||||
|
||||
相比传统部署方式,Docker 部署具有以下优势:
|
||||
|
||||
| 对比项目 | 传统部署 | Docker 部署 |
|
||||
|---------|---------|------------|
|
||||
| **部署时间** | 30-60分钟 | 5分钟 |
|
||||
| **技术要求** | Linux运维经验 | 会用Docker即可 |
|
||||
| **环境要求** | 公网IP + 域名 | 内网即可使用 |
|
||||
| **配置复杂度** | 10+个手动步骤 | 一键自动配置 |
|
||||
| **成功率** | ~70% | >95% |
|
||||
| **维护难度** | 需要手动管理多个服务 | 容器自动管理 |
|
||||
| 对比项目 | 传统部署 | Docker 部署 |
|
||||
| -------------- | -------------------- | ---------------- |
|
||||
| **部署时间** | 30-60 分钟 | 5 分钟 |
|
||||
| **技术要求** | Linux 运维经验 | 会用 Docker 即可 |
|
||||
| **环境要求** | 公网 IP + 域名 | 内网即可使用 |
|
||||
| **配置复杂度** | 10+个手动步骤 | 一键自动配置 |
|
||||
| **成功率** | ~70% | >95% |
|
||||
| **维护难度** | 需要手动管理多个服务 | 容器自动管理 |
|
||||
|
||||
## 📋 系统要求
|
||||
|
||||
### 最低配置
|
||||
- **CPU**: 1核
|
||||
|
||||
- **CPU**: 1 核
|
||||
- **内存**: 512MB
|
||||
- **磁盘**: 2GB 可用空间
|
||||
- **网络**: 任意网络环境(内网/公网均可)
|
||||
|
||||
### 推荐配置
|
||||
- **CPU**: 2核及以上
|
||||
- **内存**: 1GB及以上
|
||||
- **磁盘**: 5GB及以上可用空间
|
||||
- **网络**: 100Mbps及以上
|
||||
|
||||
- **CPU**: 2 核及以上
|
||||
- **内存**: 1GB 及以上
|
||||
- **磁盘**: 5GB 及以上可用空间
|
||||
- **网络**: 100Mbps 及以上
|
||||
|
||||
### 软件依赖
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+ (或 docker-compose 1.27+)
|
||||
- curl (用于健康检查)
|
||||
- openssl (用于SSL证书生成)
|
||||
- openssl (用于 SSL 证书生成)
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
@@ -52,7 +55,7 @@ cd PrivyDrop
|
||||
bash deploy.sh
|
||||
|
||||
# 等待部署完成后访问
|
||||
# http://localhost:3000
|
||||
# http://localhost:3002
|
||||
```
|
||||
|
||||
就是这么简单!🎉
|
||||
@@ -60,6 +63,7 @@ bash deploy.sh
|
||||
## 📚 部署模式详解
|
||||
|
||||
### 基础模式 (默认)
|
||||
|
||||
**适用场景**: 内网文件传输、个人使用、测试环境
|
||||
|
||||
```bash
|
||||
@@ -67,25 +71,29 @@ bash deploy.sh
|
||||
```
|
||||
|
||||
**特性**:
|
||||
|
||||
- ✅ HTTP 访问
|
||||
- ✅ 内网 P2P 传输
|
||||
- ✅ 使用公共 STUN 服务器
|
||||
- ✅ 零配置启动
|
||||
|
||||
### 公网模式
|
||||
**适用场景**: 有公网IP但无域名的服务器
|
||||
|
||||
**适用场景**: 有公网 IP 但无域名的服务器
|
||||
|
||||
```bash
|
||||
bash deploy.sh --mode public --with-turn
|
||||
```
|
||||
|
||||
**特性**:
|
||||
|
||||
- ✅ HTTP 访问
|
||||
- ✅ 内置 TURN 服务器
|
||||
- ✅ 支持复杂网络环境
|
||||
- ✅ 自动配置 NAT 穿透
|
||||
|
||||
### 完整模式
|
||||
|
||||
**适用场景**: 生产环境、有域名的公网服务器
|
||||
|
||||
```bash
|
||||
@@ -93,12 +101,15 @@ bash deploy.sh --domain your-domain.com --mode full --with-nginx --with-turn
|
||||
```
|
||||
|
||||
**特性**:
|
||||
|
||||
- ✅ HTTPS 安全访问
|
||||
- ✅ 自签名 SSL 证书
|
||||
- ✅ Nginx 反向代理
|
||||
- ✅ 内置 TURN 服务器
|
||||
- ✅ 完整生产环境配置
|
||||
|
||||
> 提示:若家庭宽带/运营商代理导致脚本误判为公网环境,可追加 `--mode private` 强制跳过公网检测,按基础模式执行;如果自动识别到的局域网地址不是你想要的,可进一步追加 `--local-ip 192.168.x.x` 显式指定。
|
||||
|
||||
## 🔧 高级配置
|
||||
|
||||
### 自定义端口
|
||||
@@ -110,6 +121,18 @@ BACKEND_PORT=8081
|
||||
HTTP_PORT=8000
|
||||
```
|
||||
|
||||
### 构建阶段代理(可选)
|
||||
|
||||
若需要在 Docker 构建时走网络代理,可在 `.env` 中设置以下变量,或者在执行 `deploy.sh` 之前通过环境变量导出。重新运行配置脚本时,这些字段会被保留:
|
||||
|
||||
```bash
|
||||
HTTP_PROXY=http://你的代理:7890
|
||||
HTTPS_PROXY=http://你的代理:7890
|
||||
NO_PROXY=localhost,127.0.0.1,backend,frontend,redis,coturn
|
||||
```
|
||||
|
||||
`docker-compose` 会把这些变量作为 build args 传递给前后端镜像,Dockerfile 中会自动设置为环境变量,从而让 `npm`/`pnpm` 使用代理。若无需代理,保持为空即可。
|
||||
|
||||
### 启用特定服务
|
||||
|
||||
```bash
|
||||
@@ -123,44 +146,44 @@ bash deploy.sh --with-turn
|
||||
bash deploy.sh --with-nginx --with-turn
|
||||
```
|
||||
|
||||
### 开发模式部署
|
||||
|
||||
```bash
|
||||
# 启用开发模式 (支持代码热更新)
|
||||
bash deploy.sh --dev
|
||||
```
|
||||
|
||||
## 🌐 访问方式
|
||||
|
||||
### 本机访问
|
||||
- **前端应用**: http://localhost:3000
|
||||
- **API接口**: http://localhost:3001
|
||||
|
||||
- **前端应用**: http://localhost:3002
|
||||
- **API 接口**: http://localhost:3001
|
||||
- **健康检查**: http://localhost:3001/health
|
||||
|
||||
### 局域网访问
|
||||
|
||||
部署完成后,脚本会自动显示局域网访问地址:
|
||||
|
||||
```
|
||||
🌐 局域网访问:
|
||||
前端应用: http://192.168.1.100:3000
|
||||
前端应用: http://192.168.1.100:3002
|
||||
后端API: http://192.168.1.100:3001
|
||||
```
|
||||
|
||||
### HTTPS访问 (如果启用)
|
||||
### HTTPS 访问 (如果启用)
|
||||
|
||||
- **安全访问**: https://localhost
|
||||
- **证书位置**: `docker/ssl/ca-cert.pem`
|
||||
|
||||
**注意**: 首次访问HTTPS时,浏览器会提示证书不受信任,这是正常的。可以:
|
||||
**注意**: 首次访问 HTTPS 时,浏览器会提示证书不受信任,这是正常的。可以:
|
||||
|
||||
1. 点击"高级" → "继续访问"
|
||||
2. 或导入 `docker/ssl/ca-cert.pem` 证书到浏览器
|
||||
|
||||
## 🔍 管理命令
|
||||
|
||||
### 查看服务状态
|
||||
|
||||
```bash
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
### 查看服务日志
|
||||
|
||||
```bash
|
||||
# 查看所有服务日志
|
||||
docker-compose logs -f
|
||||
@@ -172,6 +195,7 @@ docker-compose logs -f redis
|
||||
```
|
||||
|
||||
### 重启服务
|
||||
|
||||
```bash
|
||||
# 重启所有服务
|
||||
docker-compose restart
|
||||
@@ -181,6 +205,7 @@ docker-compose restart backend
|
||||
```
|
||||
|
||||
### 停止服务
|
||||
|
||||
```bash
|
||||
# 停ิ止服务但保留数据
|
||||
docker-compose stop
|
||||
@@ -190,6 +215,7 @@ docker-compose down
|
||||
```
|
||||
|
||||
### 完全清理
|
||||
|
||||
```bash
|
||||
# 清理所有容器、镜像和数据
|
||||
bash deploy.sh --clean
|
||||
@@ -200,26 +226,33 @@ bash deploy.sh --clean
|
||||
### 常见问题
|
||||
|
||||
#### 1. 端口被占用
|
||||
|
||||
**现象**: 部署时提示端口已被占用
|
||||
|
||||
```
|
||||
⚠️ 以下端口已被占用: 3000, 3001
|
||||
⚠️ 以下端口已被占用: 3002, 3001
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 方法1: 修改端口配置
|
||||
echo "FRONTEND_PORT=8080" >> .env
|
||||
echo "BACKEND_PORT=8081" >> .env
|
||||
|
||||
# 方法2: 停止占用端口的程序
|
||||
sudo ss -tulpn | grep :3000
|
||||
```bash
|
||||
# 方法1: 清理旧容器
|
||||
bash deploy.sh --clean # 或 docker-compose down
|
||||
|
||||
# 方法2: 查找并结束占用进程
|
||||
sudo ss -tulpn | grep :3002
|
||||
sudo kill -9 <PID>
|
||||
|
||||
# 方法3: 如仍冲突,再调整端口
|
||||
vim .env # 修改 FRONTEND_PORT / BACKEND_PORT
|
||||
```
|
||||
|
||||
#### 2. 内存不足
|
||||
|
||||
**现象**: 容器启动失败或频繁重启
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 检查内存使用
|
||||
free -h
|
||||
@@ -231,10 +264,12 @@ sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
```
|
||||
|
||||
#### 3. Docker权限问题
|
||||
#### 3. Docker 权限问题
|
||||
|
||||
**现象**: 提示权限不足
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 将用户添加到docker组
|
||||
sudo usermod -aG docker $USER
|
||||
@@ -244,16 +279,18 @@ newgrp docker
|
||||
```
|
||||
|
||||
#### 4. 服务无法访问
|
||||
|
||||
**现象**: 浏览器无法打开页面
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 1. 检查服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 2. 检查健康状态
|
||||
curl http://localhost:3001/health
|
||||
curl http://localhost:3000/api/health
|
||||
curl http://localhost:3002/api/health
|
||||
|
||||
# 3. 查看详细日志
|
||||
docker-compose logs -f
|
||||
@@ -262,10 +299,12 @@ docker-compose logs -f
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
#### 5. WebRTC连接失败
|
||||
**现象**: 无法建立P2P连接
|
||||
#### 5. WebRTC 连接失败
|
||||
|
||||
**现象**: 无法建立 P2P 连接
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 启用TURN服务器
|
||||
bash deploy.sh --with-turn
|
||||
@@ -285,7 +324,7 @@ bash test-health-apis.sh
|
||||
# 手动检查各服务
|
||||
curl http://localhost:3001/health # 后端基础检查
|
||||
curl http://localhost:3001/health/detailed # 后端详细检查
|
||||
curl http://localhost:3000/api/health # 前端检查
|
||||
curl http://localhost:3002/api/health # 前端检查
|
||||
```
|
||||
|
||||
### 性能监控
|
||||
@@ -306,11 +345,13 @@ docker system prune -f
|
||||
### 生产环境优化
|
||||
|
||||
1. **启用 Nginx 缓存**:
|
||||
|
||||
```bash
|
||||
bash deploy.sh --with-nginx
|
||||
```
|
||||
|
||||
2. **配置资源限制**:
|
||||
|
||||
```yaml
|
||||
# 在 docker-compose.yml 中添加
|
||||
services:
|
||||
@@ -324,6 +365,7 @@ services:
|
||||
```
|
||||
|
||||
3. **启用日志轮转**:
|
||||
|
||||
```bash
|
||||
# 配置日志大小限制
|
||||
echo '{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}' | sudo tee /etc/docker/daemon.json
|
||||
@@ -333,6 +375,7 @@ sudo systemctl restart docker
|
||||
### 网络优化
|
||||
|
||||
1. **使用专用网络**:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
privydrop-network:
|
||||
@@ -343,6 +386,7 @@ networks:
|
||||
```
|
||||
|
||||
2. **启用 HTTP/2**:
|
||||
|
||||
```bash
|
||||
# 自动启用 (需要 HTTPS)
|
||||
bash deploy.sh --mode full --with-nginx
|
||||
@@ -350,20 +394,22 @@ bash deploy.sh --mode full --with-nginx
|
||||
|
||||
## 🔒 安全配置
|
||||
|
||||
### SSL/TLS配置
|
||||
### SSL/TLS 配置
|
||||
|
||||
1. **自签名证书** (默认):
|
||||
|
||||
- 自动生成和配置
|
||||
- 适用于内网和测试环境
|
||||
- 证书位置: `docker/ssl/`
|
||||
|
||||
2. **Let's Encrypt证书** (计划中):
|
||||
2. **Let's Encrypt 证书** (计划中):
|
||||
- 自动申请和续期
|
||||
- 适用于有域名的生产环境
|
||||
|
||||
### 网络安全
|
||||
|
||||
1. **防火墙配置**:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo ufw allow 80/tcp
|
||||
@@ -438,31 +484,35 @@ docker-compose up -d
|
||||
## 🆘 获取帮助
|
||||
|
||||
### 命令行帮助
|
||||
|
||||
```bash
|
||||
bash deploy.sh --help
|
||||
```
|
||||
|
||||
### 在线资源
|
||||
|
||||
- [项目主页](https://github.com/david-bai00/PrivyDrop)
|
||||
- [在线演示](https://www.privydrop.app/)
|
||||
- [问题反馈](https://github.com/david-bai00/PrivyDrop/issues)
|
||||
|
||||
### 社区支持
|
||||
- GitHub Issues: 技术问题和bug报告
|
||||
|
||||
- GitHub Issues: 技术问题和 bug 报告
|
||||
- GitHub Discussions: 使用交流和功能建议
|
||||
|
||||
---
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.0.0 (Docker化版本)
|
||||
### v1.0.0 (Docker 化版本)
|
||||
|
||||
- ✅ 新增 Docker 一键部署支持
|
||||
- ✅ 新增健康检查API
|
||||
- ✅ 新增健康检查 API
|
||||
- ✅ 新增自动环境检测和配置生成
|
||||
- ✅ 新增多种部署模式
|
||||
- ✅ 新增完整的故障排除指南
|
||||
- ✅ 支持内网部署,无需公网IP
|
||||
- ✅ 支持内网部署,无需公网 IP
|
||||
|
||||
---
|
||||
|
||||
**🎉 恭喜!你已经成功部署了 PrivyDrop。开始享受安全、私密的文件分享吧!**
|
||||
**🎉 恭喜!你已经成功部署了 PrivyDrop。开始享受安全、私密的文件分享吧!**
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
node_modules
|
||||
.next
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
.env*
|
||||
npm-debug.log*
|
||||
.npm
|
||||
coverage
|
||||
.nyc_output
|
||||
*.log
|
||||
public/sw.js
|
||||
public/workbox-*.js
|
||||
+16
-20
@@ -1,17 +1,21 @@
|
||||
# 多阶段构建 - 构建阶段
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
ARG HTTP_PROXY
|
||||
ARG HTTPS_PROXY
|
||||
ARG NO_PROXY
|
||||
|
||||
ENV http_proxy=${HTTP_PROXY} \
|
||||
https_proxy=${HTTPS_PROXY} \
|
||||
no_proxy=${NO_PROXY}
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装构建依赖
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
# 复制package文件
|
||||
COPY package*.json ./
|
||||
COPY pnpm-lock.yaml ./
|
||||
|
||||
# 安装pnpm
|
||||
RUN npm install -g pnpm
|
||||
# 安装pnpm(使用npm,避免网络问题)
|
||||
RUN npm install -g pnpm --no-audit --no-fund
|
||||
|
||||
# 安装依赖
|
||||
RUN pnpm install --frozen-lockfile
|
||||
@@ -31,12 +35,6 @@ FROM node:18-alpine AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装运行时依赖
|
||||
RUN apk add --no-cache \
|
||||
curl \
|
||||
dumb-init \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# 创建非root用户
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nextjs -u 1001 -G nodejs
|
||||
@@ -45,24 +43,22 @@ RUN addgroup -g 1001 -S nodejs && \
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
COPY health-check.js ./
|
||||
|
||||
# 设置环境变量
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ENV PORT 3000
|
||||
ENV PORT 3002
|
||||
ENV HOSTNAME "0.0.0.0"
|
||||
|
||||
USER nextjs
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 3000
|
||||
EXPOSE 3002
|
||||
|
||||
# 健康检查
|
||||
# 使用Node.js脚本做健康检查(替代curl)
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:3000/api/health || exit 1
|
||||
|
||||
# 使用dumb-init作为PID 1
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
CMD node health-check.js
|
||||
|
||||
# 启动应用
|
||||
CMD ["node", "server.js"]
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
@@ -225,7 +225,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
|
||||
}
|
||||
return updated;
|
||||
});
|
||||
}, 3000);
|
||||
}, 3002);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const http = require('http');
|
||||
|
||||
const options = {
|
||||
host: 'localhost',
|
||||
port: process.env.PORT || 3002,
|
||||
path: '/api/health',
|
||||
timeout: 2000,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
console.log('Frontend health check passed');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log(`Frontend health check failed with status: ${res.statusCode}`);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
console.log(`Frontend health check failed: ${err.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
req.on('timeout', () => {
|
||||
console.log('Frontend health check timeout');
|
||||
req.destroy();
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
req.end();
|
||||
@@ -27,7 +27,7 @@ export class ReceptionConfig {
|
||||
// Network and timing
|
||||
static readonly NETWORK_CONFIG = {
|
||||
FIREFOX_COMPATIBILITY_DELAY: 10, // ms delay for Firefox compatibility
|
||||
FINALIZATION_TIMEOUT: 30000, // 30s timeout for file finalization
|
||||
FINALIZATION_TIMEOUT: 30020, // 30s timeout for file finalization
|
||||
GRACEFUL_SHUTDOWN_TIMEOUT: 5000, // 5s timeout for graceful shutdown
|
||||
};
|
||||
|
||||
@@ -54,7 +54,10 @@ export class ReceptionConfig {
|
||||
/**
|
||||
* Calculate expected chunks count for file size and offset
|
||||
*/
|
||||
static calculateExpectedChunks(fileSize: number, startOffset: number = 0): number {
|
||||
static calculateExpectedChunks(
|
||||
fileSize: number,
|
||||
startOffset: number = 0
|
||||
): number {
|
||||
return Math.ceil((fileSize - startOffset) / this.FILE_CONFIG.CHUNK_SIZE);
|
||||
}
|
||||
|
||||
@@ -68,7 +71,12 @@ export class ReceptionConfig {
|
||||
/**
|
||||
* Check if file should be saved to disk
|
||||
*/
|
||||
static shouldSaveToDisk(fileSize: number, hasSaveDirectory: boolean): boolean {
|
||||
return hasSaveDirectory || fileSize >= this.FILE_CONFIG.LARGE_FILE_THRESHOLD;
|
||||
static shouldSaveToDisk(
|
||||
fileSize: number,
|
||||
hasSaveDirectory: boolean
|
||||
): boolean {
|
||||
return (
|
||||
hasSaveDirectory || fileSize >= this.FILE_CONFIG.LARGE_FILE_THRESHOLD
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"dev": "next dev -H 0.0.0.0 -p 3002",
|
||||
"build": "next build",
|
||||
"start": "next start -p 3000",
|
||||
"start": "next start -p 3002",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+4492
-2209
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@ else
|
||||
fi
|
||||
|
||||
# 检查前端健康
|
||||
if curl -f http://localhost:3000/api/health >/dev/null 2>&1; then
|
||||
if curl -f http://localhost:3002/api/health >/dev/null 2>&1; then
|
||||
echo "✅ 前端服务正常"
|
||||
else
|
||||
echo "❌ 前端服务异常"
|
||||
@@ -36,6 +36,6 @@ else
|
||||
|
||||
echo ""
|
||||
echo "🔗 访问链接:"
|
||||
echo " 前端应用: http://localhost:3000"
|
||||
echo " 前端应用: http://localhost:3002"
|
||||
echo " 后端API: http://localhost:3001"
|
||||
fi
|
||||
+3
-3
@@ -159,7 +159,7 @@ main() {
|
||||
backend_running=true
|
||||
fi
|
||||
|
||||
if check_service 3000 "前端"; then
|
||||
if check_service 3002 "前端"; then
|
||||
frontend_running=true
|
||||
fi
|
||||
|
||||
@@ -191,8 +191,8 @@ main() {
|
||||
if [ "$frontend_running" = true ]; then
|
||||
echo -e "${BLUE}=== 测试前端健康检查API ===${NC}"
|
||||
|
||||
test_api "http://localhost:3000/api/health" "前端基础健康检查"
|
||||
test_api "http://localhost:3000/api/health/detailed" "前端详细健康检查"
|
||||
test_api "http://localhost:3002/api/health" "前端基础健康检查"
|
||||
test_api "http://localhost:3002/api/health/detailed" "前端详细健康检查"
|
||||
fi
|
||||
|
||||
# 测试结果汇总
|
||||
|
||||
Reference in New Issue
Block a user