129 lines
3.7 KiB
Bash
129 lines
3.7 KiB
Bash
#!/bin/bash
|
||||
|
|
# ============================================================
|
|||
|
|
# 0524 平台:按现有约定替换/回滚单个(或多个)服务容器
|
|||
|
|
# 位置:服务器 /mnt/web/0524-replace.sh
|
|||
|
|
#
|
|||
|
|
# 用法:
|
|||
|
|
# bash 0524-replace.sh admin # 用 0524admin:latest 重建 admin
|
|||
|
|
# bash 0524-replace.sh fishgame admin # 一次替换多个
|
|||
|
|
# TAG=dual-20261008 bash 0524-replace.sh admin # 回滚 admin 到旧镜像
|
|||
|
|
#
|
|||
|
|
# 约定(与线上既有部署保持一致):
|
|||
|
|
# - 网络 webapi_backend
|
|||
|
|
# - 端口只绑 127.0.0.1
|
|||
|
|
# - 配置挂载 /mnt/web/config -> /app/Config(全服务共用)
|
|||
|
|
# - 日志挂载 /mnt/web/logs -> /app/logs
|
|||
|
|
# - ASPNETCORE_URLS 按各服务内部端口
|
|||
|
|
# ============================================================
|
|||
|
|
set -u
|
|||
|
|
|
|||
|
|
NET=webapi_backend
|
|||
|
|
CFG=/mnt/web/config
|
|||
|
|
LOGS=/mnt/web/logs
|
|||
|
|
UPLOADS=/mnt/web/uploads
|
|||
|
|
TAG="${TAG:-latest}"
|
|||
|
|
ROLLBACK_TAG="${ROLLBACK_TAG:-dual-20261008}"
|
|||
|
|
|
|||
|
|
ALL="gateway admin user customer chess fishroom fishgame"
|
|||
|
|
|
|||
|
|
# 容器内部监听端口
|
|||
|
|
internal_port() {
|
|||
|
|
case "$1" in
|
|||
|
|
gateway) echo 8001 ;;
|
|||
|
|
admin) echo 5241 ;;
|
|||
|
|
user) echo 5245 ;;
|
|||
|
|
customer) echo 5247 ;;
|
|||
|
|
chess) echo 5242 ;;
|
|||
|
|
fishroom) echo 5244 ;;
|
|||
|
|
fishgame) echo 8001 ;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
# 宿主机映射端口(只绑 127.0.0.1)
|
|||
|
|
host_port() {
|
|||
|
|
case "$1" in
|
|||
|
|
gateway) echo 8001 ;;
|
|||
|
|
admin) echo 5241 ;;
|
|||
|
|
user) echo 5245 ;;
|
|||
|
|
customer) echo 5247 ;;
|
|||
|
|
chess) echo 5242 ;;
|
|||
|
|
fishroom) echo 5244 ;;
|
|||
|
|
fishgame) echo 5248 ;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
# 额外的 -v/-e 参数
|
|||
|
|
extra_args() {
|
|||
|
|
case "$1" in
|
|||
|
|
gateway) echo "-v $CFG/ocelot.json:/app/ocelot.json -v $UPLOADS:/app/uploads" ;;
|
|||
|
|
admin) echo "-v $UPLOADS:/app/wwwroot/uploads" ;;
|
|||
|
|
customer) echo "-v $UPLOADS:/app/wwwroot/uploads" ;;
|
|||
|
|
*) echo "" ;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
# INSTANCE_ID(日志文件名里用于区分实例)
|
|||
|
|
instance_id() {
|
|||
|
|
case "$1" in
|
|||
|
|
gateway) echo "" ;;
|
|||
|
|
fishgame) echo "1" ;;
|
|||
|
|
*) echo "Container_Port_$(host_port "$1")" ;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
run_container() {
|
|||
|
|
local svc=$1 tag=$2
|
|||
|
|
local ip hp inst extra
|
|||
|
|
ip=$(internal_port "$svc"); hp=$(host_port "$svc"); inst=$(instance_id "$svc"); extra=$(extra_args "$svc")
|
|||
|
|
|
|||
|
|
docker rm -f "0524$svc" >/dev/null 2>&1
|
|||
|
|
local envar="ASPNETCORE_URLS=http://+:$ip"
|
|||
|
|
[ -n "$inst" ] && envar="$envar -e INSTANCE_ID=$inst"
|
|||
|
|
|
|||
|
|
# shellcheck disable=SC2086
|
|||
|
|
docker run -d --name "0524$svc" --restart always --network "$NET" \
|
|||
|
|
-e $envar $extra \
|
|||
|
|
-p "127.0.0.1:$hp:$ip" \
|
|||
|
|
-v "$CFG:/app/Config" -v "$LOGS:/app/logs" -v "$CFG/nlog.config:/app/nlog.config" \
|
|||
|
|
"0524$svc:$tag" >/dev/null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
health() {
|
|||
|
|
local hp; hp=$(host_port "$1")
|
|||
|
|
for _ in $(seq 1 15); do
|
|||
|
|
local c; c=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:$hp/health")
|
|||
|
|
[ "$c" = "200" ] && return 0
|
|||
|
|
sleep 2
|
|||
|
|
done
|
|||
|
|
return 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
replace_one() {
|
|||
|
|
local svc=$1
|
|||
|
|
echo "=== 替换 $svc (0524$svc:$TAG)==="
|
|||
|
|
run_container "$svc" "$TAG"
|
|||
|
|
if health "$svc"; then
|
|||
|
|
echo " ✔ $svc 健康检查通过"
|
|||
|
|
else
|
|||
|
|
echo " ✘ $svc 未通过,输出日志并回滚到 $ROLLBACK_TAG"
|
|||
|
|
docker logs --tail 40 "0524$svc" 2>&1 | tail -20
|
|||
|
|
run_container "$svc" "$ROLLBACK_TAG"
|
|||
|
|
health "$svc" && echo " ↩ 已回滚,$svc 恢复正常" || echo " !! 回滚后仍不健康,请人工介入"
|
|||
|
|
return 1
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if [ $# -eq 0 ]; then
|
|||
|
|
echo "用法: bash 0524-replace.sh <服务...> (可选服务: $ALL)"
|
|||
|
|
echo " TAG=dual-20261008 bash 0524-replace.sh <服务...> # 回滚"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
for svc in "$@"; do
|
|||
|
|
case " $ALL " in
|
|||
|
|
*" $svc "*) replace_one "$svc" ;;
|
|||
|
|
*) echo "未知服务: $svc(可选: $ALL)" ;;
|
|||
|
|
esac
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo "=== 当前业务容器 ==="
|
|||
|
|
docker ps --format '{{.Names}} => {{.Image}} => {{.Status}}' | grep 0524
|