En règle générale, les problèmes d'autorisations avec un montage de volume hôte sont dus au fait que l'uid / gid à l'intérieur du conteneur n'a pas accès au fichier conformément aux autorisations uid / gid du fichier sur l'hôte. Cependant, ce cas spécifique est différent.
Le point à la fin de la chaîne d'autorisation drwxr-xr-x.
, indique que SELinux est configuré. Lorsque vous utilisez un montage hôte avec SELinux, vous devez passer une option supplémentaire à la fin de la définition du volume:
- L'
z
option indique que le contenu du montage de liaison est partagé entre plusieurs conteneurs.
- L'
Z
option indique que le contenu du montage de liaison est privé et non partagé.
Votre commande de montage de volume ressemblerait alors à:
sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash
En savoir plus sur les montages d'hôte avec SELinux sur: https://docs.docker.com/storage/#configure-the-selinux-label
Pour d'autres qui voient ce problème avec les conteneurs s'exécutant en tant qu'utilisateur différent, vous devez vous assurer que l'uid / gid de l'utilisateur à l'intérieur du conteneur dispose des autorisations sur le fichier sur l'hôte. Sur les serveurs de production, cela se fait souvent en contrôlant l'uid / gid dans le processus de création d'image pour faire correspondre un uid / gid sur l'hôte qui a accès aux fichiers (ou mieux encore, n'utilisez pas de montages d'hôte en production).
Un volume nommé est souvent préféré pour héberger des montages car il initialise le répertoire de volume à partir du répertoire d'image, y compris toute propriété de fichier et autorisations. Cela se produit lorsque le volume est vide et que le conteneur est créé avec le volume nommé.
Les utilisateurs de MacOS ont maintenant OSXFS qui gère automatiquement les uid / gid entre l'hôte Mac et les conteneurs. Les fichiers de l'intérieur de la machine virtuelle intégrée qui sont montés dans le conteneur, comme /var/lib/docker.sock, ne sont pas utiles.
Pour les environnements de développement où l'uid / gid de l'hôte peut changer par développeur, ma solution préférée est de démarrer le conteneur avec un point d'entrée s'exécutant en tant que root, de corriger l'uid / gid de l'utilisateur à l'intérieur du conteneur pour correspondre au uid / gid du volume de l'hôte, et puis utilisez gosu
pour passer de la racine à l'utilisateur du conteneur pour exécuter l'application à l'intérieur du conteneur. Le script important pour cela est fix-perms
dans mes scripts d'image de base, qui peuvent être trouvés à: https://github.com/sudo-bmitch/docker-base
Le bit important du fix-perms
script est:
# 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
Cela obtient l'uid de l'utilisateur à l'intérieur du conteneur, et l'uid du fichier, et s'ils ne correspondent pas, appelle usermod
pour ajuster l'uid. Enfin, il effectue une recherche récursive pour corriger tous les fichiers qui n'ont pas changé d'uid. J'aime mieux que d'exécuter un conteneur avec un -u $(id -u):$(id -g)
indicateur, car le code de point d'entrée ci-dessus ne nécessite pas que chaque développeur exécute un script pour démarrer le conteneur, et tous les fichiers en dehors du volume appartenant à l'utilisateur verront leurs autorisations corrigées.
Vous pouvez également demander à docker d'initialiser un répertoire hôte à partir d'une image en utilisant un volume nommé qui effectue un montage de liaison. Ce répertoire doit exister à l'avance et vous devez fournir un chemin absolu vers le répertoire hôte, contrairement aux volumes hôtes dans un fichier de composition qui peuvent être des chemins relatifs. Le répertoire doit également être vide pour que docker l'initialise. Trois options différentes pour définir un volume nommé sur un montage de liaison ressemblent à:
# 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
...
Enfin, si vous essayez d'utiliser des espaces de noms d'utilisateurs, vous constaterez que les volumes hôtes ont des problèmes d'autorisation car les uid / gid des conteneurs sont décalés. Dans ce scénario, il est probablement plus facile d'éviter les volumes hôtes et de n'utiliser que les volumes nommés.