Cosa fa#
Quando monti una cartella dell'host dentro un container con -v, i file mantengono i permessi originali dell'host. Se l'utente dentro il container ha un UID diverso dall'utente host, non puo' leggere o scrivere quei file. La soluzione e' creare l'utente nel container con lo stesso UID dell'utente host, a runtime.
TL;DR#
Host (Mac): barno uid=501
Container: node uid=1000
-v ~/.claude:/home/claude/.claude
↑
file di proprieta' uid=501
utente claude (uid=1000) non puo' leggerli
→ Permission deniedSoluzione: creare l'utente nel container con uid=501 all'avvio.
Il problema — UID mismatch#
I bind mount (-v host:container) montano i file con i permessi originali
dell'host. Il kernel controlla i permessi tramite UID numerici, non nomi utente.
Host:
/Users/barno/.claude/ → uid=501 gid=20
Container (senza fix):
/home/claude/.claude/ → uid=501 gid=20 (stesso UID fisico)
utente claude → uid=1000
→ claude non puo' leggere i file (uid diverso)
Container (con fix):
utente claude creato con uid=501
→ node legge i file (uid coincide)ls -la dentro il container mostra i file come "root" o come un numero
senza nome (es. 501) quando l'UID non corrisponde a nessun utente
nel container. Questo e' il segnale diagnostico principale.
La soluzione — entrypoint dinamico#
Invece di fissare l'UID nel Dockerfile, l'utente viene creato a runtime dall'entrypoint con l'UID passato come variabile d'ambiente:
# docker run passa il proprio UID
docker run -e DEFAULT_UID=$(id -u) ...
# sul Mac: DEFAULT_UID=501L'entrypoint riceve DEFAULT_UID=501 e crea l'utente con quell'UID:
entrypoint:
1. riceve DEFAULT_UID=501
2. crea gruppo "node"
3. crea utente "node" con uid=501
4. sistema i permessi sulla home
5. droppa i privilegi con gosu
6. lancia il processo come utente "node" (uid=501)Risultato: l'utente dentro il container ha lo stesso UID dell'utente host e puo' leggere/scrivere i file montati.
gosu — drop privilegi sicuro#
Il container parte sempre come root (necessario per creare utenti).
gosu permette di droppare i privilegi prima di lanciare il processo:
exec gosu "${USER_ID}:${GROUP_NAME}" "$@"Prima di gosu: processo gira come root (uid=0)
Dopo gosu: processo gira come claude (uid=501)Differenza rispetto a su e sudo:
su → apre una nuova shell (overhead, problemi con segnali)
sudo → mantiene alcune capacita' di root
gosu → exec diretto, nessun processo intermedio, drop pulitoNon girare processi in produzione come root dentro container.
Se il container viene compromesso, l'attaccante ha UID=0 anche sull'host
se il container ha --privileged o volumi critici montati.
Permessi sui file montati — diagnostica#
# Dentro il container — vedi i permessi reali
ls -la /home/claude/.claude/
# Se i file mostrano un numero invece del nome utente:
# -rw-r--r-- 1 501 20 ... file.json
# ↑
# UID 501 non ha un nome in questo container
# → UID mismatch
# Verifica l'UID dell'utente corrente
id
whoami
# Verifica l'UID dei file
stat /home/claude/.claude/settings.jsonPattern completo — struttura file#
progetto/
├── Dockerfile → installa dipendenze + copia entrypoint
├── docker-entrypoint.sh → crea utente dinamico, droppa privilegi
└── ~/.zshrc → funzione shell che passa DEFAULT_UIDFlusso:
~/.zshrc (Mac)
→ docker run -e DEFAULT_UID=$(id -u) ...
↓
docker-entrypoint.sh (dentro container, come root)
→ crea utente con UID corretto
→ chown home
→ exec gosu uid:gid processo
↓
processo gira come utente corretto
→ puo' leggere/scrivere file montatiWarning comuni#
useradd warning: node's uid 501 outside of the UID_MIN 1000 and UID_MAX 60000 range.Innocuo su Debian/Ubuntu — UID 501 e' fuori dal range standard ma funziona. Il range e' una convenzione, non un vincolo tecnico.
useradd: warning: the home directory /home/claude already exists.
useradd: Not copying any file from skel directory into it.Innocuo — la home esiste gia' (dal Dockerfile o dal volume montato).
useradd non sovrascrive i file esistenti.
Scenario Reale Blue Team#
Un analista deve girare uno strumento di analisi (es. Claude Code) in un container per isolare l'accesso al filesystem host. Monta solo le cartelle necessarie con bind mount. Il problema dei permessi e' il primo ostacolo:
# Diagnosi rapida
docker run --rm -it immagine id
# Se uid=0 → gira come root → problema sicurezza
# Se uid=1000 ma file uid=501 → permessi negati
# Fix rapido per test (non produzione)
docker run --user $(id -u):$(id -g) ...
# Fix corretto (produzione)
→ entrypoint dinamico con gosuCollegato a#
- system — categoria
- iam — categoria
- docker-security — sicurezza container, principio minimo privilegio
- docker-volumes — bind mount e volumi
- docker-overview — modello mentale container


