chore:Initial addition of Docker related content
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 全局变量
|
||||
NETWORK_MODE=""
|
||||
LOCAL_IP=""
|
||||
PUBLIC_IP=""
|
||||
DEPLOYMENT_MODE="basic"
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# 检测网络环境
|
||||
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
|
||||
|
||||
if [[ -z "$LOCAL_IP" ]]; then
|
||||
LOCAL_IP="127.0.0.1"
|
||||
log_warning "无法自动检测本机IP,使用默认值: $LOCAL_IP"
|
||||
fi
|
||||
|
||||
# 检测公网连接
|
||||
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 "检测到公网环境"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
echo " 公网IP: $PUBLIC_IP"
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
log_warning "公网连接不稳定,按内网环境处理"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
fi
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
log_success "检测到内网环境"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查系统资源
|
||||
check_system_resources() {
|
||||
log_info "检查系统资源..."
|
||||
|
||||
local warnings=0
|
||||
|
||||
# 检查内存
|
||||
if command -v free >/dev/null 2>&1; then
|
||||
TOTAL_MEM=$(free -m | awk 'NR==2{print $2}')
|
||||
if [[ $TOTAL_MEM -lt 512 ]]; then
|
||||
log_error "内存不足: ${TOTAL_MEM}MB (建议至少512MB)"
|
||||
return 1
|
||||
elif [[ $TOTAL_MEM -lt 1024 ]]; then
|
||||
log_warning "内存较少: ${TOTAL_MEM}MB (建议至少1GB)"
|
||||
warnings=$((warnings + 1))
|
||||
else
|
||||
log_success "内存充足: ${TOTAL_MEM}MB"
|
||||
fi
|
||||
else
|
||||
log_warning "无法检测内存使用情况"
|
||||
warnings=$((warnings + 1))
|
||||
fi
|
||||
|
||||
# 检查磁盘空间
|
||||
DISK_USAGE=$(df -h / | awk 'NR==2{print $5}' | sed 's/%//')
|
||||
if [[ $DISK_USAGE -gt 95 ]]; then
|
||||
log_error "磁盘空间不足: ${DISK_USAGE}%已使用"
|
||||
return 1
|
||||
elif [[ $DISK_USAGE -gt 80 ]]; then
|
||||
log_warning "磁盘空间紧张: ${DISK_USAGE}%已使用"
|
||||
warnings=$((warnings + 1))
|
||||
else
|
||||
log_success "磁盘空间充足: ${DISK_USAGE}%已使用"
|
||||
fi
|
||||
|
||||
# 检查可用磁盘空间
|
||||
AVAILABLE_SPACE=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
|
||||
if [[ $AVAILABLE_SPACE -lt 2 ]]; then
|
||||
log_error "可用磁盘空间不足: ${AVAILABLE_SPACE}GB (建议至少2GB)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ $warnings -gt 0 ]]; then
|
||||
log_warning "系统资源检查通过,但有 $warnings 个警告"
|
||||
else
|
||||
log_success "系统资源检查通过"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 验证Docker环境
|
||||
verify_docker_installation() {
|
||||
log_info "检查Docker环境..."
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装"
|
||||
echo "请安装Docker: https://docs.docker.com/get-docker/"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||||
log_error "Docker Compose未安装"
|
||||
echo "请安装Docker Compose: https://docs.docker.com/compose/install/"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查Docker服务状态
|
||||
if ! docker info &> /dev/null; then
|
||||
log_error "Docker服务未运行"
|
||||
echo "请启动Docker服务"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查Docker版本
|
||||
DOCKER_VERSION=$(docker --version | grep -oE '[0-9]+\.[0-9]+' | head -1)
|
||||
log_success "Docker版本: $DOCKER_VERSION"
|
||||
|
||||
# 检查Docker Compose版本
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
COMPOSE_VERSION=$(docker-compose --version | grep -oE '[0-9]+\.[0-9]+' | head -1)
|
||||
log_success "Docker Compose版本: $COMPOSE_VERSION"
|
||||
else
|
||||
COMPOSE_VERSION=$(docker compose version --short 2>/dev/null || echo "内置")
|
||||
log_success "Docker Compose版本: $COMPOSE_VERSION"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 检查端口占用
|
||||
check_port_availability() {
|
||||
local ports="$1"
|
||||
log_info "检查端口占用..."
|
||||
|
||||
local occupied_ports=()
|
||||
|
||||
IFS=',' read -ra PORT_ARRAY <<< "$ports"
|
||||
for port in "${PORT_ARRAY[@]}"; do
|
||||
port=$(echo "$port" | xargs) # 去除空格
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
if ss -tuln | grep -q ":$port "; then
|
||||
occupied_ports+=("$port")
|
||||
fi
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
if netstat -tuln 2>/dev/null | grep -q ":$port "; then
|
||||
occupied_ports+=("$port")
|
||||
fi
|
||||
else
|
||||
log_warning "无法检查端口占用情况 (缺少ss和netstat命令)"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#occupied_ports[@]} -gt 0 ]]; then
|
||||
log_warning "以下端口已被占用: ${occupied_ports[*]}"
|
||||
log_info "可以通过修改.env文件中的端口配置来解决冲突"
|
||||
else
|
||||
log_success "所有端口都可用"
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测部署模式
|
||||
detect_deployment_mode() {
|
||||
log_info "确定部署模式..."
|
||||
|
||||
if [[ "$NETWORK_MODE" == "public" ]] && [[ -n "$DOMAIN_NAME" ]]; then
|
||||
DEPLOYMENT_MODE="full"
|
||||
log_success "部署模式: 完整模式 (HTTPS + TURN服务器)"
|
||||
elif [[ "$NETWORK_MODE" == "public" ]]; then
|
||||
DEPLOYMENT_MODE="public"
|
||||
log_success "部署模式: 公网模式 (HTTP + 自签证书)"
|
||||
else
|
||||
DEPLOYMENT_MODE="basic"
|
||||
log_success "部署模式: 基础模式 (内网HTTP)"
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${BLUE}=== PrivyDrop Docker 环境检测 ===${NC}\n"
|
||||
|
||||
# 读取命令行参数
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--domain)
|
||||
DOMAIN_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--mode)
|
||||
DEPLOYMENT_MODE="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 执行检测
|
||||
detect_network_environment
|
||||
echo ""
|
||||
|
||||
if ! check_system_resources; then
|
||||
log_error "系统资源检查失败,请解决资源问题后重试"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if ! verify_docker_installation; then
|
||||
log_error "Docker环境检查失败,请安装并启动Docker"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
check_port_availability "80,443,3000,3001,3478,5349,6379"
|
||||
echo ""
|
||||
|
||||
detect_deployment_mode
|
||||
echo ""
|
||||
|
||||
log_success "环境检测完成!"
|
||||
echo -e "${BLUE}检测结果:${NC}"
|
||||
echo " 网络模式: $NETWORK_MODE"
|
||||
echo " 本机IP: $LOCAL_IP"
|
||||
[[ -n "$PUBLIC_IP" ]] && echo " 公网IP: $PUBLIC_IP"
|
||||
echo " 部署模式: $DEPLOYMENT_MODE"
|
||||
|
||||
# 导出环境变量供其他脚本使用
|
||||
export NETWORK_MODE
|
||||
export LOCAL_IP
|
||||
export PUBLIC_IP
|
||||
export DEPLOYMENT_MODE
|
||||
export DOMAIN_NAME
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 如果脚本被直接执行
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
@@ -0,0 +1,600 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 导入环境检测脚本
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/detect-environment.sh"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# 生成环境变量文件
|
||||
generate_env_file() {
|
||||
log_info "生成环境变量配置..."
|
||||
|
||||
local env_file=".env"
|
||||
|
||||
# 生成随机密码
|
||||
local turn_password=$(openssl rand -base64 32 2>/dev/null || echo "privydrop$(date +%s)")
|
||||
|
||||
cat > "$env_file" << EOF
|
||||
# PrivyDrop Docker 配置文件
|
||||
# 自动生成时间: $(date)
|
||||
# 网络模式: $NETWORK_MODE
|
||||
# 部署模式: $DEPLOYMENT_MODE
|
||||
|
||||
# =============================================================================
|
||||
# 网络配置
|
||||
# =============================================================================
|
||||
CORS_ORIGIN=http://${LOCAL_IP}
|
||||
NEXT_PUBLIC_API_URL=http://${LOCAL_IP}:3001
|
||||
|
||||
# =============================================================================
|
||||
# 端口配置
|
||||
# =============================================================================
|
||||
FRONTEND_PORT=3000
|
||||
BACKEND_PORT=3001
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
|
||||
# =============================================================================
|
||||
# Redis配置
|
||||
# =============================================================================
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
# =============================================================================
|
||||
# 部署配置
|
||||
# =============================================================================
|
||||
DEPLOYMENT_MODE=${DEPLOYMENT_MODE}
|
||||
NETWORK_MODE=${NETWORK_MODE}
|
||||
LOCAL_IP=${LOCAL_IP}
|
||||
PUBLIC_IP=${PUBLIC_IP:-}
|
||||
|
||||
# =============================================================================
|
||||
# SSL配置
|
||||
# =============================================================================
|
||||
SSL_MODE=self-signed
|
||||
DOMAIN_NAME=${DOMAIN_NAME:-}
|
||||
|
||||
# =============================================================================
|
||||
# TURN服务器配置 (可选)
|
||||
# =============================================================================
|
||||
TURN_ENABLED=${TURN_ENABLED:-false}
|
||||
TURN_USERNAME=privydrop
|
||||
TURN_PASSWORD=${turn_password}
|
||||
TURN_REALM=${DOMAIN_NAME:-turn.local}
|
||||
|
||||
# =============================================================================
|
||||
# Nginx配置
|
||||
# =============================================================================
|
||||
NGINX_SERVER_NAME=${DOMAIN_NAME:-${LOCAL_IP}}
|
||||
|
||||
# =============================================================================
|
||||
# 日志配置
|
||||
# =============================================================================
|
||||
LOG_LEVEL=info
|
||||
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"
|
||||
}
|
||||
|
||||
# 生成Nginx配置
|
||||
generate_nginx_config() {
|
||||
log_info "生成Nginx配置..."
|
||||
|
||||
mkdir -p docker/nginx/conf.d
|
||||
|
||||
local server_name="${DOMAIN_NAME:-${LOCAL_IP} localhost}"
|
||||
local upstream_backend="backend:3001"
|
||||
local upstream_frontend="frontend:3000"
|
||||
|
||||
# 生成主Nginx配置
|
||||
cat > docker/nginx/nginx.conf << 'EOF'
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# 日志格式
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
# 基础配置
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
server_tokens off;
|
||||
|
||||
# 客户端配置
|
||||
client_max_body_size 100M;
|
||||
client_header_timeout 60s;
|
||||
client_body_timeout 60s;
|
||||
|
||||
# Gzip配置
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1000;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/xml+rss
|
||||
application/json;
|
||||
|
||||
# 包含站点配置
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
EOF
|
||||
|
||||
# 生成站点配置
|
||||
cat > docker/nginx/conf.d/default.conf << EOF
|
||||
# 上游服务定义
|
||||
upstream backend {
|
||||
server ${upstream_backend};
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream frontend {
|
||||
server ${upstream_frontend};
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# HTTP服务器配置
|
||||
server {
|
||||
listen 80;
|
||||
server_name ${server_name};
|
||||
|
||||
# 安全头
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
|
||||
# 健康检查端点
|
||||
location /nginx-health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# 后端API代理
|
||||
location /api/ {
|
||||
proxy_pass http://backend/api/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
|
||||
# 超时配置
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
# 后端健康检查代理
|
||||
location /health {
|
||||
proxy_pass http://backend/health;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
}
|
||||
|
||||
# Socket.IO代理
|
||||
location /socket.io/ {
|
||||
proxy_pass http://backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
|
||||
# WebSocket特殊配置
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
}
|
||||
|
||||
# 前端应用代理
|
||||
location / {
|
||||
proxy_pass http://frontend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
|
||||
# Next.js特殊配置
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
log_success "Nginx配置已生成"
|
||||
echo " 主配置: docker/nginx/nginx.conf"
|
||||
echo " 站点配置: docker/nginx/conf.d/default.conf"
|
||||
}
|
||||
|
||||
# 生成SSL证书
|
||||
generate_ssl_certificates() {
|
||||
if [[ "$SSL_MODE" == "self-signed" ]] || [[ "$NETWORK_MODE" == "private" ]]; then
|
||||
log_info "生成自签名SSL证书..."
|
||||
|
||||
mkdir -p docker/ssl
|
||||
|
||||
# 生成CA私钥
|
||||
openssl genrsa -out docker/ssl/ca-key.pem 4096 2>/dev/null
|
||||
|
||||
# 生成CA证书
|
||||
openssl req -new -x509 -days 365 -key docker/ssl/ca-key.pem \
|
||||
-out docker/ssl/ca-cert.pem \
|
||||
-subj "/C=CN/ST=Local/L=Local/O=PrivyDrop/CN=PrivyDrop-CA" 2>/dev/null
|
||||
|
||||
# 生成服务器私钥
|
||||
openssl genrsa -out docker/ssl/server-key.pem 4096 2>/dev/null
|
||||
|
||||
# 生成服务器证书请求
|
||||
openssl req -new -key docker/ssl/server-key.pem \
|
||||
-out docker/ssl/server.csr \
|
||||
-subj "/C=CN/ST=Local/L=Local/O=PrivyDrop/CN=${LOCAL_IP}" 2>/dev/null
|
||||
|
||||
# 创建扩展配置
|
||||
cat > docker/ssl/server.ext << EOF
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = *.local
|
||||
DNS.3 = ${DOMAIN_NAME:-privydrop.local}
|
||||
IP.1 = ${LOCAL_IP}
|
||||
IP.2 = 127.0.0.1
|
||||
EOF
|
||||
|
||||
# 签名服务器证书
|
||||
openssl x509 -req -days 365 -in docker/ssl/server.csr \
|
||||
-CA docker/ssl/ca-cert.pem -CAkey docker/ssl/ca-key.pem \
|
||||
-out docker/ssl/server-cert.pem -CAcreateserial \
|
||||
-extensions v3_req -extfile docker/ssl/server.ext 2>/dev/null
|
||||
|
||||
# 清理临时文件
|
||||
rm -f docker/ssl/server.csr docker/ssl/server.ext docker/ssl/ca-cert.srl
|
||||
|
||||
# 设置权限
|
||||
chmod 600 docker/ssl/*-key.pem
|
||||
chmod 644 docker/ssl/*-cert.pem
|
||||
|
||||
log_success "SSL证书已生成: docker/ssl/"
|
||||
log_info "要信任证书,请导入CA证书: docker/ssl/ca-cert.pem"
|
||||
|
||||
# 生成HTTPS Nginx配置
|
||||
if [[ "$DEPLOYMENT_MODE" != "basic" ]]; then
|
||||
generate_https_nginx_config
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 生成HTTPS Nginx配置
|
||||
generate_https_nginx_config() {
|
||||
log_info "生成HTTPS Nginx配置..."
|
||||
|
||||
cat >> docker/nginx/conf.d/default.conf << EOF
|
||||
|
||||
# HTTPS服务器配置
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name ${DOMAIN_NAME:-${LOCAL_IP}};
|
||||
|
||||
# SSL配置
|
||||
ssl_certificate /etc/nginx/ssl/server-cert.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# 安全头
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
|
||||
# 健康检查端点
|
||||
location /nginx-health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# 后端API代理
|
||||
location /api/ {
|
||||
proxy_pass http://backend/api/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
}
|
||||
|
||||
# 后端健康检查代理
|
||||
location /health {
|
||||
proxy_pass http://backend/health;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
# Socket.IO代理
|
||||
location /socket.io/ {
|
||||
proxy_pass http://backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
}
|
||||
|
||||
# 前端应用代理
|
||||
location / {
|
||||
proxy_pass http://frontend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
log_success "HTTPS配置已添加"
|
||||
}
|
||||
|
||||
# 生成Coturn配置
|
||||
generate_coturn_config() {
|
||||
if [[ "$TURN_ENABLED" == "true" ]]; then
|
||||
log_info "生成Coturn TURN服务器配置..."
|
||||
|
||||
mkdir -p docker/coturn
|
||||
|
||||
cat > docker/coturn/turnserver.conf << EOF
|
||||
# PrivyDrop TURN服务器配置
|
||||
# 自动生成时间: $(date)
|
||||
|
||||
# 监听端口
|
||||
listening-port=3478
|
||||
tls-listening-port=5349
|
||||
|
||||
# 监听IP
|
||||
listening-ip=0.0.0.0
|
||||
relay-ip=0.0.0.0
|
||||
|
||||
# 外部IP (用于NAT环境)
|
||||
external-ip=${PUBLIC_IP:-${LOCAL_IP}}
|
||||
|
||||
# 服务器域名
|
||||
realm=${TURN_REALM}
|
||||
server-name=${TURN_REALM}
|
||||
|
||||
# 认证方式
|
||||
lt-cred-mech
|
||||
|
||||
# 用户认证
|
||||
user=${TURN_USERNAME}:${TURN_PASSWORD}
|
||||
|
||||
# SSL证书 (如果启用TLS)
|
||||
cert=/etc/ssl/certs/server-cert.pem
|
||||
pkey=/etc/ssl/certs/server-key.pem
|
||||
|
||||
# 日志配置
|
||||
no-stdout-log
|
||||
log-file=/var/log/turnserver.log
|
||||
verbose
|
||||
|
||||
# 安全配置
|
||||
no-cli
|
||||
no-loopback-peers
|
||||
no-multicast-peers
|
||||
|
||||
# 性能配置
|
||||
min-port=49152
|
||||
max-port=65535
|
||||
|
||||
# 数据库 (可选)
|
||||
# userdb=/var/lib/turn/turndb
|
||||
|
||||
# 其他配置
|
||||
mobility
|
||||
no-tlsv1
|
||||
no-tlsv1_1
|
||||
EOF
|
||||
|
||||
log_success "Coturn配置已生成: docker/coturn/turnserver.conf"
|
||||
log_info "TURN服务器用户名: ${TURN_USERNAME}"
|
||||
log_warning "TURN服务器密码已保存在.env文件中"
|
||||
fi
|
||||
}
|
||||
|
||||
# 生成Docker忽略文件
|
||||
generate_dockerignore() {
|
||||
log_info "生成Docker忽略文件..."
|
||||
|
||||
# 后端.dockerignore
|
||||
cat > backend/.dockerignore << EOF
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
.npm
|
||||
.env*
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
coverage
|
||||
.nyc_output
|
||||
logs
|
||||
*.log
|
||||
EOF
|
||||
|
||||
# 前端.dockerignore
|
||||
cat > frontend/.dockerignore << EOF
|
||||
node_modules
|
||||
.next
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
.env*
|
||||
npm-debug.log*
|
||||
.npm
|
||||
coverage
|
||||
.nyc_output
|
||||
*.log
|
||||
public/sw.js
|
||||
public/workbox-*.js
|
||||
EOF
|
||||
|
||||
log_success "Docker忽略文件已生成"
|
||||
}
|
||||
|
||||
# 创建日志目录
|
||||
create_log_directories() {
|
||||
log_info "创建日志目录..."
|
||||
|
||||
mkdir -p logs/{nginx,backend,frontend,coturn}
|
||||
|
||||
# 设置权限
|
||||
chmod 755 logs
|
||||
chmod 755 logs/*
|
||||
|
||||
log_success "日志目录已创建: logs/"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${BLUE}=== PrivyDrop 配置生成 ===${NC}"
|
||||
echo ""
|
||||
|
||||
# 首先运行环境检测
|
||||
if ! detect_network_environment; then
|
||||
log_error "环境检测失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! check_system_resources; then
|
||||
log_error "系统资源检查失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
detect_deployment_mode
|
||||
echo ""
|
||||
|
||||
# 生成所有配置文件
|
||||
generate_env_file
|
||||
echo ""
|
||||
|
||||
generate_nginx_config
|
||||
echo ""
|
||||
|
||||
generate_ssl_certificates
|
||||
echo ""
|
||||
|
||||
generate_coturn_config
|
||||
echo ""
|
||||
|
||||
generate_dockerignore
|
||||
echo ""
|
||||
|
||||
create_log_directories
|
||||
echo ""
|
||||
|
||||
log_success "🎉 所有配置文件生成完成!"
|
||||
echo ""
|
||||
echo -e "${BLUE}生成的文件:${NC}"
|
||||
echo " .env - 环境变量配置"
|
||||
echo " docker/nginx/ - Nginx配置"
|
||||
echo " docker/ssl/ - SSL证书"
|
||||
[[ "$TURN_ENABLED" == "true" ]] && echo " docker/coturn/ - TURN服务器配置"
|
||||
echo " logs/ - 日志目录"
|
||||
echo ""
|
||||
echo -e "${BLUE}下一步:${NC}"
|
||||
echo " 运行 './deploy.sh' 开始部署"
|
||||
}
|
||||
|
||||
# 如果脚本被直接执行
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
@@ -0,0 +1,420 @@
|
||||
#!/bin/bash
|
||||
|
||||
# PrivyDrop Docker 部署测试脚本
|
||||
# 用于验证部署的完整性和功能
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 测试结果统计
|
||||
TESTS_PASSED=0
|
||||
TESTS_FAILED=0
|
||||
TOTAL_TESTS=0
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
# 测试函数
|
||||
run_test() {
|
||||
local test_name="$1"
|
||||
local test_command="$2"
|
||||
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
log_info "测试: $test_name"
|
||||
|
||||
if eval "$test_command" >/dev/null 2>&1; then
|
||||
log_success "$test_name"
|
||||
return 0
|
||||
else
|
||||
log_error "$test_name"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Docker环境测试
|
||||
test_docker_environment() {
|
||||
echo -e "${BLUE}=== Docker环境测试 ===${NC}"
|
||||
|
||||
run_test "Docker已安装" "command -v docker"
|
||||
run_test "Docker服务运行中" "docker info"
|
||||
run_test "Docker Compose可用" "docker-compose --version || docker compose version"
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 容器状态测试
|
||||
test_container_status() {
|
||||
echo -e "${BLUE}=== 容器状态测试 ===${NC}"
|
||||
|
||||
# 检查容器是否存在和运行
|
||||
local containers=("privydrop-redis" "privydrop-backend" "privydrop-frontend")
|
||||
|
||||
for container in "${containers[@]}"; do
|
||||
run_test "容器 $container 运行中" "docker ps | grep -q $container"
|
||||
done
|
||||
|
||||
# 检查容器健康状态
|
||||
for container in "${containers[@]}"; do
|
||||
if docker ps --format "table {{.Names}}\t{{.Status}}" | grep -q "$container.*healthy"; then
|
||||
log_success "容器 $container 健康状态正常"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_warning "容器 $container 健康状态未知或不健康"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
done
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 网络连接测试
|
||||
test_network_connectivity() {
|
||||
echo -e "${BLUE}=== 网络连接测试 ===${NC}"
|
||||
|
||||
# 测试端口连通性
|
||||
local ports=("3000:前端" "3001:后端" "6379:Redis")
|
||||
|
||||
for port_info in "${ports[@]}"; do
|
||||
local port=$(echo "$port_info" | cut -d':' -f1)
|
||||
local service=$(echo "$port_info" | cut -d':' -f2)
|
||||
|
||||
run_test "$service 端口 $port 可访问" "nc -z localhost $port"
|
||||
done
|
||||
|
||||
# 测试容器间网络
|
||||
run_test "后端可连接Redis" "docker-compose exec -T backend sh -c 'nc -z redis 6379'"
|
||||
run_test "前端可连接后端" "curl -f http://localhost:3001/health"
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# API功能测试
|
||||
test_api_functionality() {
|
||||
echo -e "${BLUE}=== API功能测试 ===${NC}"
|
||||
|
||||
# 健康检查API
|
||||
run_test "后端健康检查API" "curl -f http://localhost:3001/health"
|
||||
run_test "前端健康检查API" "curl -f http://localhost:3000/api/health"
|
||||
|
||||
# 后端详细健康检查
|
||||
if curl -f http://localhost:3001/health/detailed >/dev/null 2>&1; then
|
||||
local redis_status=$(curl -s http://localhost:3001/health/detailed | jq -r '.dependencies.redis.status' 2>/dev/null)
|
||||
if [[ "$redis_status" == "connected" ]]; then
|
||||
log_success "Redis连接状态正常"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "Redis连接状态异常"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
else
|
||||
log_error "详细健康检查API不可用"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
# 业务API测试
|
||||
run_test "获取房间API" "curl -f http://localhost:3001/api/get_room"
|
||||
run_test "创建房间API" "curl -f -X POST -H 'Content-Type: application/json' -d '{\"roomId\":\"test123\"}' http://localhost:3001/api/create_room"
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# WebRTC功能测试
|
||||
test_webrtc_functionality() {
|
||||
echo -e "${BLUE}=== WebRTC功能测试 ===${NC}"
|
||||
|
||||
# 测试前端页面加载
|
||||
if curl -f http://localhost:3000 >/dev/null 2>&1; then
|
||||
log_success "前端页面可访问"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "前端页面不可访问"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
# 测试Socket.IO连接 (简单测试)
|
||||
if curl -f http://localhost:3001/socket.io/socket.io.js >/dev/null 2>&1; then
|
||||
log_success "Socket.IO客户端脚本可访问"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "Socket.IO客户端脚本不可访问"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 性能测试
|
||||
test_performance() {
|
||||
echo -e "${BLUE}=== 性能测试 ===${NC}"
|
||||
|
||||
# 内存使用测试
|
||||
local backend_memory=$(docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}" | grep privydrop-backend | awk '{print $2}' | cut -d'/' -f1)
|
||||
local frontend_memory=$(docker stats --no-stream --format "table {{.Container}}\t{{.MemUsage}}" | grep privydrop-frontend | awk '{print $2}' | cut -d'/' -f1)
|
||||
|
||||
if [[ -n "$backend_memory" ]]; then
|
||||
log_info "后端内存使用: $backend_memory"
|
||||
fi
|
||||
|
||||
if [[ -n "$frontend_memory" ]]; then
|
||||
log_info "前端内存使用: $frontend_memory"
|
||||
fi
|
||||
|
||||
# 响应时间测试
|
||||
local response_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:3001/health)
|
||||
if (( $(echo "$response_time < 1.0" | bc -l) )); then
|
||||
log_success "API响应时间正常: ${response_time}s"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_warning "API响应时间较慢: ${response_time}s"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 安全测试
|
||||
test_security() {
|
||||
echo -e "${BLUE}=== 安全测试 ===${NC}"
|
||||
|
||||
# 检查容器用户
|
||||
local backend_user=$(docker-compose exec -T backend whoami 2>/dev/null || echo "unknown")
|
||||
local frontend_user=$(docker-compose exec -T frontend whoami 2>/dev/null || echo "unknown")
|
||||
|
||||
if [[ "$backend_user" != "root" ]]; then
|
||||
log_success "后端容器使用非root用户: $backend_user"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_warning "后端容器使用root用户"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
if [[ "$frontend_user" != "root" ]]; then
|
||||
log_success "前端容器使用非root用户: $frontend_user"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_warning "前端容器使用root用户"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
# 检查敏感信息泄露
|
||||
if curl -s http://localhost:3001/health/detailed | grep -q "password\|secret\|key" >/dev/null 2>&1; then
|
||||
log_warning "健康检查API可能泄露敏感信息"
|
||||
else
|
||||
log_success "健康检查API未泄露敏感信息"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 日志测试
|
||||
test_logging() {
|
||||
echo -e "${BLUE}=== 日志测试 ===${NC}"
|
||||
|
||||
# 检查日志目录
|
||||
if [[ -d "logs" ]]; then
|
||||
log_success "日志目录存在"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_warning "日志目录不存在"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
# 检查日志文件
|
||||
local log_files=("logs/backend" "logs/frontend")
|
||||
for log_dir in "${log_files[@]}"; do
|
||||
if [[ -d "$log_dir" ]]; then
|
||||
log_success "日志目录 $log_dir 存在"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_info "日志目录 $log_dir 不存在 (可能正常)"
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
done
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 配置文件测试
|
||||
test_configuration() {
|
||||
echo -e "${BLUE}=== 配置文件测试 ===${NC}"
|
||||
|
||||
# 检查环境变量文件
|
||||
if [[ -f ".env" ]]; then
|
||||
log_success ".env 文件存在"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
|
||||
# 检查关键配置项
|
||||
local required_vars=("LOCAL_IP" "CORS_ORIGIN" "NEXT_PUBLIC_API_URL")
|
||||
for var in "${required_vars[@]}"; do
|
||||
if grep -q "^$var=" .env; then
|
||||
log_success "配置项 $var 已设置"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "配置项 $var 未设置"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
done
|
||||
else
|
||||
log_error ".env 文件不存在"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
# 检查Docker Compose文件
|
||||
if [[ -f "docker-compose.yml" ]]; then
|
||||
log_success "docker-compose.yml 文件存在"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "docker-compose.yml 文件不存在"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 清理测试
|
||||
test_cleanup() {
|
||||
echo -e "${BLUE}=== 清理功能测试 ===${NC}"
|
||||
|
||||
# 测试清理命令是否可用
|
||||
if [[ -f "deploy.sh" ]]; then
|
||||
log_success "部署脚本存在"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
|
||||
# 测试帮助命令
|
||||
if bash deploy.sh --help >/dev/null 2>&1; then
|
||||
log_success "部署脚本帮助功能正常"
|
||||
TESTS_PASSED=$((TESTS_PASSED + 1))
|
||||
else
|
||||
log_error "部署脚本帮助功能异常"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
else
|
||||
log_error "部署脚本不存在"
|
||||
TESTS_FAILED=$((TESTS_FAILED + 1))
|
||||
fi
|
||||
TOTAL_TESTS=$((TOTAL_TESTS + 2))
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 生成测试报告
|
||||
generate_report() {
|
||||
echo -e "${BLUE}=== 测试报告 ===${NC}"
|
||||
echo ""
|
||||
|
||||
echo "📊 测试统计:"
|
||||
echo " 总测试数: $TOTAL_TESTS"
|
||||
echo -e " 通过: ${GREEN}$TESTS_PASSED${NC}"
|
||||
echo -e " 失败: ${RED}$TESTS_FAILED${NC}"
|
||||
|
||||
local success_rate=$((TESTS_PASSED * 100 / TOTAL_TESTS))
|
||||
echo " 成功率: $success_rate%"
|
||||
|
||||
echo ""
|
||||
echo "📋 系统信息:"
|
||||
echo " Docker版本: $(docker --version)"
|
||||
echo " Docker Compose版本: $(docker-compose --version 2>/dev/null || docker compose version 2>/dev/null || echo '未知')"
|
||||
echo " 操作系统: $(uname -s) $(uname -r)"
|
||||
echo " 测试时间: $(date)"
|
||||
|
||||
echo ""
|
||||
if [[ $TESTS_FAILED -eq 0 ]]; then
|
||||
echo -e "${GREEN}🎉 所有测试通过!PrivyDrop 部署成功!${NC}"
|
||||
echo ""
|
||||
echo "🔗 访问链接:"
|
||||
echo " 前端应用: http://localhost:3000"
|
||||
echo " 后端API: http://localhost:3001"
|
||||
|
||||
# 显示局域网访问地址
|
||||
if [[ -f ".env" ]]; then
|
||||
local local_ip=$(grep "LOCAL_IP=" .env | cut -d'=' -f2)
|
||||
if [[ -n "$local_ip" && "$local_ip" != "127.0.0.1" ]]; then
|
||||
echo ""
|
||||
echo "🌐 局域网访问:"
|
||||
echo " 前端应用: http://$local_ip:3000"
|
||||
echo " 后端API: http://$local_ip:3001"
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}❌ 有 $TESTS_FAILED 个测试失败${NC}"
|
||||
echo ""
|
||||
echo "🔧 故障排除建议:"
|
||||
echo " 1. 查看容器状态: docker-compose ps"
|
||||
echo " 2. 查看容器日志: docker-compose logs -f"
|
||||
echo " 3. 重新部署: bash deploy.sh"
|
||||
echo " 4. 完全清理后重新部署: bash deploy.sh --clean"
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${BLUE}=== PrivyDrop Docker 部署测试开始 ===${NC}"
|
||||
echo ""
|
||||
|
||||
# 检查必要工具
|
||||
local missing_tools=()
|
||||
for tool in curl jq bc nc; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
missing_tools+=("$tool")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing_tools[@]} -gt 0 ]]; then
|
||||
log_warning "缺少测试工具: ${missing_tools[*]}"
|
||||
log_info "建议安装: sudo apt-get install curl jq bc netcat"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 运行所有测试
|
||||
test_docker_environment
|
||||
test_container_status
|
||||
test_network_connectivity
|
||||
test_api_functionality
|
||||
test_webrtc_functionality
|
||||
test_performance
|
||||
test_security
|
||||
test_logging
|
||||
test_configuration
|
||||
test_cleanup
|
||||
|
||||
# 生成报告
|
||||
generate_report
|
||||
}
|
||||
|
||||
# 捕获中断信号
|
||||
trap 'echo -e "\n${YELLOW}测试被中断${NC}"; exit 1' INT TERM
|
||||
|
||||
# 运行主函数
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user