Files
aiot-platform-cloud/scripts/deploy.sh

231 lines
5.9 KiB
Bash
Raw Normal View History

#!/bin/bash
# ============================================
# AIOT Platform - 部署脚本
# 滚动更新部署,支持健康检查和自动回滚
# ============================================
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 配置
COMPOSE_FILE="docker-compose.core.yml"
REGISTRY="172.17.16.7:5000"
HEALTH_CHECK_TIMEOUT=120
HEALTH_CHECK_INTERVAL=5
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查服务健康状态
check_health() {
local service=$1
local container_name="aiot-${service}"
local elapsed=0
log_info "等待 ${service} 健康检查..."
while [ $elapsed -lt $HEALTH_CHECK_TIMEOUT ]; do
if docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null | grep -q "healthy"; then
log_info "${service} 健康检查通过 ✓"
return 0
fi
sleep $HEALTH_CHECK_INTERVAL
elapsed=$((elapsed + HEALTH_CHECK_INTERVAL))
echo -n "."
done
echo ""
log_error "${service} 健康检查超时 ✗"
return 1
}
# 备份当前运行的镜像标签
backup_current_tags() {
log_info "备份当前镜像标签..."
docker-compose -f "$COMPOSE_FILE" config --services | while read service; do
local current_image=$(docker inspect "aiot-${service}" --format='{{.Config.Image}}' 2>/dev/null || echo "")
if [ -n "$current_image" ]; then
echo "${service}=${current_image}" >> .deploy_backup
fi
done
log_info "备份完成: .deploy_backup"
}
# 部署单个服务
deploy_service() {
local service=$1
log_info "========================================="
log_info "部署服务: ${service}"
log_info "========================================="
# 拉取最新镜像
log_info "拉取最新镜像..."
if ! docker-compose -f "$COMPOSE_FILE" pull "$service"; then
log_error "拉取镜像失败"
return 1
fi
# 启动新容器
log_info "启动新容器..."
if ! docker-compose -f "$COMPOSE_FILE" up -d "$service"; then
log_error "启动容器失败"
return 1
fi
# 健康检查
if ! check_health "$service"; then
log_error "${service} 部署失败,准备回滚..."
return 1
fi
log_info "${service} 部署成功 ✓"
return 0
}
# 回滚服务
rollback_service() {
local service=$1
log_warn "回滚服务: ${service}"
# 从备份文件读取之前的镜像
if [ -f .deploy_backup ]; then
local backup_image=$(grep "^${service}=" .deploy_backup | cut -d'=' -f2)
if [ -n "$backup_image" ]; then
log_info "回滚到镜像: ${backup_image}"
docker-compose -f "$COMPOSE_FILE" stop "$service"
docker tag "$backup_image" "${REGISTRY}/${service}:latest"
docker-compose -f "$COMPOSE_FILE" up -d "$service"
if check_health "$service"; then
log_info "${service} 回滚成功 ✓"
return 0
fi
fi
fi
log_error "${service} 回滚失败 ✗"
return 1
}
# 主部署流程
main() {
log_info "========================================="
log_info "AIOT Platform 部署开始"
log_info "========================================="
# 检查 .env 文件
if [ ! -f .env ]; then
log_error ".env 文件不存在,请先复制 .env.example 并配置"
exit 1
fi
# 加载环境变量
source .env
# 备份当前状态
rm -f .deploy_backup
backup_current_tags
# 获取要部署的服务列表
local services_to_deploy=""
if [ $# -eq 0 ]; then
# 部署所有核心服务
services_to_deploy=$(docker-compose -f "$COMPOSE_FILE" config --services | grep -v -E "mysql|redis|nacos|rocketmq")
else
# 部署指定服务
services_to_deploy="$@"
fi
log_info "待部署服务: ${services_to_deploy}"
# 部署服务
local failed_services=""
for service in $services_to_deploy; do
if ! deploy_service "$service"; then
failed_services="${failed_services} ${service}"
# 尝试回滚
rollback_service "$service"
fi
done
# 清理旧镜像
log_info "清理悬空镜像..."
docker image prune -f
# 部署结果
echo ""
log_info "========================================="
if [ -z "$failed_services" ]; then
log_info "所有服务部署成功 ✓"
log_info "========================================="
rm -f .deploy_backup
exit 0
else
log_error "以下服务部署失败: ${failed_services}"
log_error "========================================="
exit 1
fi
}
# 显示帮助
show_help() {
cat << EOF
用法: $0 [服务名...]
部署 AIOT Platform 服务到生产环境
参数:
无参数 部署所有应用服务
服务名... 部署指定的服务
示例:
$0 # 部署所有服务
$0 viewsh-gateway # 仅部署 gateway
$0 viewsh-module-iot-server viewsh-module-iot-gateway # 部署多个服务
服务列表:
- viewsh-gateway
- viewsh-module-system-server
- viewsh-module-infra-server
- viewsh-module-iot-server
- viewsh-module-iot-gateway
- viewsh-module-ops-server
EOF
}
# 参数处理
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_help
exit 0
fi
# 执行主流程
main "$@"