fix(docker): home dir e cache uv per l'utente non privilegiato (#38.1)

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>
This commit is contained in:
2026-09-21 23:23:31 +02:00
parent 8b43e7a601
commit e10585a071
4 changed files with 44 additions and 5 deletions
+7 -2
View File
@@ -13,8 +13,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
shared-mime-info \ shared-mime-info \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Non-root user the app runs as at runtime. # Non-root user the app runs as at runtime. -m creates a home dir: `uv run`
RUN useradd -u 10001 app # in the CMD below writes its cache under $HOME, and without one it has
# nowhere writable to put it.
RUN useradd -m -u 10001 app
# Independent of $HOME regardless: keeps the cache path explicit and writable
# by the app user even if the home directory assumption ever changes.
ENV UV_CACHE_DIR=/tmp/uv-cache
WORKDIR /app WORKDIR /app
+7 -2
View File
@@ -18,8 +18,13 @@ FROM python:3.11.16-slim AS base
# uv from the official slim image (fast Python package manager). # uv from the official slim image (fast Python package manager).
COPY --from=ghcr.io/astral-sh/uv:0.10.9 /uv /uvx /usr/local/bin/ COPY --from=ghcr.io/astral-sh/uv:0.10.9 /uv /uvx /usr/local/bin/
# Non-root user the app runs as at runtime. # Non-root user the app runs as at runtime. -m creates a home dir: `uv run`
RUN useradd -u 10001 app # in the CMD below writes its cache under $HOME, and without one it has
# nowhere writable to put it.
RUN useradd -m -u 10001 app
# Independent of $HOME regardless: keeps the cache path explicit and writable
# by the app user even if the home directory assumption ever changes.
ENV UV_CACHE_DIR=/tmp/uv-cache
WORKDIR /app WORKDIR /app
+6 -1
View File
@@ -10,7 +10,12 @@ COPY --from=ghcr.io/astral-sh/uv:0.10.9 /uv /usr/local/bin/uv
# Non-root user the app runs as at runtime. Same UID as the server's Dockerfile # Non-root user the app runs as at runtime. Same UID as the server's Dockerfile
# so both containers agree on ownership of the shared uploads volume (point 13). # so both containers agree on ownership of the shared uploads volume (point 13).
RUN useradd -u 10001 app # -m creates a home dir: `uv run` in the CMD below writes its cache under
# $HOME, and without one it has nowhere writable to put it.
RUN useradd -m -u 10001 app
# Independent of $HOME regardless: keeps the cache path explicit and writable
# by the app user even if the home directory assumption ever changes.
ENV UV_CACHE_DIR=/tmp/uv-cache
WORKDIR /app WORKDIR /app
COPY pyproject.toml uv.lock ./ COPY pyproject.toml uv.lock ./
+24
View File
@@ -435,6 +435,30 @@ docker compose -f docker-compose.yml logs -f server
docker compose -f docker-compose.yml down docker compose -f docker-compose.yml down
``` ```
### Aggiornare un'installazione esistente
Le immagini precedenti creavano l'utente non privilegiato senza una home
directory (`useradd -u 10001 app`), e il volume `upload_data` che ne è
risultato appartiene a `root`. Le immagini attuali creano l'utente con
`-m` e impostano `UV_CACHE_DIR=/tmp/uv-cache`, ma questo non cambia da solo
la proprietà di un volume già esistente: se si riparte con le nuove immagini
su un volume creato da una versione precedente, il container `server` non
riesce a scrivere sotto `/app/uploads`.
Prima del primo avvio con le nuove immagini, va quindi corretta la proprietà
del volume:
```bash
docker compose -f docker-compose.yml run --rm --user root --entrypoint chown server -R 10001:10001 /app/uploads
```
(sostituire `docker-compose.yml` con `docker-compose.dev.yml` per
un'installazione di sviluppo/on-premise). Il comando usa il servizio
`server` perché è quello che monta il volume `upload_data` in lettura e
scrittura; il worker di visione lo monta in sola lettura e non ne ha
bisogno. Un'installazione nuova, che parte da un volume vuoto, non richiede
questo passo.
--- ---
## SSL/TLS ## SSL/TLS