Skip to main content
Glama
update.sh11.2 kB
#!/bin/bash ################################################################################ # Zero-Downtime Update Script for KYC MCP Server # This script performs rolling updates with minimal service interruption ################################################################################ set -euo pipefail # Configuration APP_DIR="/opt/kyc-mcp-server" BLUE_COMPOSE="docker-compose.blue.yml" GREEN_COMPOSE="docker-compose.green.yml" HEALTH_CHECK_TIMEOUT=60 HEALTH_CHECK_INTERVAL=5 # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging functions log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } log_step() { echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" } # Error handler error_exit() { log_error "$1" exit 1 } # Check prerequisites check_prerequisites() { log_step "Checking prerequisites..." if [ ! -f "$APP_DIR/docker-compose.yml" ]; then error_exit "docker-compose.yml not found in $APP_DIR" fi if [ ! -f "$APP_DIR/.env" ]; then error_exit ".env file not found in $APP_DIR" fi log_info "Prerequisites check passed" } # Detect current active deployment detect_active_deployment() { log_step "Detecting active deployment..." if docker ps | grep -q "kyc-mcp-server-blue"; then echo "blue" elif docker ps | grep -q "kyc-mcp-server-green"; then echo "green" else # Default to blue if no deployment exists echo "blue" fi } # Get inactive deployment get_inactive_deployment() { local active=$1 if [ "$active" = "blue" ]; then echo "green" else echo "blue" fi } # Create blue-green compose files create_compose_files() { log_step "Creating blue-green compose files..." cd "$APP_DIR" # Create blue deployment compose file cat > "$BLUE_COMPOSE" <<'EOF' version: '3.8' services: kyc-mcp-server-blue: build: context: . dockerfile: Dockerfile container_name: kyc-mcp-server-blue environment: - KYC_API_BASE_URL=${KYC_API_BASE_URL} - KYC_API_KEY=${KYC_API_KEY} - KYC_JWT_SECRET=${KYC_JWT_SECRET} - KYC_JWT_ALGORITHM=HS256 - KYC_JWT_EXPIRY=3600 - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - CACHE_ENABLED=true - CACHE_DEFAULT_TTL=3600 - RATE_LIMIT_ENABLED=true - RATE_LIMIT_PER_MINUTE=60 - RATE_LIMIT_PER_HOUR=1000 - LOG_LEVEL=INFO - ENABLE_METRICS=true - METRICS_PORT=9090 - MAX_RETRIES=3 - REQUEST_TIMEOUT=30 depends_on: - redis networks: - kyc-network restart: unless-stopped stdin_open: true tty: true ports: - "8080:8080" redis: image: redis:7-alpine container_name: kyc-redis command: redis-server --appendonly yes volumes: - redis-data:/data networks: - kyc-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 networks: kyc-network: driver: bridge volumes: redis-data: driver: local EOF # Create green deployment compose file cat > "$GREEN_COMPOSE" <<'EOF' version: '3.8' services: kyc-mcp-server-green: build: context: . dockerfile: Dockerfile container_name: kyc-mcp-server-green environment: - KYC_API_BASE_URL=${KYC_API_BASE_URL} - KYC_API_KEY=${KYC_API_KEY} - KYC_JWT_SECRET=${KYC_JWT_SECRET} - KYC_JWT_ALGORITHM=HS256 - KYC_JWT_EXPIRY=3600 - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - CACHE_ENABLED=true - CACHE_DEFAULT_TTL=3600 - RATE_LIMIT_ENABLED=true - RATE_LIMIT_PER_MINUTE=60 - RATE_LIMIT_PER_HOUR=1000 - LOG_LEVEL=INFO - ENABLE_METRICS=true - METRICS_PORT=9091 - MAX_RETRIES=3 - REQUEST_TIMEOUT=30 depends_on: - redis networks: - kyc-network restart: unless-stopped stdin_open: true tty: true ports: - "8081:8080" redis: image: redis:7-alpine container_name: kyc-redis command: redis-server --appendonly yes volumes: - redis-data:/data networks: - kyc-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 networks: kyc-network: driver: bridge volumes: redis-data: driver: local EOF log_info "Blue-green compose files created" } # Pull latest code pull_code() { log_step "Pulling latest code..." cd "$APP_DIR" if [ -d .git ]; then git stash git pull origin main || git pull origin master log_info "Code updated" else log_warn "Not a git repository. Skipping code pull." fi } # Build new version build_new_version() { local deployment=$1 log_step "Building new version for $deployment deployment..." cd "$APP_DIR" if [ "$deployment" = "blue" ]; then docker-compose -f "$BLUE_COMPOSE" build --no-cache else docker-compose -f "$GREEN_COMPOSE" build --no-cache fi log_info "New version built" } # Start new deployment start_new_deployment() { local deployment=$1 log_step "Starting $deployment deployment..." cd "$APP_DIR" if [ "$deployment" = "blue" ]; then docker-compose -f "$BLUE_COMPOSE" up -d else docker-compose -f "$GREEN_COMPOSE" up -d fi log_info "$deployment deployment started" } # Wait for new deployment to be ready wait_for_deployment() { local deployment=$1 local container_name="kyc-mcp-server-$deployment" log_step "Waiting for $deployment deployment to be ready..." local elapsed=0 while [ $elapsed -lt $HEALTH_CHECK_TIMEOUT ]; do if docker ps | grep -q "$container_name"; then # Simple check: container is running log_info "$deployment deployment is running" sleep 5 # Give it a bit more time to stabilize return 0 fi echo -n "." sleep $HEALTH_CHECK_INTERVAL elapsed=$((elapsed + HEALTH_CHECK_INTERVAL)) done echo "" log_error "$deployment deployment failed to start within ${HEALTH_CHECK_TIMEOUT}s" return 1 } # Health check new deployment health_check_deployment() { local deployment=$1 local container_name="kyc-mcp-server-$deployment" log_step "Performing health check on $deployment deployment..." # Check if container is running if ! docker ps | grep -q "$container_name"; then log_error "$deployment container is not running" return 1 fi # Check logs for errors local logs=$(docker logs --tail 50 "$container_name" 2>&1) if echo "$logs" | grep -qi "fatal\|critical"; then log_error "Critical errors found in $deployment logs" return 1 fi log_info "$deployment deployment health check passed" return 0 } # Switch traffic to new deployment switch_traffic() { local new_deployment=$1 log_step "Switching traffic to $new_deployment deployment..." # In a real scenario, this would update load balancer or reverse proxy # For now, we'll just update nginx configuration if [ -f /etc/nginx/sites-available/kyc-mcp.conf ]; then local new_port if [ "$new_deployment" = "blue" ]; then new_port="8080" else new_port="8081" fi # Update nginx upstream sudo sed -i "s/server localhost:[0-9]\+/server localhost:$new_port/" \ /etc/nginx/sites-available/kyc-mcp.conf # Test nginx configuration sudo nginx -t # Reload nginx sudo systemctl reload nginx log_info "Traffic switched to $new_deployment deployment" else log_warn "Nginx configuration not found. Manual traffic switching required." fi } # Stop old deployment stop_old_deployment() { local deployment=$1 log_step "Stopping $deployment deployment..." cd "$APP_DIR" # Wait a bit before stopping to ensure traffic has switched log_info "Waiting 30 seconds for connections to drain..." sleep 30 if [ "$deployment" = "blue" ]; then docker-compose -f "$BLUE_COMPOSE" down else docker-compose -f "$GREEN_COMPOSE" down fi log_info "$deployment deployment stopped" } # Rollback to old deployment rollback() { local old_deployment=$1 log_error "Update failed. Rolling back to $old_deployment deployment..." # Switch traffic back switch_traffic "$old_deployment" log_info "Rollback completed" } # Show update summary show_summary() { local active_deployment=$1 log_step "Update Summary" echo "==========================================" echo "Application: KYC MCP Server" echo "Active Deployment: $active_deployment" echo "Update Time: $(date '+%Y-%m-%d %H:%M:%S')" echo "==========================================" # Show running containers echo "" echo "Running Containers:" docker ps --filter "name=kyc" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" echo "" echo "==========================================" log_info "Zero-downtime update completed successfully!" echo "==========================================" } # Main update function main() { log_info "Starting zero-downtime update of KYC MCP Server..." # Check prerequisites check_prerequisites # Create blue-green compose files create_compose_files # Detect current active deployment ACTIVE_DEPLOYMENT=$(detect_active_deployment) NEW_DEPLOYMENT=$(get_inactive_deployment "$ACTIVE_DEPLOYMENT") log_info "Current active deployment: $ACTIVE_DEPLOYMENT" log_info "New deployment will be: $NEW_DEPLOYMENT" # Pull latest code pull_code # Build new version build_new_version "$NEW_DEPLOYMENT" # Start new deployment start_new_deployment "$NEW_DEPLOYMENT" # Wait for new deployment to be ready if ! wait_for_deployment "$NEW_DEPLOYMENT"; then docker-compose -f "docker-compose.$NEW_DEPLOYMENT.yml" down error_exit "New deployment failed to start" fi # Health check new deployment if ! health_check_deployment "$NEW_DEPLOYMENT"; then docker-compose -f "docker-compose.$NEW_DEPLOYMENT.yml" down error_exit "New deployment failed health check" fi # Switch traffic to new deployment switch_traffic "$NEW_DEPLOYMENT" # Stop old deployment stop_old_deployment "$ACTIVE_DEPLOYMENT" # Show summary show_summary "$NEW_DEPLOYMENT" log_info "Update completed successfully!" } # Run main function main

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CTD-Techs/CTD-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server