250 lines
7.7 KiB
Bash
250 lines
7.7 KiB
Bash
#!/bin/bash
|
|
|
|
# =============================================================================
|
|
# Genex Portal - 部署管理脚本
|
|
# =============================================================================
|
|
#
|
|
# Docker 命令:
|
|
# ./deploy.sh build 仅构建 Docker 镜像
|
|
# ./deploy.sh start 构建并启动服务 (默认)
|
|
# ./deploy.sh stop 停止服务
|
|
# ./deploy.sh restart 重启服务
|
|
# ./deploy.sh logs 查看服务日志
|
|
# ./deploy.sh status 查看服务状态
|
|
# ./deploy.sh clean 清理容器和镜像
|
|
#
|
|
# Nginx + SSL 命令 (需要 root 权限):
|
|
# sudo ./deploy.sh nginx install [domain] [email] 安装 Nginx + SSL 证书
|
|
# sudo ./deploy.sh nginx ssl [domain] [email] 仅申请/续期 SSL 证书
|
|
# ./deploy.sh nginx status 查看 Nginx 状态
|
|
# ./deploy.sh nginx reload 重载 Nginx 配置
|
|
#
|
|
# 默认域名: gogenex.com
|
|
# 默认邮箱: admin@gogenex.com
|
|
#
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
PROJECT_NAME="genex-portal"
|
|
IMAGE_NAME="genex-portal"
|
|
CONTAINER_NAME="genex-portal"
|
|
DEFAULT_PORT=3001
|
|
DEFAULT_DOMAIN="gogenex.com"
|
|
DEFAULT_EMAIL="admin@gogenex.com"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
check_docker() {
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker 未安装"
|
|
exit 1
|
|
fi
|
|
if ! docker info &> /dev/null; then
|
|
log_error "Docker 服务未运行"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_docker_compose() {
|
|
if docker compose version &> /dev/null; then
|
|
COMPOSE_CMD="docker compose"
|
|
elif command -v docker-compose &> /dev/null; then
|
|
COMPOSE_CMD="docker-compose"
|
|
else
|
|
log_error "Docker Compose 未安装"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
build() {
|
|
log_info "构建 Docker 镜像..."
|
|
$COMPOSE_CMD build --no-cache
|
|
log_success "镜像构建完成"
|
|
}
|
|
|
|
start() {
|
|
log_info "部署 Genex Portal..."
|
|
PORT=${PORT:-$DEFAULT_PORT}
|
|
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
|
|
log_warn "端口 $PORT 已被占用,停止旧服务..."
|
|
stop
|
|
fi
|
|
$COMPOSE_CMD up -d --build
|
|
log_info "等待服务启动..."
|
|
sleep 5
|
|
if docker ps | grep -q $CONTAINER_NAME; then
|
|
log_success "服务部署成功! http://localhost:$PORT"
|
|
else
|
|
log_error "服务启动失败,查看日志: ./deploy.sh logs"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
stop() {
|
|
log_info "停止服务..."
|
|
$COMPOSE_CMD down
|
|
log_success "服务已停止"
|
|
}
|
|
|
|
restart() { stop; start; }
|
|
|
|
logs() { $COMPOSE_CMD logs -f; }
|
|
|
|
clean() {
|
|
log_info "清理容器和镜像..."
|
|
$COMPOSE_CMD down --rmi local --volumes --remove-orphans
|
|
docker image prune -f
|
|
log_success "清理完成"
|
|
}
|
|
|
|
status() {
|
|
log_info "服务状态:"
|
|
docker ps -a --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
}
|
|
|
|
cmd_nginx_install() {
|
|
local domain="${1:-$DEFAULT_DOMAIN}"
|
|
local email="${2:-$DEFAULT_EMAIL}"
|
|
local conf_file="$SCRIPT_DIR/nginx/${domain}.conf"
|
|
|
|
log_info "为 $domain 安装 Nginx + SSL..."
|
|
|
|
if [ ! -f "$conf_file" ]; then
|
|
log_error "配置文件不存在: $conf_file"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$EUID" -ne 0 ]; then
|
|
log_error "需要 root 权限: sudo ./deploy.sh nginx install $domain $email"
|
|
exit 1
|
|
fi
|
|
|
|
# 安装依赖
|
|
log_info "[1/5] 检查依赖..."
|
|
command -v nginx &> /dev/null || { apt update && apt install -y nginx; systemctl enable nginx; systemctl start nginx; }
|
|
command -v certbot &> /dev/null || apt install -y certbot python3-certbot-nginx
|
|
|
|
# HTTP 临时配置
|
|
log_info "[2/5] 部署 HTTP 临时配置..."
|
|
mkdir -p /var/www/certbot
|
|
cat > /etc/nginx/sites-available/$domain << HTTPEOF
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name $domain www.$domain;
|
|
location /.well-known/acme-challenge/ { root /var/www/certbot; }
|
|
location / {
|
|
proxy_pass http://127.0.0.1:${DEFAULT_PORT};
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
}
|
|
}
|
|
HTTPEOF
|
|
ln -sf /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/
|
|
nginx -t && systemctl reload nginx
|
|
|
|
# SSL 证书
|
|
log_info "[3/5] 申请 SSL 证书..."
|
|
if [ -d "/etc/letsencrypt/live/$domain" ]; then
|
|
log_warn "证书已存在,跳过"
|
|
else
|
|
certbot certonly --webroot --webroot-path=/var/www/certbot \
|
|
--email $email --agree-tos --no-eff-email \
|
|
-d $domain -d www.$domain
|
|
log_success "SSL 证书申请成功!"
|
|
fi
|
|
|
|
# HTTPS 完整配置
|
|
log_info "[4/5] 部署 HTTPS 配置..."
|
|
cp "$conf_file" /etc/nginx/sites-available/$domain
|
|
nginx -t && systemctl reload nginx
|
|
|
|
# 自动续期
|
|
log_info "[5/5] 配置自动续期..."
|
|
if [ ! -f /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh ]; then
|
|
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
|
|
cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'HOOKEOF'
|
|
#!/bin/bash
|
|
systemctl reload nginx
|
|
HOOKEOF
|
|
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
|
|
fi
|
|
|
|
log_success "完成! https://$domain"
|
|
}
|
|
|
|
cmd_nginx_ssl() {
|
|
local domain="${1:-$DEFAULT_DOMAIN}"
|
|
local email="${2:-$DEFAULT_EMAIL}"
|
|
[ "$EUID" -ne 0 ] && { log_error "需要 root 权限"; exit 1; }
|
|
mkdir -p /var/www/certbot
|
|
if [ -d "/etc/letsencrypt/live/$domain" ]; then
|
|
certbot renew --cert-name $domain
|
|
else
|
|
certbot certonly --webroot --webroot-path=/var/www/certbot \
|
|
--email $email --agree-tos --no-eff-email \
|
|
-d $domain -d www.$domain
|
|
fi
|
|
log_success "SSL 证书完成"
|
|
}
|
|
|
|
cmd_nginx_status() {
|
|
systemctl is-active nginx &>/dev/null && echo -e "Nginx: ${GREEN}运行中${NC}" || echo -e "Nginx: ${RED}未运行${NC}"
|
|
command -v certbot &>/dev/null && certbot certificates 2>/dev/null | grep -E "(Certificate Name|Expiry Date|Domains)" | sed 's/^/ /'
|
|
}
|
|
|
|
cmd_nginx_reload() {
|
|
[ "$EUID" -ne 0 ] && { log_error "需要 root 权限"; exit 1; }
|
|
nginx -t && systemctl reload nginx
|
|
log_success "Nginx 已重载"
|
|
}
|
|
|
|
show_help() {
|
|
echo ""
|
|
echo "Genex Portal 部署脚本"
|
|
echo ""
|
|
echo "Docker: build | start | stop | restart | logs | status | clean"
|
|
echo "Nginx: nginx install [domain] [email] | nginx ssl | nginx status | nginx reload"
|
|
echo ""
|
|
echo "默认域名: $DEFAULT_DOMAIN 端口: $DEFAULT_PORT"
|
|
echo ""
|
|
}
|
|
|
|
main() {
|
|
cd "$SCRIPT_DIR"
|
|
case "${1:-start}" in
|
|
build) check_docker; check_docker_compose; build ;;
|
|
start) check_docker; check_docker_compose; start ;;
|
|
stop) check_docker; check_docker_compose; stop ;;
|
|
restart) check_docker; check_docker_compose; restart ;;
|
|
logs) check_docker; check_docker_compose; logs ;;
|
|
status) check_docker; status ;;
|
|
clean) check_docker; check_docker_compose; clean ;;
|
|
nginx)
|
|
case "${2:-install}" in
|
|
install) cmd_nginx_install "$3" "$4" ;;
|
|
ssl) cmd_nginx_ssl "$3" "$4" ;;
|
|
status) cmd_nginx_status ;;
|
|
reload) cmd_nginx_reload ;;
|
|
*) log_error "未知命令: $2"; exit 1 ;;
|
|
esac
|
|
;;
|
|
help|--help|-h) show_help ;;
|
|
*) log_error "未知命令: $1"; show_help; exit 1 ;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|