#!/bin/bash # 设置变量 DATA_DIR="/data" SCRIPT_DIR="/boot/脚本" COMPOSE_FILE="$SCRIPT_DIR/ru.yaml" # 检查是否以 root 权限运行 if [ "$EUID" -ne 0 ]; then echo "请使用 sudo 运行此脚本" exit 1 fi # 函数:彻底清理 Docker 资源 cleanup_docker() { echo "清理 Docker 资源..." # 停止并删除所有相关容器 docker stop nginx-proxy-manager 2>/dev/null || true docker rm nginx-proxy-manager 2>/dev/null || true # 删除 Docker Compose 项目 docker compose -p nginx down 2>/dev/null || true # 清理网络 docker network prune -f # 检查并删除占用端口的僵尸容器 echo "检查占用端口的容器..." docker ps -a --format "table {{.Names}}\t{{.Ports}}" | grep -E "(80|81|443)" || echo "未发现明显端口冲突" } # 函数:更准确的端口检查 check_port_advanced() { local port=$1 echo "深度检查端口 $port ..." # 方法1: netstat if netstat -tulpn 2>/dev/null | grep -q ":${port} "; then echo "netstat 发现端口 $port 被占用" netstat -tulpn | grep ":${port} " return 1 fi # 方法2: ss if ss -tulpn 2>/dev/null | grep -q ":${port} "; then echo "ss 发现端口 $port 被占用" ss -tulpn | grep ":${port} " return 1 fi # 方法3: lsof if lsof -i :${port} 2>/dev/null | grep -q "LISTEN"; then echo "lsof 发现端口 $port 被占用" lsof -i :${port} return 1 fi # 方法4: 检查 Docker 容器映射 if docker ps --format "table {{.Names}}\t{{.Ports}}" 2>/dev/null | grep -q ":${port}->"; then echo "Docker 容器正在使用端口 $port" docker ps --format "table {{.Names}}\t{{.Ports}}" | grep ":${port}->" return 1 fi echo "端口 $port 可用" return 0 } # 函数:使用备用端口部署 deploy_with_alternate_ports() { local http_port="8080" local admin_port="8081" local https_port="8443" echo "使用备用端口部署: HTTP=$http_port, 管理界面=$admin_port, HTTPS=$https_port" # 创建配置 cat > "$COMPOSE_FILE" << EOF # Nginx Proxy Manager 配置(备用端口) services: app: image: 'docker.io/jc21/nginx-proxy-manager:latest' container_name: nginx-proxy-manager restart: unless-stopped ports: - '${http_port}:80' - '${admin_port}:81' - '${https_port}:443' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt environment: - DISABLE_IPV6=false EOF deploy_service $http_port $admin_port $https_port } # 函数:部署服务 deploy_service() { local http_port=$1 local admin_port=$2 local https_port=$3 # 切换到脚本目录 cd "$SCRIPT_DIR" || exit 1 # 检查 Docker 是否运行 if ! systemctl is-active --quiet docker; then echo "启动 Docker 服务..." systemctl start docker sleep 5 fi # 部署服务 echo "启动 Nginx Proxy Manager..." docker compose -p nginx -f "$COMPOSE_FILE" up -d if [ $? -eq 0 ]; then echo "等待服务启动..." sleep 10 SERVER_IP=$(hostname -I | awk '{print $1}') echo "==================================================" echo "✅ Nginx Proxy Manager 部署成功!" echo "管理界面: http://${SERVER_IP}:${admin_port}" echo "HTTP 端口: ${http_port}" echo "HTTPS 端口: ${https_port}" echo "初始账号: admin@example.com" echo "初始密码: changeme" echo "==================================================" else echo "❌ 容器启动失败" echo "检查 Docker 日志:docker logs nginx-proxy-manager" return 1 fi } # 主程序 echo "创建必要的目录..." mkdir -p "$DATA_DIR" mkdir -p "$SCRIPT_DIR" # 显示当前状态 echo "=== 系统状态检查 ===" check_port_advanced 80 check_port_advanced 81 check_port_advanced 443 echo "" echo "=== Docker 状态 ===" docker ps -a | grep nginx || echo "未发现 nginx 相关容器" echo "" echo "请选择部署方案:" echo "1) 彻底清理后使用默认端口重试" echo "2) 直接使用备用端口 (8080, 8081, 8443) - 推荐" echo "3) 手动指定端口" echo "4) 退出" read -p "请输入选择 (1-4): " choice case $choice in 1) echo "执行彻底清理并使用默认端口..." cleanup_docker sleep 3 # 使用默认端口 cat > "$COMPOSE_FILE" << EOF services: app: image: 'docker.io/jc21/nginx-proxy-manager:latest' container_name: nginx-proxy-manager restart: unless-stopped ports: - '80:80' - '81:81' - '443:443' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt EOF deploy_service 80 81 443 ;; 2) cleanup_docker deploy_with_alternate_ports ;; 3) echo "请手动指定端口:" read -p "HTTP 端口 (推荐 8080): " custom_http read -p "管理界面端口 (推荐 8081): " custom_admin read -p "HTTPS 端口 (推荐 8443): " custom_https HTTP_PORT=${custom_http:-8080} ADMIN_PORT=${custom_admin:-8081} HTTPS_PORT=${custom_https:-8443} cleanup_docker cat > "$COMPOSE_FILE" << EOF services: app: image: 'docker.io/jc21/nginx-proxy-manager:latest' container_name: nginx-proxy-manager restart: unless-stopped ports: - '${HTTP_PORT}:80' - '${ADMIN_PORT}:81' - '${HTTPS_PORT}:443' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt EOF deploy_service $HTTP_PORT $ADMIN_PORT $HTTPS_PORT ;; 4) echo "退出脚本" exit 0 ;; *) echo "无效选择,使用备用端口" cleanup_docker deploy_with_alternate_ports ;; esac