BioScan Museo ships as a fully self-contained Docker Compose stack. A single build command brings up the Flask web app, a local Ollama LLM, the FastAPI TTS sidecar, and two ngrok tunnels for public HTTPS access. This guide explains each service, port mapping, volume layout, and how to tune the stack for constrained hardware like the Orange Pi 4 Pro.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/GustavoNightmare/InformacionMuseo/llms.txt
Use this file to discover all available pages before exploring further.
Deploy the Full Stack
Prepare environment variables
Copy If ngrok tunnels are not needed (local-only deployment), the
.env.example to .env and fill in all required values before building. The minimum set needed to start the stack without errors is:ngrok and ngrok-tts services will fail to start but the rest of the stack will work normally.Build and start all services
From the project root directory:The
--build flag rebuilds the museo-app and servertts images from their respective Dockerfiles. The ollama and ngrok services use pre-built images pulled from Docker Hub. On first run, the Ollama init script will pull the configured chat and embedding models, which may take significant time depending on network and hardware.Verify all services are up
Check the status of every container:Run quick health checks against the two main HTTP services:Replace
IP_O_HOST with localhost for local access or your machine’s LAN IP for network access.Retrieve public ngrok URLs
Once both ngrok containers are running, retrieve their public HTTPS URLs from the logs:Each service prints its assigned HTTPS URL on startup. You can also inspect them through the browser-based dashboards at the ports listed in the Port Mappings table below.After obtaining the TTS tunnel URL, update Then recreate only the TTS service so it picks up the new value:
.env:Service Reference
Each service indocker-compose.yml has a specific role. The table below summarises what each one does, its image source, and its key environment variables.
museo-app
Built from the project rootDockerfile (Python 3.11-slim). The docker/entrypoint.sh script runs flask --app app.py init-db, optionally create-admin (when CREATE_ADMIN_ON_BOOT=true) and seed (when SEED_ON_BOOT=true), then launches Gunicorn:
docker-compose.yml:
ollama
Usesollama/ollama:latest with a custom entrypoint (docker/ollama-init.sh) that starts the Ollama server, waits for it to be ready, then pulls the chat and embedding models if they are not already cached:
ollama/ directory is mounted as a volume so downloaded models persist across restarts.
servertts
Built fromServertts/Dockerfile. Communicates back to museo-app using:
Servertts/cache_audio/ and debug QR frames in Servertts/debug_frames/.
ngrok
Usesngrok/ngrok:latest. Tunnels the Flask app:
ngrok-tts
A secondngrok/ngrok:latest instance with a separate auth token. Tunnels the TTS sidecar:
Port Mappings
| Service | Host Port | Container Port | Description |
|---|---|---|---|
museo-app | 5000 | 5000 | Flask / Gunicorn web application |
servertts | 8010 | 8010 | FastAPI TTS sidecar |
ngrok | 4040 | 4040 | ngrok web inspector for Flask tunnel |
ngrok-tts | 4041 | 4040 | ngrok web inspector for TTS tunnel |
Persistence Volumes
All stateful data is stored in host-relative directories that survivedocker compose down and --build rebuilds:
| Host directory | Mount point in container | Contents |
|---|---|---|
./instance | /app/instance | SQLite database (bioscan.db) |
./chroma_db | /app/chroma_db | ChromaDB vector index |
./static/uploads | /app/static/uploads | Uploaded images, audio, and documents |
./ollama | /root/.ollama | Ollama model weights |
./Servertts/cache_audio | /app/cache_audio | Cached MP3 audio files |
./Servertts/debug_frames | /app/debug_frames | JPEG frames for QR debugging |
Useful Docker Compose Commands
Stop all services without removing volumes:.env values):
.env:
Health Checks
Use these commands to confirm services are responding at the network level:by-qr endpoint for the seeded Cóndor Andino species (replace TU_TTS_API_KEY with your TTS_API_KEY):