139 lines
6.9 KiB
Bash
139 lines
6.9 KiB
Bash
#!/usr/bin/env bash
|
||
# ============================================================
|
||
# 捕鱼/棋牌平台 - 一键部署脚本(Linux 服务器 + Docker)
|
||
#
|
||
# 用法:
|
||
# bash deploy/deploy.sh
|
||
# PUBLIC_HOST=1.2.3.4:8001 bash deploy/deploy.sh # 指定客户端访问地址(含端口)
|
||
#
|
||
# 前置要求:
|
||
# - Linux 服务器已安装 Docker(含 docker compose v2 插件)
|
||
# - 服务器可访问 nuget.org 与 docker hub(首次编译需要联网拉取依赖)
|
||
# - 建议预留 5GB 以上磁盘空间
|
||
#
|
||
# 脚本做的事:
|
||
# 1. 在 dotnet/sdk:8.0 容器内编译发布 7 个 Host(服务器无需安装 .NET SDK)
|
||
# 2. 覆盖各服务的部署版 Config/system.json,并把网关下游地址改写为容器名
|
||
# 3. 构建 7 个镜像(0524gateway / 0524admin / 0524user / 0524customer /
|
||
# 0524chess / 0524fishroom / 0524fishgame)
|
||
# 4. 启动全部容器(4 个中间件 + 7 个应用)并做健康检查
|
||
#
|
||
# 常用运维命令:
|
||
# 查看状态:docker compose -f deploy/docker-compose.yml ps
|
||
# 查看日志:docker compose -f deploy/docker-compose.yml logs -f <服务名>
|
||
# 停止全部:docker compose -f deploy/docker-compose.yml down
|
||
# ============================================================
|
||
set -euo pipefail
|
||
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
DEPLOY_DIR="$ROOT/deploy"
|
||
PUB_DIR="$DEPLOY_DIR/publish"
|
||
COMPOSE_FILE="$DEPLOY_DIR/docker-compose.yml"
|
||
SDK_IMAGE="mcr.microsoft.com/dotnet/sdk:8.0"
|
||
NUGET_VOLUME="buyu-nuget"
|
||
|
||
log() { echo -e "\033[1;32m[部署]\033[0m $*"; }
|
||
warn() { echo -e "\033[1;33m[警告]\033[0m $*"; }
|
||
|
||
# 客户端访问地址(用于捕鱼对局层返回给客户端的 WebSocket 地址);不传则自动取本机第一个 IP
|
||
if [ -z "${PUBLIC_HOST:-}" ]; then
|
||
SERVER_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||
PUBLIC_HOST="${SERVER_IP:-localhost}:8001"
|
||
fi
|
||
|
||
# ---------- 0. 环境检查 ----------
|
||
command -v docker >/dev/null 2>&1 || { echo "未检测到 docker,请先安装 Docker"; exit 1; }
|
||
docker compose version >/dev/null 2>&1 || { echo "未检测到 docker compose v2,请安装 docker-compose-plugin"; exit 1; }
|
||
[ -f "$COMPOSE_FILE" ] || { echo "缺少编排文件:$COMPOSE_FILE"; exit 1; }
|
||
|
||
# ---------- 1. 容器内编译发布 + 准备部署配置 ----------
|
||
log "1/4 编译发布(在容器内进行,首次需要拉取 SDK 镜像与 NuGet 包,耗时较长)..."
|
||
docker run --rm \
|
||
-v "$ROOT":/src \
|
||
-w /src \
|
||
-v "$NUGET_VOLUME":/root/.nuget/packages \
|
||
-e PUBLIC_HOST="$PUBLIC_HOST" \
|
||
"$SDK_IMAGE" bash -c '
|
||
set -e
|
||
rm -rf /src/deploy/publish
|
||
mkdir -p /src/deploy/publish
|
||
dotnet publish Gateway/Gateway.csproj -c Release -o /src/deploy/publish/gateway --nologo
|
||
dotnet publish AdminSrc/AdminHost/AdminHost.csproj -c Release -o /src/deploy/publish/admin --nologo
|
||
dotnet publish UserSrc/UserHost/UserHost.csproj -c Release -o /src/deploy/publish/user --nologo
|
||
dotnet publish CustomerSrc/CustomerHost/CustomerHost.csproj -c Release -o /src/deploy/publish/customer --nologo
|
||
dotnet publish ChessGameHost/ChessGameHost.csproj -c Release -o /src/deploy/publish/chess --nologo
|
||
dotnet publish FishGameSrc/FishRoomHost/FishRoomHost.csproj -c Release -o /src/deploy/publish/fishroom --nologo
|
||
dotnet publish FishGameSrc/FishGameHost/FishGameHost.csproj -c Release -o /src/deploy/publish/fishgame --nologo
|
||
|
||
# 覆盖部署版配置(各 Host 的 Config/system.json 默认不会随发布输出,必须显式拷贝)
|
||
for name in gateway admin user customer chess fishroom fishgame; do
|
||
mkdir -p /src/deploy/publish/$name/Config
|
||
cp /src/deploy/config/$name/system.json /src/deploy/publish/$name/Config/system.json
|
||
cp /src/nlog.config /src/deploy/publish/$name/nlog.config
|
||
done
|
||
|
||
# 捕鱼对局层:替换客户端要访问的 WebSocket 地址(经网关 /gamehub 路由)
|
||
sed -i "s|__PUBLIC_HOST__|$PUBLIC_HOST|g" /src/deploy/publish/fishgame/Config/system.json
|
||
|
||
# 网关:ocelot 下游地址由 localhost:524x 改写为「容器名:80」(容器间互访)
|
||
OCELOT=/src/deploy/publish/gateway/ocelot.json
|
||
sed -i \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5241 }|{ \"Host\": \"0524admin\", \"Port\": 80 }|" \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5245 }|{ \"Host\": \"0524user\", \"Port\": 80 }|" \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5247 }|{ \"Host\": \"0524customer\", \"Port\": 80 }|" \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5242 }|{ \"Host\": \"0524chess\", \"Port\": 80 }|" \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5244 }|{ \"Host\": \"0524fishroom\", \"Port\": 80 }|" \
|
||
-e "s|{ \"Host\": \"localhost\", \"Port\": 5248 }|{ \"Host\": \"0524fishgame\", \"Port\": 80 }|" \
|
||
"$OCELOT"
|
||
'
|
||
|
||
# ---------- 2. 构建 7 个应用镜像 ----------
|
||
log "2/4 构建镜像..."
|
||
build_image() { # 镜像名 入口dll 发布目录名
|
||
docker build -f "$DEPLOY_DIR/Dockerfile" --build-arg "APP_DLL=$2" -t "$1" "$PUB_DIR/$3"
|
||
echo " ✔ $1"
|
||
}
|
||
build_image 0524gateway Gateway.dll gateway
|
||
build_image 0524admin AdminHost.dll admin
|
||
build_image 0524user UserHost.dll user
|
||
build_image 0524customer CustomerHost.dll customer
|
||
build_image 0524chess ChessGameHost.dll chess
|
||
build_image 0524fishroom FishRoomHost.dll fishroom
|
||
build_image 0524fishgame FishGameHost.dll fishgame
|
||
|
||
# ---------- 3. 启动全部容器 ----------
|
||
log "3/4 启动容器(4 个中间件 + 7 个应用)..."
|
||
mkdir -p "$DEPLOY_DIR"/logs/{gateway,admin,user,customer,chess,fishroom,fishgame}
|
||
mkdir -p "$DEPLOY_DIR"/uploads/{admin,user,customer}
|
||
docker compose -f "$COMPOSE_FILE" up -d
|
||
|
||
# ---------- 4. 健康检查 ----------
|
||
log "4/4 等待服务就绪..."
|
||
sleep 8
|
||
check() { # 地址 服务名
|
||
for _ in $(seq 1 15); do
|
||
if curl -fsS -o /dev/null --max-time 2 "$1"; then
|
||
echo " ✔ $2 $1"
|
||
return 0
|
||
fi
|
||
sleep 2
|
||
done
|
||
warn "$2 未就绪:$1(排查:docker compose -f deploy/docker-compose.yml logs $2)"
|
||
}
|
||
check "http://localhost:8001/health" gateway
|
||
check "http://localhost:5241/health" admin
|
||
check "http://localhost:5245/health" user
|
||
check "http://localhost:5247/health" customer
|
||
check "http://localhost:5242/health" chess
|
||
check "http://localhost:5244/health" fishroom
|
||
check "http://localhost:5248/health" fishgame
|
||
|
||
echo ""
|
||
log "部署完成"
|
||
echo "----------------------------------------------------------"
|
||
echo " 统一入口(网关) : http://$PUBLIC_HOST"
|
||
echo " RabbitMQ 控制台 : http://<服务器IP>:15672(admin / 123456)"
|
||
echo " 日志目录 : deploy/logs/<服务名>/日期/"
|
||
echo " 上传文件目录 : deploy/uploads/<服务名>/"
|
||
echo " 停止全部 : docker compose -f deploy/docker-compose.yml down"
|
||
echo "----------------------------------------------------------" |