Files
kra-new/deploy/deploy.sh
T
2026-09-23 18:20:17 +08:00

148 lines
6.0 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ============================================================
# live.fuhua91.com 一键部署脚本
#
# 用法:
# ./deploy.sh 拉取 latest 最新镜像并重启
# ./deploy.sh v1.0.0 部署指定版本
#
# 建议: 放到 /root/deploy.sh,执行 chmod 700 /root/deploy.sh
# 依赖: 服务器已安装 docker,且能访问 harbor.fuhua91.com
# ============================================================
set -euo pipefail
# ---------- 可按需调整的参数 ----------
REGISTRY="harbor.fuhua91.com"
PROJECT="live"
# Harbor 机器人账号(密码只通过 HARBOR_PASSWORD 环境变量提供)
HARBOR_USER_DEFAULT='robot$live+live'
BASE_DIR="/www/wwwroot/live.fuhua91.com"
CONFIG_DIR="$BASE_DIR/config" # 后端配置目录 -> 容器内 /data/conf
LOG_DIR="$BASE_DIR/log" # 后端日志目录 -> 容器内 /app/logs
UPLOADS_DIR="$BASE_DIR/uploads" # 上传文件目录 -> 容器内 /app/uploads
FRONTEND_PORT=9501 # admin 管理后台 nginx 容器
BACKEND_PORT=9502 # 后端 API/WebSocket 容器
LIVEWEB_PORT=9503 # live 用户端(PC 直播页) nginx 容器
LIVE_UDP_PORT="${KRA_LIVE_UDP_PORT:-9504}" # WebRTC 音视频固定 UDP 端口(与 9501-9503 顺延配套)
LIVE_PUBLIC_IP="${KRA_LIVE_PUBLIC_IP:-}" # 留空时从站点域名解析
LIVE_HOST="${KRA_LIVE_HOST:-live.yuzou99.com}"
NETWORK="live-net"
BACKEND_NAME="live-backend"
FRONTEND_NAME="live-frontend"
LIVEWEB_NAME="live-web"
# --------------------------------------
TAG="${1:-latest}"
BACKEND_IMAGE="$REGISTRY/$PROJECT/backend:$TAG"
FRONTEND_IMAGE="$REGISTRY/$PROJECT/frontend:$TAG"
LIVEWEB_IMAGE="$REGISTRY/$PROJECT/live-web:$TAG"
# 基础环境检查(Docker / MySQL / Redis 由 server-init.sh 负责)
if ! command -v docker >/dev/null 2>&1; then
echo "错误: 服务器未安装 Docker,请先执行基础环境初始化脚本:"
echo " bash server-init.sh"
exit 1
fi
if ! docker ps --format '{{.Names}}' | grep -qx 'live-mysql' || \
! docker ps --format '{{.Names}}' | grep -qx 'live-redis'; then
echo "警告: live-mysql / live-redis 容器未在运行,后端将连不上数据库。"
echo " 请先执行基础环境初始化脚本: bash server-init.sh"
fi
echo "==> 部署版本: $TAG"
# 1. 准备挂载目录
mkdir -p "$CONFIG_DIR" "$LOG_DIR" "$UPLOADS_DIR"
# 2. 首次运行检查配置文件
if [ ! -f "$CONFIG_DIR/config.yaml" ]; then
echo "错误: 缺少 $CONFIG_DIR/config.yaml"
echo "请先将项目 configs/config.yaml 复制到该路径,"
echo "并修改其中的 MySQL / Redis 等连接信息后重新执行本脚本。"
exit 1
fi
if [ -z "$LIVE_PUBLIC_IP" ]; then
# 1) 域名解析,过滤内网/回环地址(服务器 /etc/hosts 可能指向内网)
# getent 域名不存在时返回非零且无输出,须吞掉退出码,否则 pipefail+set -e 会静默退出
LIVE_PUBLIC_IP="$( { timeout 10 getent ahostsv4 "$LIVE_HOST" 2>/dev/null || true; } | awk '{print $1}' | grep -E '^[0-9]+(\.[0-9]+){3}$' \
| grep -vE '^(10\.|127\.|169\.254\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)' | head -n1 || true)"
fi
if [ -z "$LIVE_PUBLIC_IP" ]; then
# 2) 域名取不到公网 IP 时,回退查询公网出口 IP(云主机 EIP 1:1 NAT 场景一致)
LIVE_PUBLIC_IP="$(curl -4 -fsS --max-time 5 https://api.ipify.org 2>/dev/null \
|| curl -4 -fsS --max-time 5 https://ifconfig.me 2>/dev/null || true)"
fi
if ! printf '%s' "$LIVE_PUBLIC_IP" | grep -Eq '^[0-9]+(\.[0-9]+){3}$'; then
echo "错误: 无法确定直播服务公网 IPv4,请通过 KRA_LIVE_PUBLIC_IP 显式设置"
exit 1
fi
echo "==> WebRTC 媒体地址: $LIVE_PUBLIC_IP:$LIVE_UDP_PORT/udp"
# 3. 登录 Harbor;未传密码时复用服务器现有的 Docker 登录态
HARBOR_USER="${HARBOR_USER:-$HARBOR_USER_DEFAULT}"
HARBOR_LOGGED_IN=false
if [ -n "${HARBOR_PASSWORD:-}" ]; then
echo "==> 登录 $REGISTRY"
echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" --username "$HARBOR_USER" --password-stdin >/dev/null
HARBOR_LOGGED_IN=true
else
echo "==> 未提供 HARBOR_PASSWORD,复用服务器现有 Docker 登录态"
fi
# 4. 拉取最新镜像
echo "==> 拉取镜像"
docker pull "$BACKEND_IMAGE"
docker pull "$FRONTEND_IMAGE"
docker pull "$LIVEWEB_IMAGE"
# 5. 重建容器
echo "==> 重启容器"
docker network create "$NETWORK" >/dev/null 2>&1 || true
docker rm -f "$BACKEND_NAME" "$FRONTEND_NAME" "$LIVEWEB_NAME" 2>/dev/null || true
# 容器内进程以 uid 1000 (kra) 运行,日志/上传目录需要写权限
chown -R 1000:1000 "$LOG_DIR" "$UPLOADS_DIR" 2>/dev/null || \
chmod -R 777 "$LOG_DIR" "$UPLOADS_DIR"
# 后端: 配置 /data/conf,日志 /app/logs,上传 /app/uploads
docker run -d --name "$BACKEND_NAME" \
--restart always \
--network "$NETWORK" \
-p "$BACKEND_PORT:8000" \
-p "$LIVE_UDP_PORT:$LIVE_UDP_PORT/udp" \
-e KRA_LIVE_PUBLIC_IP="$LIVE_PUBLIC_IP" \
-e KRA_LIVE_UDP_PORT="$LIVE_UDP_PORT" \
-v "$CONFIG_DIR:/data/conf" \
-v "$LOG_DIR:/app/logs" \
-v "$UPLOADS_DIR:/app/uploads" \
"$BACKEND_IMAGE"
# 前端: nginx 静态站点,容器内已配置 /api -> live-backend:8000
docker run -d --name "$FRONTEND_NAME" \
--restart always \
--network "$NETWORK" \
-p "$FRONTEND_PORT:80" \
"$FRONTEND_IMAGE"
# live 用户端(PC 直播页): nginx 静态站点,主域名 / 反代到该容器
docker run -d --name "$LIVEWEB_NAME" \
--restart always \
--network "$NETWORK" \
-p "$LIVEWEB_PORT:80" \
"$LIVEWEB_IMAGE"
if [ "$HARBOR_LOGGED_IN" = true ]; then
docker logout "$REGISTRY" >/dev/null 2>&1 || true
fi
echo "==> 部署完成"
docker ps --filter "name=$BACKEND_NAME" --filter "name=$FRONTEND_NAME" --filter "name=$LIVEWEB_NAME"
echo ""
echo "admin 前端容器: http://<服务器IP>:$FRONTEND_PORT"
echo "后端容器: http://<服务器IP>:$BACKEND_PORT"
echo "live 前端容器: http://<服务器IP>:$LIVEWEB_PORT"
echo "提示: 网站正常访问走宝塔 nginx 反代(80/443),9501/9502 为直连调试端口,记得放行防火墙。"