feat(scripts): add unified deployment management script

Commands:
- start/stop/restart/status - service lifecycle
- logs - view service logs
- build/pull - build and deploy
- health - health check all services
- kong - Kong routes/services/plugins management
- db - PostgreSQL/Redis/Neo4j access and backup
- clean - cleanup images/volumes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-09 19:45:47 -08:00
parent e98b0a424f
commit f06e6ee76e
1 changed files with 435 additions and 0 deletions

435
scripts/deploy.sh Normal file
View File

@ -0,0 +1,435 @@
#!/bin/bash
#===============================================================================
# iConsulting 部署管理脚本
#
# 用法:
# ./scripts/deploy.sh <command> [options]
#
# 命令:
# start 启动所有服务
# stop 停止所有服务
# restart 重启所有服务
# status 查看服务状态
# logs 查看日志
# build 构建服务镜像
# pull 拉取最新代码并重新部署
# health 健康检查
# kong Kong 相关操作
# db 数据库相关操作
# clean 清理资源
#
#===============================================================================
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 项目根目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
cd "$PROJECT_ROOT"
#===============================================================================
# 辅助函数
#===============================================================================
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"
}
print_header() {
echo ""
echo "=============================================="
echo " $1"
echo "=============================================="
echo ""
}
#===============================================================================
# 服务管理
#===============================================================================
cmd_start() {
print_header "启动所有服务"
log_info "启动基础设施..."
docker compose up -d postgres redis neo4j
log_info "等待数据库就绪..."
sleep 10
log_info "启动 Kong API 网关..."
docker compose up -d kong
log_info "等待 Kong 就绪..."
sleep 5
log_info "启动后端服务..."
docker compose up -d user-service payment-service knowledge-service conversation-service evolution-service
log_info "启动 Nginx..."
docker compose up -d nginx
log_success "所有服务已启动"
cmd_status
}
cmd_stop() {
print_header "停止所有服务"
docker compose down
log_success "所有服务已停止"
}
cmd_restart() {
local service=$1
if [ -n "$service" ]; then
print_header "重启服务: $service"
docker compose restart "$service"
log_success "$service 已重启"
else
print_header "重启所有服务"
docker compose restart
log_success "所有服务已重启"
fi
}
cmd_status() {
print_header "服务状态"
docker compose ps
}
cmd_logs() {
local service=$1
local lines=${2:-100}
if [ -n "$service" ]; then
docker compose logs -f --tail="$lines" "$service"
else
docker compose logs -f --tail="$lines"
fi
}
#===============================================================================
# 构建和部署
#===============================================================================
cmd_build() {
local service=$1
if [ -n "$service" ]; then
print_header "构建服务: $service"
docker compose build --no-cache "$service"
else
print_header "构建所有服务"
docker compose build --no-cache
fi
log_success "构建完成"
}
cmd_pull() {
print_header "拉取最新代码并部署"
log_info "拉取最新代码..."
git pull
log_info "重新构建服务..."
docker compose build
log_info "重新启动服务..."
docker compose up -d
log_success "部署完成"
cmd_status
}
#===============================================================================
# 健康检查
#===============================================================================
cmd_health() {
print_header "健康检查"
echo "服务健康状态:"
echo ""
# 检查各服务
services=(
"postgres:5432:PostgreSQL"
"redis:6379:Redis"
"neo4j:7474:Neo4j"
"kong:8001:Kong"
"user-service:3001:User Service"
"payment-service:3002:Payment Service"
"knowledge-service:3003:Knowledge Service"
"conversation-service:3004:Conversation Service"
"evolution-service:3005:Evolution Service"
"nginx:80:Nginx"
)
for service_info in "${services[@]}"; do
IFS=':' read -r service port name <<< "$service_info"
if docker compose exec -T "$service" wget -q --spider "http://localhost:$port/health" 2>/dev/null || \
docker compose exec -T "$service" curl -sf "http://localhost:$port/health" 2>/dev/null || \
docker compose exec -T "$service" pg_isready 2>/dev/null || \
docker compose exec -T "$service" redis-cli ping 2>/dev/null | grep -q PONG; then
echo -e " ${GREEN}${NC} $name"
else
# 检查容器是否运行
if docker compose ps "$service" 2>/dev/null | grep -q "Up"; then
echo -e " ${YELLOW}?${NC} $name (运行中,但健康检查失败)"
else
echo -e " ${RED}${NC} $name (未运行)"
fi
fi
done
echo ""
# Kong 路由检查
log_info "Kong 路由配置:"
curl -s http://localhost:8001/routes 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//g; s/"//g' | while read name; do
echo " - $name"
done || echo " (无法获取)"
echo ""
}
#===============================================================================
# Kong 管理
#===============================================================================
cmd_kong() {
local subcmd=$1
shift
case "$subcmd" in
status)
print_header "Kong 状态"
curl -s http://localhost:8001/status | jq . 2>/dev/null || echo "Kong 未响应"
;;
routes)
print_header "Kong 路由"
curl -s http://localhost:8001/routes | jq '.data[] | {name, paths, methods}' 2>/dev/null || echo "Kong 未响应"
;;
services)
print_header "Kong 服务"
curl -s http://localhost:8001/services | jq '.data[] | {name, host, port}' 2>/dev/null || echo "Kong 未响应"
;;
plugins)
print_header "Kong 插件"
curl -s http://localhost:8001/plugins | jq '.data[] | {name, enabled}' 2>/dev/null || echo "Kong 未响应"
;;
reload)
print_header "重载 Kong 配置"
docker compose restart kong
log_success "Kong 已重载"
;;
test)
print_header "测试 Kong API 路由"
echo "测试 /api/v1/conversations:"
curl -s -o /dev/null -w " HTTP %{http_code}\n" -X POST http://localhost:8000/api/v1/conversations \
-H "Content-Type: application/json" \
-H "x-user-id: test" \
-d '{}'
echo "测试 /api/v1/users:"
curl -s -o /dev/null -w " HTTP %{http_code}\n" http://localhost:8000/api/v1/users/health 2>/dev/null || echo " (无 health 端点)"
;;
*)
echo "Kong 子命令:"
echo " status - 查看 Kong 状态"
echo " routes - 查看路由配置"
echo " services - 查看服务配置"
echo " plugins - 查看插件配置"
echo " reload - 重载配置"
echo " test - 测试 API 路由"
;;
esac
}
#===============================================================================
# 数据库管理
#===============================================================================
cmd_db() {
local subcmd=$1
shift
case "$subcmd" in
psql)
print_header "连接 PostgreSQL"
docker compose exec postgres psql -U postgres -d iconsulting
;;
redis)
print_header "连接 Redis"
docker compose exec redis redis-cli -a redis123
;;
neo4j)
print_header "Neo4j 浏览器"
echo "访问: http://localhost:7474"
echo "用户: neo4j"
echo "密码: neo4j123"
;;
backup)
local backup_dir="backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$backup_dir"
print_header "备份数据库"
log_info "备份 PostgreSQL..."
docker compose exec -T postgres pg_dump -U postgres iconsulting > "$backup_dir/postgres.sql"
log_info "备份 Redis..."
docker compose exec -T redis redis-cli -a redis123 BGSAVE
log_success "备份完成: $backup_dir"
;;
*)
echo "数据库子命令:"
echo " psql - 连接 PostgreSQL"
echo " redis - 连接 Redis"
echo " neo4j - Neo4j 连接信息"
echo " backup - 备份数据库"
;;
esac
}
#===============================================================================
# 清理
#===============================================================================
cmd_clean() {
local subcmd=$1
case "$subcmd" in
images)
print_header "清理未使用的镜像"
docker image prune -f
;;
volumes)
print_header "清理未使用的卷"
log_warn "这将删除未使用的数据卷!"
read -p "确定要继续吗?(y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker volume prune -f
fi
;;
all)
print_header "完全清理"
log_warn "这将停止所有容器并删除所有数据!"
read -p "确定要继续吗?(y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker compose down -v --rmi all
log_success "清理完成"
fi
;;
*)
echo "清理子命令:"
echo " images - 清理未使用的镜像"
echo " volumes - 清理未使用的卷"
echo " all - 完全清理(危险)"
;;
esac
}
#===============================================================================
# 主入口
#===============================================================================
show_help() {
echo "iConsulting 部署管理脚本"
echo ""
echo "用法: $0 <command> [options]"
echo ""
echo "命令:"
echo " start 启动所有服务"
echo " stop 停止所有服务"
echo " restart [service] 重启服务(可指定单个服务)"
echo " status 查看服务状态"
echo " logs [service] 查看日志"
echo " build [service] 构建服务镜像"
echo " pull 拉取最新代码并部署"
echo " health 健康检查"
echo " kong <subcmd> Kong 管理"
echo " db <subcmd> 数据库管理"
echo " clean <subcmd> 清理资源"
echo ""
echo "示例:"
echo " $0 start # 启动所有服务"
echo " $0 logs conversation-service # 查看对话服务日志"
echo " $0 kong routes # 查看 Kong 路由"
echo " $0 db psql # 连接 PostgreSQL"
echo ""
}
# 主命令分发
case "$1" in
start)
cmd_start
;;
stop)
cmd_stop
;;
restart)
cmd_restart "$2"
;;
status)
cmd_status
;;
logs)
cmd_logs "$2" "$3"
;;
build)
cmd_build "$2"
;;
pull)
cmd_pull
;;
health)
cmd_health
;;
kong)
shift
cmd_kong "$@"
;;
db)
shift
cmd_db "$@"
;;
clean)
shift
cmd_clean "$@"
;;
help|--help|-h)
show_help
;;
*)
if [ -n "$1" ]; then
log_error "未知命令: $1"
fi
show_help
exit 1
;;
esac