In genere, i problemi di autorizzazione con un mount del volume host sono dovuti al fatto che uid / gid all'interno del contenitore non ha accesso al file in base alle autorizzazioni uid / gid del file sull'host. Tuttavia, questo caso specifico è diverso.
Il punto alla fine della stringa di autorizzazione drwxr-xr-x.
, indica che SELinux è configurato. Quando si utilizza un mount host con SELinux, è necessario passare un'opzione aggiuntiva alla fine della definizione del volume:
- L'
z
opzione indica che il contenuto del bind mount è condiviso tra più contenitori.
- L'
Z
opzione indica che il contenuto di bind mount è privato e non condiviso.
Il comando di montaggio del volume sarebbe quindi simile a:
sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash
Per ulteriori informazioni sui supporti host con SELinux, consultare: https://docs.docker.com/storage/#configure-the-selinux-label
Per gli altri che riscontrano questo problema con i contenitori in esecuzione come utente diverso, è necessario assicurarsi che l'uid / gid dell'utente all'interno del contenitore disponga delle autorizzazioni per il file sull'host. Sui server di produzione, ciò avviene spesso controllando uid / gid nel processo di creazione dell'immagine per abbinare un uid / gid sull'host che ha accesso ai file (o, meglio ancora, non utilizzare i montaggi host in produzione).
Un volume con nome è spesso preferito per ospitare i montaggi perché inizializzerà la directory del volume dalla directory delle immagini, inclusi eventuali diritti e proprietà del file. Ciò accade quando il volume è vuoto e il contenitore viene creato con il volume indicato.
Gli utenti MacOS ora hanno OSXFS che gestisce automaticamente gli uid / gid tra l'host Mac e i container. Un posto in cui non aiuta sono i file dall'interno della VM incorporata che vengono montati nel contenitore, come /var/lib/docker.sock.
Per ambienti di sviluppo in cui l'host uid / gid può cambiare per sviluppatore, la mia soluzione preferita è avviare il contenitore con un punto di accesso in esecuzione come root, correggere l'uid / gid dell'utente all'interno del contenitore in modo che corrisponda al volume dell'host uid / gid e quindi utilizzare gosu
per rilasciare dalla radice all'utente del contenitore per eseguire l'applicazione all'interno del contenitore. Lo script importante per questo è fix-perms
nei miei script di immagini di base, che possono essere trovati su: https://github.com/sudo-bmitch/docker-base
La parte importante dello fix-perms
script è:
# update the uid
if [ -n "$opt_u" ]; then
OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
NEW_UID=$(stat -c "%u" "$1")
if [ "$OLD_UID" != "$NEW_UID" ]; then
echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
usermod -u "$NEW_UID" -o "$opt_u"
if [ -n "$opt_r" ]; then
find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
fi
fi
fi
Ciò porta l'UID dell'utente all'interno del contenitore, l'UID del file e, se non corrispondono, chiama usermod
per regolare l'UID. Infine fa una ricerca ricorsiva per riparare tutti i file che non hanno cambiato gli utenti. Mi piace di più rispetto all'esecuzione di un contenitore con un -u $(id -u):$(id -g)
flag perché il codice sopra indicato non richiede che ogni sviluppatore esegua uno script per avviare il contenitore e tutti i file al di fuori del volume di proprietà dell'utente avranno le autorizzazioni corrette.
Puoi anche fare in modo che la finestra mobile inizializzi una directory host da un'immagine usando un volume con nome che esegue un montaggio bind. Questa directory deve esistere in anticipo ed è necessario fornire un percorso assoluto alla directory host, diversamente dai volumi host in un file di composizione che possono essere percorsi relativi. La directory deve anche essere vuota per la finestra mobile per inizializzarla. Tre diverse opzioni per la definizione di un volume con nome in un montaggio bind sono:
# create the volume in advance
$ docker volume create --driver local \
--opt type=none \
--opt device=/home/user/test \
--opt o=bind \
test_vol
# create on the fly with --mount
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
foo
# inside a docker-compose file
...
volumes:
bind-test:
driver: local
driver_opts:
type: none
o: bind
device: /home/user/test
...
Infine, se provi a utilizzare gli spazi dei nomi utente, scoprirai che i volumi host hanno problemi di autorizzazione perché gli uid / gid dei container vengono spostati. In quello scenario, è probabilmente più semplice evitare i volumi host e usare solo i volumi con nome.