useradd senza -m lascia l'utente app senza $HOME: uv run nel CMD non
trova dove scrivere la sua cache. Aggiunto -m a useradd in Dockerfile,
Dockerfile.frontend e Dockerfile.vision, e UV_CACHE_DIR=/tmp/uv-cache
esplicito (indipendente da $HOME). docs/DEPLOYMENT.md: nuova sezione
sull'aggiornamento di un'installazione esistente, con il chown del
volume upload_data ereditato da versioni precedenti.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Punto 1: useradd -u 10001 app, chown /app (+ /app/uploads sul server),
USER app in tutti e tre i Dockerfile. Stesso UID sul server e sul worker
di visione, che condividono il volume uploads in sola lettura (punto 13).
Punto 2: python:3.11.16-slim (server, client), python:3.13.15-slim
(vision), ghcr.io/astral-sh/uv:0.10.9 (versione locale di `uv --version`).
Dockerfile.frontend: TailwindCSS ora si compila in uno stage separato
dall'immagine ufficiale node:20.20.2-bookworm-slim, non più con
`curl | bash` su nodesource nell'immagine finale.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Un build senza la variabile produceva un'immagine che partiva e
rispondeva "healthy" pur fallendo ogni richiesta, /health incluso: non
c'era un healthcheck a dirlo. Tre correzioni: RUN test -n
"$VISION_ENGINE_VERSION" in Dockerfile.vision dopo l'ARG, fallisce
subito con il comando da lanciare; healthcheck su /health nel servizio
vision di entrambi i compose; VISION_ENGINE_VERSION documentata in
.env.example accanto a VISION_WORKER_URL, che già c'era.
Verificato con docker build reale: senza la variabile fallisce al passo
del test con il messaggio atteso; con la variabile impostata l'immagine
si costruisce, il container parte, e python3 -c
"urllib.request.urlopen('http://localhost:8100/health')" - lo stesso
comando usato nell'healthcheck - risponde 200 con l'engine_version
giusta.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
Ruling R9: separa l'extra vision (runner: 4 pacchetti VisionSuite + numpy)
da vision-worker (fastapi, uvicorn, pillow, python-multipart, sopra vision).
Prima il worker risolveva solo perche' vs-pm2d le lista per conto suo; un
domani lo stub di stazione dovra' incorporare il runner senza trascinarsi
dietro un server web che non gli serve.
Aggiorna Dockerfile.vision e README.md al nuovo extra; il test del worker ora
pinna anche il valore numerico del diametro (non solo la chiave), agganciato
alla stessa tolleranza del test in-process del runner.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
Container FastAPI separato (Dockerfile.vision, python:3.13-slim) che
espone run_graph/engine_version del Task 2 via POST /run e GET /health,
cosi' l'immagine del server principale non importa mai VisionSuite.
engine_version() ora legge VISION_ENGINE_VERSION se impostata, altrimenti
ricade su git rev-parse nel checkout di sviluppo, e non inventa mai un
valore: senza nessuna delle due solleva un errore esplicito. Nel container
il fallback a git non puo' funzionare (.git del submodule punta fuori dal
build context), quindi Dockerfile.vision prende il commit come build arg
e lo fissa in ambiente; i compose file lo passano da VISION_ENGINE_VERSION.
Nessuna porta pubblicata e nessuna label Traefik sul servizio vision: e'
raggiungibile solo dal server, su tmflow-net.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU