From 3056635a5c0948d9e8963e2279833551b7a65d80 Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Apr 2026 19:41:11 +0800 Subject: [PATCH] for deploy --- .dockerignore | 14 ++++++++++++++ .env.example | 33 ++++++++++++++++++-------------- Dockerfile | 27 ++++++++++++++++++++++++++ docker-compose.yml | 47 ++++++++++++++++++++++++++++++++++++++++++++++ entrypoint.sh | 8 ++++++++ 5 files changed, 115 insertions(+), 14 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..981ad2e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +venv/ +__pycache__/ +*.pyc +*.pyo +.env +*.db +*.db-shm +*.db-wal +.git/ +.gitignore +*.md +test_*.py +simulate_trades.py +scripts/ diff --git a/.env.example b/.env.example index 63aba3a..52f0a70 100644 --- a/.env.example +++ b/.env.example @@ -1,23 +1,28 @@ -# Database -DATABASE_URL=sqlite+aiosqlite:///./trumpsignal.db -# For Postgres in production: -# DATABASE_URL=postgresql+asyncpg://user:password@host:5432/trumpsignal +# ── Database ───────────────────────────────────────────────────────────────── +# For Docker Compose — only POSTGRES_PASSWORD needs to be set; +# DATABASE_URL is built automatically by docker-compose.yml. +# For local dev without Docker, set DATABASE_URL directly: +# DATABASE_URL=sqlite+aiosqlite:///./trumpsignal.db +POSTGRES_PASSWORD=change_me_in_production -# Frontend origin for CORS -FRONTEND_URL=http://localhost:3001 +# ── CORS / Frontend ────────────────────────────────────────────────────────── +# Your frontend origin — no trailing slash +FRONTEND_URL=https://yourdomain.com -# AI provider (OpenAI-compatible). Default below is gptsapi.net relay for Claude. +# ── Encryption ─────────────────────────────────────────────────────────────── +# KEK for envelope-encrypting HL API keys in DB. +# Generate: openssl rand -hex 32 +# WARNING: rotating this invalidates all stored keys. +ENCRYPTION_KEY= + +# ── AI provider ────────────────────────────────────────────────────────────── AI_API_KEY= AI_BASE_URL=https://api.gptsapi.net/v1 AI_MODEL=claude-sonnet-4-6 -# Hyperliquid — leverage & network only. Per-user API keys are stored in DB. -HL_LEVERAGE=3 +# ── Hyperliquid ────────────────────────────────────────────────────────────── HL_MAINNET=true +# ── Runtime ────────────────────────────────────────────────────────────────── # development | production -ENVIRONMENT=development - -# KEK for envelope-encrypting HL API keys in the DB. -# Generate: `openssl rand -hex 32`. ROTATING THIS INVALIDATES ALL STORED KEYS. -ENCRYPTION_KEY= +ENVIRONMENT=production diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d98cddb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM python:3.11-slim + +# System deps +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc libpq-dev curl \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Install Python deps first (layer cache) +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# App source +COPY . . + +# Make entrypoint executable +RUN chmod +x entrypoint.sh + +# Non-root user for security +RUN useradd -m appuser && chown -R appuser /app +USER appuser + +EXPOSE 8000 + +# Runs: alembic upgrade head → uvicorn +ENTRYPOINT ["./entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..43af063 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,47 @@ +services: + + db: + image: postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_DB: trumpsignal + POSTGRES_USER: trumpsignal + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U trumpsignal"] + interval: 5s + timeout: 5s + retries: 10 + + api: + build: . + restart: unless-stopped + depends_on: + db: + condition: service_healthy + ports: + - "8000:8000" + environment: + DATABASE_URL: postgresql+asyncpg://trumpsignal:${POSTGRES_PASSWORD}@db:5432/trumpsignal + FRONTEND_URL: ${FRONTEND_URL} + ENCRYPTION_KEY: ${ENCRYPTION_KEY} + AI_API_KEY: ${AI_API_KEY} + AI_BASE_URL: ${AI_BASE_URL:-https://api.gptsapi.net/v1} + AI_MODEL: ${AI_MODEL:-claude-sonnet-4-6} + HL_MAINNET: ${HL_MAINNET:-true} + ENVIRONMENT: ${ENVIRONMENT:-production} + volumes: + # Persist SQLite only if you're still using it (dev fallback). + # In production with Postgres this volume isn't needed. + - api_data:/app/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"] + interval: 15s + timeout: 5s + retries: 5 + +volumes: + postgres_data: + api_data: diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..aa7aaec --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e + +echo "[entrypoint] Running Alembic migrations..." +alembic upgrade head + +echo "[entrypoint] Starting API server..." +exec uvicorn app.main:app --host 0.0.0.0 --port 8000