Spaces:
Runtime error
Runtime error
chore(infra): contenedores, despliegue y scripts de arranque local
Browse filesAñade Dockerfiles de backend y UI, docker-compose, render.yaml para el despliegue gratuito y los scripts PowerShell de arranque local sin Docker (run_backend, run_ui, dev) que usan 'python -m uvicorn' para evitar los shims .exe bloqueados por OneDrive. Incluye placeholders de models/ y sample_data/.
- backend/Dockerfile +23 -0
- docker-compose.yml +32 -0
- frontend/Dockerfile +13 -0
- models/.gitkeep +2 -0
- render.yaml +16 -0
- sample_data/README.md +7 -0
- scripts/dev.ps1 +8 -0
- scripts/run_backend.ps1 +11 -0
- scripts/run_ui.ps1 +9 -0
backend/Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Imagen del backend FastAPI del MVP (CPU).
|
| 2 |
+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
|
| 3 |
+
|
| 4 |
+
WORKDIR /app
|
| 5 |
+
|
| 6 |
+
# Instalar dependencias de producción desde el manifiesto
|
| 7 |
+
COPY pyproject.toml ./
|
| 8 |
+
RUN uv sync --no-dev
|
| 9 |
+
|
| 10 |
+
COPY backend/ ./backend/
|
| 11 |
+
|
| 12 |
+
# Para ACTIVAR el conteo: descargar el modelo desde Hugging Face Hub en el build.
|
| 13 |
+
# (Mientras COUNTING_ENABLED=false el backend funciona en standby y no requiere modelo.)
|
| 14 |
+
# ARG MODEL_VERSION=2.0.0
|
| 15 |
+
# RUN uv run python -c "from huggingface_hub import hf_hub_download; \
|
| 16 |
+
# hf_hub_download(repo_id='<org>/agrovision-plantcount', \
|
| 17 |
+
# filename='agrovision-plantcount-v${MODEL_VERSION}.onnx', local_dir='/app/models')"
|
| 18 |
+
|
| 19 |
+
ENV COUNTING_ENABLED=false
|
| 20 |
+
ENV MODEL_PATH=/app/models/agrovision-plantcount-v2.0.0.onnx
|
| 21 |
+
ENV MODEL_VERSION=2.0.0
|
| 22 |
+
EXPOSE 8000
|
| 23 |
+
CMD ["uv", "run", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Stack local del MVP: backend FastAPI (api) + UI Shiny (ui).
|
| 2 |
+
# El conteo arranca en standby (COUNTING_ENABLED=false); la app levanta igual.
|
| 3 |
+
services:
|
| 4 |
+
api:
|
| 5 |
+
build:
|
| 6 |
+
context: .
|
| 7 |
+
dockerfile: backend/Dockerfile
|
| 8 |
+
ports:
|
| 9 |
+
- "8000:8000"
|
| 10 |
+
environment:
|
| 11 |
+
- COUNTING_ENABLED=false
|
| 12 |
+
- ALLOWED_ORIGINS=http://localhost:8001
|
| 13 |
+
volumes:
|
| 14 |
+
- ./models:/app/models:ro
|
| 15 |
+
- ./sample_data:/app/sample_data:ro
|
| 16 |
+
healthcheck:
|
| 17 |
+
test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/api/status')\""]
|
| 18 |
+
interval: 10s
|
| 19 |
+
timeout: 5s
|
| 20 |
+
retries: 5
|
| 21 |
+
|
| 22 |
+
ui:
|
| 23 |
+
build:
|
| 24 |
+
context: .
|
| 25 |
+
dockerfile: frontend/Dockerfile
|
| 26 |
+
ports:
|
| 27 |
+
- "8001:8001"
|
| 28 |
+
environment:
|
| 29 |
+
- API_BASE_URL=http://api:8000
|
| 30 |
+
depends_on:
|
| 31 |
+
api:
|
| 32 |
+
condition: service_healthy
|
frontend/Dockerfile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Imagen de la UI Shiny for Python del MVP.
|
| 2 |
+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
|
| 3 |
+
|
| 4 |
+
WORKDIR /app
|
| 5 |
+
|
| 6 |
+
COPY pyproject.toml ./
|
| 7 |
+
RUN uv sync --no-dev
|
| 8 |
+
|
| 9 |
+
COPY frontend/ ./frontend/
|
| 10 |
+
|
| 11 |
+
ENV API_BASE_URL=http://localhost:8000
|
| 12 |
+
EXPOSE 8001
|
| 13 |
+
CMD ["uv", "run", "shiny", "run", "frontend/app.py", "--host", "0.0.0.0", "--port", "8001"]
|
models/.gitkeep
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Carpeta para el artefacto del modelo (agrovision-plantcount-*.onnx).
|
| 2 |
+
# Los pesos NO se versionan: se descargan de Hugging Face Hub en el build.
|
render.yaml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Despliegue del backend del MVP en Render (capa gratuita).
|
| 2 |
+
# La UI Shiny se despliega aparte en ShinyApps.io (rsconnect deploy shiny ./frontend).
|
| 3 |
+
services:
|
| 4 |
+
- type: web
|
| 5 |
+
name: agrovision-mvp-api
|
| 6 |
+
runtime: docker
|
| 7 |
+
dockerfilePath: ./backend/Dockerfile
|
| 8 |
+
plan: free
|
| 9 |
+
healthCheckPath: /api/status
|
| 10 |
+
envVars:
|
| 11 |
+
- key: COUNTING_ENABLED
|
| 12 |
+
value: "false" # true cuando el modelo esté publicado
|
| 13 |
+
- key: ALLOWED_ORIGINS
|
| 14 |
+
value: https://<tu-app>.shinyapps.io
|
| 15 |
+
- key: MODEL_VERSION
|
| 16 |
+
value: "2.0.0"
|
sample_data/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# sample_data
|
| 2 |
+
|
| 3 |
+
Ortomosaicos de ejemplo para probar el conteo localmente (cuando el módulo deje el modo *standby*).
|
| 4 |
+
|
| 5 |
+
- Las imágenes (`*.png`, `*.jpg`, `*.tif`) **no se versionan** (ver `.gitignore`).
|
| 6 |
+
- Coloca aquí un ortomosaico de arándano de prueba, p. ej. `lote_demo.png`.
|
| 7 |
+
- El conteo se activa con `COUNTING_ENABLED=true` y el modelo publicado en Hugging Face Hub.
|
scripts/dev.ps1
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Arranca backend + UI en ventanas PowerShell separadas (local, sin Docker).
|
| 2 |
+
# Uso: ./scripts/dev.ps1
|
| 3 |
+
Start-Process powershell -ArgumentList "-NoExit", "-File", "`"$PSScriptRoot\run_backend.ps1`""
|
| 4 |
+
Start-Sleep -Seconds 2
|
| 5 |
+
Start-Process powershell -ArgumentList "-NoExit", "-File", "`"$PSScriptRoot\run_ui.ps1`""
|
| 6 |
+
|
| 7 |
+
Write-Host "Backend: http://127.0.0.1:8000/api/status"
|
| 8 |
+
Write-Host "UI Shiny: http://127.0.0.1:8001"
|
scripts/run_backend.ps1
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Levanta el backend FastAPI del MVP en local (sin Docker), en http://127.0.0.1:8000
|
| 2 |
+
Set-Location (Split-Path -Parent $PSScriptRoot)
|
| 3 |
+
|
| 4 |
+
# Entorno virtual fuera de OneDrive (evita errores de hardlink/lock en carpetas sincronizadas)
|
| 5 |
+
$env:UV_PROJECT_ENVIRONMENT = "$env:LOCALAPPDATA\agrovision-venv"
|
| 6 |
+
$env:UV_LINK_MODE = "copy"
|
| 7 |
+
|
| 8 |
+
uv sync
|
| 9 |
+
# Se usa "python -m uvicorn" (no el shim uvicorn.exe) para evitar errores de
|
| 10 |
+
# ejecución en carpetas sincronizadas por OneDrive.
|
| 11 |
+
uv run python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload
|
scripts/run_ui.ps1
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Levanta la UI Shiny del MVP en local (sin Docker), en http://127.0.0.1:8001
|
| 2 |
+
Set-Location (Split-Path -Parent $PSScriptRoot)
|
| 3 |
+
|
| 4 |
+
$env:UV_PROJECT_ENVIRONMENT = "$env:LOCALAPPDATA\agrovision-venv"
|
| 5 |
+
$env:UV_LINK_MODE = "copy"
|
| 6 |
+
|
| 7 |
+
# La app Shiny es ASGI: se sirve con uvicorn (python -m) para evitar el shim
|
| 8 |
+
# shiny.exe, que OneDrive bloquea. Equivale a `shiny run frontend/app.py`.
|
| 9 |
+
uv run python -m uvicorn frontend.app:app --host 127.0.0.1 --port 8001 --reload
|