#!/usr/bin/env bash # ============================================================================= # Fischer AgentKit — 生产环境一键启动脚本 # ============================================================================= # # 启动:Docker Compose(agentkit + Redis + PostgreSQL) # 要求:.env 文件存在(含 LLM API Key、JWT Secret) # # 用法: # bash scripts/prod-start.sh # 启动所有服务 # bash scripts/prod-start.sh --init # 首次启动(初始化 DB) # bash scripts/prod-start.sh --build # 构建镜像后启动 # bash scripts/prod-start.sh --help # 帮助 # ============================================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$PROJECT_ROOT" : "${COMPOSE_FILE:=docker-compose.yaml}" # ── 颜色 ──────────────────────────────────────────────────────────────────── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # ── 帮助 ──────────────────────────────────────────────────────────────────── show_help() { cat <<-'EOF' Fischer AgentKit — 生产环境启动 用法: bash scripts/prod-start.sh [选项] 选项: --init 首次启动,初始化数据库表 --build 先构建/拉取镜像,再启动 --pull 仅拉取最新镜像(不启动) --help 显示此帮助 Docker Compose 文件: docker-compose.yaml 服务端口: 8001 — AgentKit API 服务 6379 — Redis 5432 — PostgreSQL 访问: http://localhost:8001 EOF } # ── 参数解析 ──────────────────────────────────────────────────────────────── INIT_DB=0 BUILD=0 PULL_ONLY=0 while [[ $# -gt 0 ]]; do case $1 in --init) INIT_DB=1; shift ;; --build) BUILD=1; shift ;; --pull) PULL_ONLY=1; shift ;; --help|-h) show_help; exit 0 ;; *) shift ;; esac done # ── 日志函数 ──────────────────────────────────────────────────────────────── info() { echo -e "${BLUE}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[FAIL]${NC} $*"; } # ── 前置检查 ──────────────────────────────────────────────────────────────── check_deps() { info "检查依赖..." for cmd in docker; do if ! command -v "$cmd" &>/dev/null; then fail "缺少依赖: $cmd" exit 1 fi done # docker compose v2+ (no separate docker-compose binary needed) if ! command -v docker-compose &>/dev/null && docker compose version &>/dev/null; then ok "docker compose 可用(v2+)" elif command -v docker-compose &>/dev/null; then ok "docker-compose 可用" else fail "缺少 docker 或 docker compose v2" exit 1 fi ok "依赖检查通过" } check_env() { info "检查环境配置..." if [[ ! -f .env ]]; then fail "未找到 .env 文件" echo " 请先创建 .env 文件(参考 .env.example)" exit 1 fi # 检查关键变量 if ! grep -q "DASHSCOPE_API_KEY\|DEEPSEEK_API_KEY" .env 2>/dev/null; then warn ".env 中可能缺少 LLM API Key" fi ok ".env 存在" } # ── 数据库初始化 ──────────────────────────────────────────────────────────── init_db() { info "初始化数据库..." docker compose -f "$COMPOSE_FILE" exec -T postgres \ psql -U agentkit -d agentkit -c "SELECT 1" &>/dev/null || { fail "PostgreSQL 容器未就绪,等待后重试..." sleep 5 } # 等待 PostgreSQL 完全就绪 local attempt=0 while [[ $attempt -lt 30 ]]; do if docker compose -f "$COMPOSE_FILE" exec -T postgres \ pg_isready -U agentkit &>/dev/null; then break fi sleep 1 ((attempt++)) done ok "数据库就绪" } # ── 主流程 ───────────────────────────────────────────────────────────────── echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo -e "${CYAN} Fischer AgentKit — 生产环境启动${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" check_deps check_env if [[ $PULL_ONLY -eq 1 ]]; then info "拉取最新镜像..." docker compose -f "$COMPOSE_FILE" pull ok "镜像拉取完成" exit 0 fi echo "" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" echo -e "${GREEN} 启动 Docker 服务...${NC}" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" echo "" if [[ $BUILD -eq 1 ]]; then info "构建/拉取镜像..." docker compose -f "$COMPOSE_FILE" build --pull ok "镜像构建完成" fi # 创建网络(如不存在) docker network ls 2>/dev/null | grep -q "fischer-agentkit_default" || \ docker network create fischer-agentkit_default &>/dev/null || true info "启动服务(docker compose up -d)..." docker compose -f "$COMPOSE_FILE" up -d --remove-orphans # 等待健康检查 info "等待服务就绪(健康检查最多 120s)..." local attempt=0 while [[ $attempt -lt 60 ]]; do if curl -sf http://127.0.0.1:8001/api/v1/health &>/dev/null; then break fi sleep 2 ((attempt++)) echo -n "." done echo "" # 显示状态 echo "" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" echo -e "${GREEN} Docker 服务状态${NC}" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" docker compose -f "$COMPOSE_FILE" ps # 状态检查 if curl -sf http://127.0.0.1:8001/api/v1/health &>/dev/null; then echo "" ok "AgentKit API 就绪 -> http://127.0.0.1:8001" echo "" echo -e "${GREEN}═══════════════════════════════════════════════════${NC}" echo -e "${GREEN} 生产服务全部启动成功!${NC}" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" echo -e " AgentKit API: ${GREEN}http://localhost:8001${NC}" echo -e " Redis: ${GREEN}localhost:6379${NC}" echo -e " PostgreSQL: ${GREEN}localhost:5432${NC}" echo -e "${GREEN}─────────────────────────────────────────────────${NC}" echo -e " 查看日志: ${CYAN}docker compose -f $COMPOSE_FILE logs -f${NC}" echo -e " 停止服务: ${CYAN}bash scripts/prod-stop.sh${NC}" echo -e "${GREEN}═══════════════════════════════════════════════════${NC}" else echo "" fail "AgentKit API 启动超时,查看日志诊断:" echo -e " ${CYAN}docker compose -f $COMPOSE_FILE logs --tail=50${NC}" exit 1 fi