diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..df5e60b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +__pycache__/ +*.py[cod] +*.log +.env +.git +.gitignore +.notebooks +.ipynb_checkpoints/ diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml new file mode 100644 index 0000000..8e89a71 --- /dev/null +++ b/.github/workflows/build-docker.yml @@ -0,0 +1,32 @@ +name: Build Streamlit image + +on: + push: + branches: ["main"] + workflow_dispatch: + +permissions: + contents: read + packages: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile.streamlit + push: true + tags: ghcr.io/${{ github.repository_owner }}/btc-tools-dashboard:latest diff --git a/Dockerfile.streamlit b/Dockerfile.streamlit new file mode 100644 index 0000000..4f6696d --- /dev/null +++ b/Dockerfile.streamlit @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1 +FROM python:3.11-slim AS base + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /app + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 8501 + +CMD ["streamlit", "run", "dashboard/app.py", "--server.port=8501", "--server.address=0.0.0.0"] diff --git a/README.md b/README.md index 09c4625..dac615f 100644 --- a/README.md +++ b/README.md @@ -1 +1,33 @@ -# btc-tools \ No newline at end of file +# btc-tools + +BTC Tools provides a Streamlit dashboard and supporting utilities for tracking +Bitcoin technical indicators using Kraken market data via `ccxt`. + +## Quickstart + +```bash +pip install -r requirements.txt +streamlit run dashboard/app.py +``` + +## Run with Docker + +Build and start the dashboard in a self-contained container: + +```bash +docker compose up --build +``` + +This uses the provided `Dockerfile.streamlit` and maps the service to +. The container is configured to restart automatically, +matching always-on hosts like project hubs. + +## Permanent hosting + +- Deploy the Docker image automatically with the provided GitHub Actions workflow + (publishes to GitHub Container Registry as + `ghcr.io//btc-tools-dashboard:latest`). +- Or follow the deployment guide for Streamlit Community Cloud, Hugging Face + Spaces, and other hosting targets. + +See [docs/deployment.md](docs/deployment.md) for detailed instructions. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..700dd5a --- /dev/null +++ b/compose.yaml @@ -0,0 +1,11 @@ +services: + streamlit: + build: + context: . + dockerfile: Dockerfile.streamlit + ports: + - "8501:8501" + restart: unless-stopped + environment: + - STREAMLIT_SERVER_PORT=8501 + - STREAMLIT_SERVER_ADDRESS=0.0.0.0 diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..1b0f519 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,86 @@ +# Deployment Guide + +This project ships with a Streamlit dashboard located at `dashboard/app.py`. The +sections below walk through a few zero-cost and low-maintenance options for +keeping the site running continuously, similar to other AI project hubs. + +## Option 1 – Streamlit Community Cloud (recommended) + +The [Streamlit Community Cloud](https://streamlit.io/cloud) offers free hosting +for public Streamlit applications and automatically keeps the service alive. + +1. **Prepare your repository** + - Push this project to a public GitHub repository (forking it is fine). + - Ensure the repo contains `dashboard/app.py` and `requirements.txt` at the + root (already present in this project). +2. **Create the app on Streamlit Cloud** + - Sign in at using your GitHub account. + - Click **New app**, pick the repository, select the default branch, and set + the main file path to `dashboard/app.py`. + - The build system will auto-install dependencies from `requirements.txt` and + start the app. The site receives a stable public URL that stays active as + long as it has occasional traffic (Streamlit periodically wakes the app). +3. **Optional: configure secrets / settings** + - If you need to override the timeframe or other values, edit + `conf/settings.yml` in your repository. + - If you later add credentials or API keys, open the Streamlit Cloud app, + navigate to **Settings → Secrets**, and paste the key/value pairs in TOML + format. + +The app will restart automatically whenever you push new commits to the selected +branch, so keeping it updated is just a matter of pushing to GitHub. + +## Option 2 – GitHub Actions + GitHub Container Registry + +The repository now includes a workflow at +`.github/workflows/build-docker.yml` that continuously builds the production +image using `Dockerfile.streamlit`. + +1. Enable GitHub Packages for your account/organization (Settings → Packages). +2. Push this repository to GitHub and ensure the `main` branch is your default. +3. On each push to `main`, the workflow builds `ghcr.io//btc-tools-dashboard:latest` + using the checked-in Dockerfile and publishes it to GHCR. You can also start a + manual build from the **Actions** tab via the **Run workflow** button. +4. Deploy the published image to any container host (Fly.io, Render, Railway, + Google Cloud Run, a VPS, etc.) and configure it to restart on failure. The + container automatically exposes Streamlit on port 8501 and binds to + `0.0.0.0`, so no additional entrypoint work is required. + +## Option 3 – Hugging Face Spaces + +[Hugging Face Spaces](https://huggingface.co/spaces) can also host Streamlit apps +permanently with minimal configuration. + +1. Create a new **Space** and choose the **Streamlit** template. +2. Set the `App file` to `dashboard/app.py` and upload the project files (or + connect the Space to your GitHub repo via the **Files and versions** tab). +3. Spaces automatically install the packages from `requirements.txt` and expose + the application at `https://.hf.space`. +4. Enable **Hardware → Keep alive** if you want the project to stay running even + without visitors (requires HF Pro). + +## Option 4 – Self-host with Docker Compose + +If you prefer to run the dashboard yourself, use the included Docker artifacts. + +```bash +docker compose up --build -d +``` + +The `compose.yaml` file wraps the `Dockerfile.streamlit` image and maps the +service to port 8501. The container is set to `restart: unless-stopped` so it +automatically comes back online if the host reboots. + +## Keeping the app healthy + +Regardless of the hosting option you choose: + +- Monitor logs for connectivity limits imposed by the Kraken API (ccxt handles + rate limiting, but external providers may throttle sustained heavy use). +- Schedule occasional visits or use the hosting provider’s “keep warm” toggle to + prevent free tiers from sleeping the app. +- When updating dependencies, test locally with `streamlit run dashboard/app.py` + (or `docker compose up --build`) before pushing to production. + +With the managed options above—or your own container host—you can achieve an +always-on experience similar to other AI dashboards hosted on project hubs.