#!/bin/bash set -euo pipefail # ================================================== # Nginx Proxy Manager 一键安装脚本 # 版本: 1.0 # 描述: 自动部署 Nginx Proxy Manager 反向代理管理工具 # ================================================== # 脚本配置 APP_NAME="nginx-proxy-manager" SCRIPT_NAME="deploy_nginx_proxy_manager.sh" WORK_DIR="/data" # 颜色定义 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}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 错误处理函数 error_exit() { log_error "$1" exit 1 } # 清理函数 cleanup() { log_info "正在清理临时资源..." # 可以在这里添加清理代码 } # 信号处理 trap cleanup EXIT INT TERM # ================================================== # 环境检查 # ================================================== log_info "开始检查运行环境..." # 检查是否为 root 用户 if [[ $EUID -eq 0 ]]; then log_warning "建议使用非 root 用户执行此脚本,但将继续执行..." fi # 检查 Docker 是否安装 if ! command -v docker &> /dev/null; then error_exit "Docker 未安装,请先安装 Docker" fi # 检查 Docker 服务状态 if ! systemctl is-active --quiet docker && ! systemctl is-active --quiet docker.service; then log_info "尝试启动 Docker 服务..." if ! sudo systemctl start docker 2>/dev/null; then error_exit "Docker 服务未运行且无法启动" fi fi # 测试 Docker 是否正常工作 if ! docker info &> /dev/null; then error_exit "Docker 无法正常工作,请检查 Docker 服务状态" fi log_success "环境检查通过" # ================================================== # 目录准备 # ================================================== log_info "正在准备工作目录..." # 创建并切换到工作目录 if [[ ! -d "$WORK_DIR" ]]; then log_info "创建工作目录: $WORK_DIR" if ! sudo mkdir -p "$WORK_DIR" 2>/dev/null && ! mkdir -p "$WORK_DIR"; then error_exit "无法创建目录 $WORK_DIR,请检查权限" fi fi # 进入工作目录 cd "$WORK_DIR" || error_exit "无法进入目录 $WORK_DIR" # 创建必要的子目录 for dir in nginx-proxy-manager/data nginx-proxy-manager/letsencrypt; do if [[ ! -d "$dir" ]]; then log_info "创建目录: $WORK_DIR/$dir" mkdir -p "$dir" || error_exit "无法创建目录 $dir" fi done log_success "目录准备完成" # ================================================== # 停止并删除现有容器(如果存在) # ================================================== log_info "检查现有容器..." if docker ps -a --format "table {{.Names}}" | grep -q "^${APP_NAME}$"; then log_info "发现已存在的容器,正在停止并删除..." # 停止容器 if docker ps --format "table {{.Names}}" | grep -q "^${APP_NAME}$"; then docker stop "$APP_NAME" || log_warning "停止容器失败,但将继续执行" sleep 5 fi # 删除容器 docker rm "$APP_NAME" || error_exit "删除旧容器失败" log_success "旧容器清理完成" fi # ================================================== # 拉取 Docker 镜像 # ================================================== log_info "正在拉取 Nginx Proxy Manager 镜像..." # 设置重试机制 MAX_RETRIES=3 RETRY_COUNT=0 while [[ $RETRY_COUNT -lt $MAX_RETRIES ]]; do if docker pull docker.io/jc21/nginx-proxy-manager:latest; then log_success "镜像拉取成功" break else RETRY_COUNT=$((RETRY_COUNT + 1)) if [[ $RETRY_COUNT -eq $MAX_RETRIES ]]; then error_exit "镜像拉取失败,已达到最大重试次数" else log_warning "镜像拉取失败,第 $RETRY_COUNT 次重试..." sleep 10 fi fi done # ================================================== # 部署容器 # ================================================== log_info "正在启动 Nginx Proxy Manager 容器..." DOCKER_RUN_CMD="docker run -d \ --name $APP_NAME \ --restart=unless-stopped \ -p 80:80 \ -p 81:81 \ -p 443:443 \ -v $WORK_DIR/nginx-proxy-manager/data:/data \ -v $WORK_DIR/nginx-proxy-manager/letsencrypt:/etc/letsencrypt \ docker.io/jc21/nginx-proxy-manager:latest" log_info "执行命令: $DOCKER_RUN_CMD" if ! eval "$DOCKER_RUN_CMD"; then error_exit "容器启动失败" fi log_success "容器启动命令执行成功" # ================================================== # 等待并验证服务状态 # ================================================== log_info "等待服务启动..." sleep 10 # 检查容器状态 if ! docker ps --format "table {{.Names}}\t{{.Status}}" | grep -q "$APP_NAME"; then error_exit "容器未运行,请检查日志: docker logs $APP_NAME" fi CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' "$APP_NAME" 2>/dev/null || echo "unknown") if [[ "$CONTAINER_STATUS" != "running" ]]; then error_exit "容器状态异常: $CONTAINER_STATUS,请检查日志: docker logs $APP_NAME" fi # 检查服务端口 PORTS=(80 81 443) for port in "${PORTS[@]}"; do if ! ss -tln | grep -q ":$port "; then log_warning "端口 $port 未监听,服务可能仍在启动中" fi done log_success "Nginx Proxy Manager 部署完成!" # ================================================== # 显示部署信息 # ================================================== echo log_success "🎉 Nginx Proxy Manager 部署成功!" echo echo "═══════════════════════════════════════════════════════════════" echo "访问地址: http://$(hostname -I | awk '{print $1}'):81" echo "默认邮箱: admin@example.com" echo "默认密码: changeme" echo echo "重要提示:" echo "1. 首次登录后请立即修改默认密码" echo "2. 管理界面运行在 81 端口" echo "3. 数据存储位置: $WORK_DIR/nginx-proxy-manager/" echo "4. 查看容器日志: docker logs $APP_NAME" echo "5. 停止服务: docker stop $APP_NAME" echo "6. 启动服务: docker start $APP_NAME" echo "═══════════════════════════════════════════════════════════════" echo # 显示容器状态 log_info "当前容器状态:" docker ps --filter "name=$APP_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" # 显示数据目录结构 log_info "数据目录结构:" find "$WORK_DIR/nginx-proxy-manager" -type f -name "*" | head -10