feat: add deploy-docker.sh with auto-detect Ollama, configurable model/URL
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize Pipeline was successful
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-1 Pipeline was successful
ci/woodpecker/push/build-2 Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize Pipeline was successful
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
This commit is contained in:
Executable
+326
@@ -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 <<EOF
|
||||
# Stonks Oracle — Docker Deployment Environment
|
||||
MARKET_DATA_API_KEY=${POLYGON_KEY}
|
||||
BROKER_API_KEY=${ALPACA_KEY}
|
||||
BROKER_API_SECRET=${ALPACA_SECRET}
|
||||
BROKER_BASE_URL=${ALPACA_URL}
|
||||
TRADING_ENABLED=true
|
||||
TRADING_RISK_TIER=moderate
|
||||
TRADING_MAX_OPEN_POSITIONS=15
|
||||
OLLAMA_MODEL=${OLLAMA_MODEL}
|
||||
MACRO_ENABLED=true
|
||||
COMPETITIVE_ENABLED=true
|
||||
EOF
|
||||
|
||||
# Create compose override based on Ollama configuration
|
||||
if [ "$USE_DOCKER_OLLAMA" = "true" ]; then
|
||||
# Using Docker Ollama — no override needed, default compose handles it
|
||||
rm -f docker-compose.override.yml
|
||||
echo " ✓ Using Docker Ollama container"
|
||||
else
|
||||
# Using external Ollama — disable the container and point services to it
|
||||
# Determine if URL is localhost (needs host-gateway) or remote
|
||||
if echo "$OLLAMA_URL" | grep -qE "localhost|127\.0\.0\.1"; then
|
||||
DOCKER_OLLAMA_URL="http://host.docker.internal:$(echo "$OLLAMA_URL" | grep -oP ':\K[0-9]+')"
|
||||
cat > docker-compose.override.yml <<EOF
|
||||
services:
|
||||
ollama:
|
||||
entrypoint: ["true"]
|
||||
restart: "no"
|
||||
ports: []
|
||||
extractor:
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
OLLAMA_BASE_URL: "${DOCKER_OLLAMA_URL}"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
recommendation:
|
||||
environment:
|
||||
OLLAMA_BASE_URL: "${DOCKER_OLLAMA_URL}"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
EOF
|
||||
else
|
||||
# Remote Ollama — containers can reach it directly
|
||||
cat > docker-compose.override.yml <<EOF
|
||||
services:
|
||||
ollama:
|
||||
entrypoint: ["true"]
|
||||
restart: "no"
|
||||
extractor:
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
OLLAMA_BASE_URL: "${OLLAMA_URL}"
|
||||
recommendation:
|
||||
environment:
|
||||
OLLAMA_BASE_URL: "${OLLAMA_URL}"
|
||||
EOF
|
||||
fi
|
||||
echo " ✓ Override created — services will use external Ollama at ${OLLAMA_URL}"
|
||||
fi
|
||||
|
||||
echo " ✓ .env configured (polygon=$([ -n "$POLYGON_KEY" ] && echo 'set' || echo 'empty'), alpaca=$([ -n "$ALPACA_KEY" ] && echo 'set' || echo 'empty'))"
|
||||
REMOTE_SCRIPT
|
||||
echo ""
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Step 4: Build and start all services
|
||||
# -------------------------------------------------------
|
||||
echo "--- Step 4: Building and starting services ---"
|
||||
ssh "$REMOTE_HOST" bash -s -- "$REMOTE_DIR" "$USE_DOCKER_OLLAMA" <<'REMOTE_SCRIPT'
|
||||
set -euo pipefail
|
||||
REMOTE_DIR="$1"
|
||||
USE_DOCKER_OLLAMA="$2"
|
||||
cd "$REMOTE_DIR"
|
||||
|
||||
# Stop any existing deployment
|
||||
docker compose down 2>/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'"
|
||||
Reference in New Issue
Block a user