From f151747d561728c06278b6ec4ac75a9114277947 Mon Sep 17 00:00:00 2001 From: Celes Renata Date: Wed, 29 Apr 2026 03:03:57 +0000 Subject: [PATCH] feat: add deploy-docker.sh with auto-detect Ollama, configurable model/URL --- deploy-docker.sh | 326 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100755 deploy-docker.sh diff --git a/deploy-docker.sh b/deploy-docker.sh new file mode 100755 index 0000000..50bda39 --- /dev/null +++ b/deploy-docker.sh @@ -0,0 +1,326 @@ +#!/usr/bin/env bash +set -euo pipefail + +# deploy-docker.sh — Deploy Stonks Oracle to a Docker host via SSH +# +# Usage: bash deploy-docker.sh [OPTIONS] +# +# Options: +# --host USER@HOST SSH target (default: celes@192.168.42.254) +# --ollama-url URL Ollama API URL (default: auto-detect or install) +# --ollama-model MODEL Ollama model name (default: qwen3.5:9b-fast) +# --dir PATH Remote install directory (default: ~/stonks-oracle) +# +# Examples: +# bash deploy-docker.sh +# bash deploy-docker.sh --ollama-url http://10.1.1.12:2701 --ollama-model qwen3.6 +# bash deploy-docker.sh --host user@myserver --dir /opt/stonks + +# ------------------------------------------------------- +# Configuration (override via flags or environment) +# ------------------------------------------------------- +REMOTE_HOST="${DEPLOY_HOST:-celes@192.168.42.254}" +REMOTE_DIR="${DEPLOY_DIR:-/home/celes/stonks-oracle}" +OLLAMA_URL="${DEPLOY_OLLAMA_URL:-}" +OLLAMA_MODEL="${DEPLOY_OLLAMA_MODEL:-qwen3.5:9b-fast}" +REPO_URL="http://admin:St0nks0racl3!@10.1.1.12:30300/admin/stonks-oracle.git" + +# Parse command-line flags +while [[ $# -gt 0 ]]; do + case $1 in + --host) REMOTE_HOST="$2"; shift 2 ;; + --ollama-url) OLLAMA_URL="$2"; shift 2 ;; + --ollama-model) OLLAMA_MODEL="$2"; shift 2 ;; + --dir) REMOTE_DIR="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +echo "=== Stonks Oracle Docker Deployment ===" +echo " Target: ${REMOTE_HOST}:${REMOTE_DIR}" +echo " Model: ${OLLAMA_MODEL}" +echo " Ollama: ${OLLAMA_URL:-auto-detect}" +echo "" + +# ------------------------------------------------------- +# Step 1: Clone or update the repo on the remote host +# ------------------------------------------------------- +echo "--- Step 1: Syncing repository ---" +ssh "$REMOTE_HOST" bash -s -- "$REMOTE_DIR" "$REPO_URL" <<'REMOTE_SCRIPT' +set -euo pipefail +REMOTE_DIR="$1" +REPO_URL="$2" + +if [ -d "$REMOTE_DIR/.git" ]; then + echo " Updating existing repo..." + cd "$REMOTE_DIR" + git fetch origin + git reset --hard origin/main +else + echo " Cloning fresh..." + git clone "$REPO_URL" "$REMOTE_DIR" + cd "$REMOTE_DIR" +fi + +echo " ✓ Repo synced at $(git log --oneline -1)" +REMOTE_SCRIPT +echo "" + +# ------------------------------------------------------- +# Step 2: Detect or configure Ollama +# ------------------------------------------------------- +echo "--- Step 2: Configuring Ollama ---" +if [ -z "$OLLAMA_URL" ]; then + # Auto-detect: check if Ollama is running on the remote host + OLLAMA_URL=$(ssh "$REMOTE_HOST" bash -s <<'DETECT_SCRIPT' +# Check common Ollama ports +for port in 11434 2701; do + if curl -sf --connect-timeout 2 "http://localhost:$port/api/tags" > /dev/null 2>&1; then + echo "http://localhost:$port" + exit 0 + fi +done +echo "" +DETECT_SCRIPT + ) + + if [ -n "$OLLAMA_URL" ]; then + echo " ✓ Found existing Ollama at: $OLLAMA_URL" + else + echo " No Ollama detected — will use Docker container" + OLLAMA_URL="http://ollama:11434" + fi +else + echo " Using provided Ollama URL: $OLLAMA_URL" +fi + +# Determine if we need the Docker Ollama container +USE_DOCKER_OLLAMA=false +if [ "$OLLAMA_URL" = "http://ollama:11434" ]; then + USE_DOCKER_OLLAMA=true +fi +echo "" + +# ------------------------------------------------------- +# Step 3: Create .env and compose override +# ------------------------------------------------------- +echo "--- Step 3: Configuring environment ---" +ssh "$REMOTE_HOST" bash -s -- "$REMOTE_DIR" "$OLLAMA_URL" "$OLLAMA_MODEL" "$USE_DOCKER_OLLAMA" <<'REMOTE_SCRIPT' +set -euo pipefail +REMOTE_DIR="$1" +OLLAMA_URL="$2" +OLLAMA_MODEL="$3" +USE_DOCKER_OLLAMA="$4" +cd "$REMOTE_DIR" + +# Read API keys from local files if they exist +POLYGON_KEY="" +ALPACA_KEY="" +ALPACA_SECRET="" +ALPACA_URL="https://paper-api.alpaca.markets" + +[ -f polygon.io.key ] && POLYGON_KEY=$(cat polygon.io.key) +[ -f alpaca.key ] && ALPACA_KEY=$(cat alpaca.key) +[ -f alpaca.secret ] && ALPACA_SECRET=$(cat alpaca.secret) +[ -f alpaca.url ] && ALPACA_URL=$(cat alpaca.url) + +cat > .env < docker-compose.override.yml < docker-compose.override.yml </dev/null || true + +# Build all images +echo " Building images (this may take a few minutes)..." +docker compose build --quiet 2>&1 | tail -5 + +# Start infrastructure +echo " Starting infrastructure..." +if [ "$USE_DOCKER_OLLAMA" = "true" ]; then + docker compose up -d postgres redis minio minio-init ollama +else + docker compose up -d postgres redis minio minio-init +fi + +# Wait for infrastructure to be healthy +echo " Waiting for infrastructure health checks..." +for svc in postgres redis minio; do + for i in $(seq 1 30); do + if docker compose ps "$svc" 2>/dev/null | grep -q healthy; then + break + fi + sleep 2 + done +done +echo " ✓ Infrastructure healthy" + +# Start all application services +echo " Starting application services..." +docker compose up -d + +echo " Waiting for services to stabilize..." +sleep 20 + +# Show status +echo "" +echo " Service Status:" +docker compose ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null | head -25 || docker compose ps +REMOTE_SCRIPT +echo "" + +# ------------------------------------------------------- +# Step 5: Seed the database +# ------------------------------------------------------- +echo "--- Step 5: Seeding database ---" +ssh "$REMOTE_HOST" bash -s -- "$REMOTE_DIR" <<'REMOTE_SCRIPT' +set -euo pipefail +cd "$1" + +# Wait for query-api to be healthy +for i in $(seq 1 30); do + if docker compose ps query-api 2>/dev/null | grep -q healthy; then + break + fi + sleep 3 +done + +# Run the symbol registry seed +echo " Seeding symbol registry..." +docker compose exec -T scheduler python -m services.symbol_registry.seed 2>/dev/null && echo " ✓ Database seeded" || echo " ⚠ Seed skipped (may already be seeded or service not ready)" +REMOTE_SCRIPT +echo "" + +# ------------------------------------------------------- +# Step 6: Ensure Ollama model is available +# ------------------------------------------------------- +echo "--- Step 6: Checking Ollama model ---" +ssh "$REMOTE_HOST" bash -s -- "$OLLAMA_URL" "$OLLAMA_MODEL" "$USE_DOCKER_OLLAMA" "$REMOTE_DIR" <<'REMOTE_SCRIPT' +set -euo pipefail +OLLAMA_URL="$1" +OLLAMA_MODEL="$2" +USE_DOCKER_OLLAMA="$3" +REMOTE_DIR="$4" + +if [ "$USE_DOCKER_OLLAMA" = "true" ]; then + # Pull via Docker container + cd "$REMOTE_DIR" + if docker compose exec -T ollama ollama list 2>/dev/null | grep -q "$OLLAMA_MODEL"; then + echo " ✓ Model $OLLAMA_MODEL already available" + else + echo " Pulling $OLLAMA_MODEL via Docker Ollama..." + docker compose exec -T ollama ollama pull "$OLLAMA_MODEL" + echo " ✓ Model pulled" + fi +else + # Check via API + if curl -sf "$OLLAMA_URL/api/tags" 2>/dev/null | grep -q "$OLLAMA_MODEL"; then + echo " ✓ Model $OLLAMA_MODEL already available at $OLLAMA_URL" + else + echo " Pulling $OLLAMA_MODEL via $OLLAMA_URL..." + curl -sf "$OLLAMA_URL/api/pull" -d "{\"name\":\"$OLLAMA_MODEL\"}" | tail -1 + echo " ✓ Model pulled" + fi +fi +REMOTE_SCRIPT +echo "" + +# ------------------------------------------------------- +# Done +# ------------------------------------------------------- +REMOTE_IP=$(echo "$REMOTE_HOST" | cut -d@ -f2) +echo "=== Deployment Complete ===" +echo "" +echo "Endpoints:" +echo " Dashboard: http://${REMOTE_IP}:3000" +echo " Query API: http://${REMOTE_IP}:8004" +echo " Symbol Registry: http://${REMOTE_IP}:8001" +echo " Trading Engine: http://${REMOTE_IP}:8002" +echo " Risk Engine: http://${REMOTE_IP}:8003" +echo " MinIO Console: http://${REMOTE_IP}:9001" +echo " Superset: http://${REMOTE_IP}:8088" +echo " Ollama: ${OLLAMA_URL}" +echo "" +echo "Commands:" +echo " ssh $REMOTE_HOST 'cd $REMOTE_DIR && docker compose logs -f'" +echo " ssh $REMOTE_HOST 'cd $REMOTE_DIR && docker compose ps'" +echo " ssh $REMOTE_HOST 'cd $REMOTE_DIR && docker compose down'"