Introduction
Docker est une plateforme de conteneurisation puissante qui permet aux développeurs d'empaqueter et de déployer des applications facilement. Un problème courant rencontré par les utilisateurs est l'erreur "permission denied" (permission refusée) lors du montage de volumes dans Docker. Cette erreur se produit lorsque le conteneur n'a pas les permissions appropriées pour accéder aux fichiers ou aux répertoires sur la machine hôte.
Dans ce lab, vous apprendrez à identifier, dépanner et résoudre les erreurs de permission refusée lorsque vous travaillez avec les volumes Docker. À la fin de ce tutoriel, vous comprendrez comment fonctionnent les volumes Docker, comment les permissions les affectent et les meilleures pratiques pour configurer les volumes avec les permissions correctes.
Comprendre les Volumes Docker
Les volumes Docker sont un mécanisme permettant de persister les données générées et utilisées par les conteneurs Docker. Ils vous permettent de stocker des données indépendamment du cycle de vie du conteneur, ce qui facilite la sauvegarde, le partage et la gestion des données de votre application.
Commençons par explorer les volumes Docker et créer un volume de base pour comprendre comment ils fonctionnent.
Que sont les Volumes Docker ?
Les volumes Docker servent plusieurs objectifs importants :
- Ils persistent les données même lorsque les conteneurs sont supprimés
- Ils permettent le partage de données entre les conteneurs
- Ils séparent la gestion du stockage de la gestion des conteneurs
- Ils offrent de meilleures performances que l'écriture dans la couche accessible en écriture du conteneur
Création et Gestion des Volumes Docker
Tout d'abord, créons un volume Docker simple :
docker volume create my_volume
Pour lister tous les volumes :
docker volume ls
Vous devriez voir une sortie similaire à :
DRIVER VOLUME NAME
local my_volume
Inspectons notre volume nouvellement créé pour voir où il est stocké sur la machine hôte :
docker volume inspect my_volume
La sortie affichera les détails du volume :
[
{
"CreatedAt": "2023-XX-XX....",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my_volume/_data",
"Name": "my_volume",
"Options": {},
"Scope": "local"
}
]
Le Mountpoint (point de montage) est l'endroit où Docker stocke les données du volume sur le système hôte.
Test du Montage de Volume
Exécutons un conteneur qui monte notre volume et y écrit des données :
docker run --rm -v my_volume:/data alpine sh -c "echo 'Hello from Docker!' > /data/test.txt"
Cette commande :
- Crée un conteneur Alpine Linux temporaire avec l'option
--rm(il sera supprimé à la sortie) - Monte notre
my_volumedans le répertoire/dataà l'intérieur du conteneur - Écrit "Hello from Docker!" dans un fichier nommé
test.txtdans le volume
Maintenant, vérifions que les données persistent en les lisant à partir d'un autre conteneur :
docker run --rm -v my_volume:/data alpine cat /data/test.txt
Vous devriez voir :
Hello from Docker!
Cela démontre comment les volumes Docker persistent les données à travers différents conteneurs.
Création d'un Scénario de Permission Refusée
Maintenant que nous comprenons l'utilisation de base des volumes Docker, créons un scénario qui produit l'erreur "permission denied" (permission refusée). Cela nous aidera à comprendre ce qui cause le problème et comment le résoudre.
Configuration d'un Répertoire de Test
Tout d'abord, créons un répertoire sur la machine hôte et un fichier avec des permissions spécifiques :
mkdir -p ~/project/docker-test
echo "This is a test file." > ~/project/docker-test/testfile.txt
chmod 700 ~/project/docker-test/testfile.txt
Ces commandes :
- Créent un répertoire appelé
docker-testdans votre dossier de projet - Créent un fichier de test avec du contenu
- Définissent les permissions sur le fichier pour qu'il soit lisible, accessible en écriture et exécutable uniquement par le propriétaire (vous)
Vérifions les permissions du fichier :
ls -la ~/project/docker-test/
Vous devriez voir une sortie similaire à :
total 12
drwxr-xr-x 2 labex labex 4096 XXX XX XX:XX .
drwxr-xr-x X labex labex 4096 XXX XX XX:XX ..
-rwx------ 1 labex labex 19 XXX XX XX:XX testfile.txt
Notez que les permissions du fichier sont définies sur 700 (-rwx------), ce qui signifie que seul le propriétaire (vous) peut lire, écrire ou exécuter le fichier.
Rencontre de l'Erreur de Permission Refusée
Maintenant, essayons d'accéder à ce fichier depuis un conteneur Docker :
docker run --rm -v ~/project/docker-test:/app ubuntu cat /app/testfile.txt
Vous devriez voir un message d'erreur similaire à :
cat: /app/testfile.txt: Permission denied
Cela est dû au fait que les conteneurs Docker, par défaut, s'exécutent en tant qu'utilisateur root à l'intérieur du conteneur, mais cet utilisateur root ne correspond pas au même ID utilisateur que votre utilisateur hôte. Lorsque Docker monte un répertoire hôte, les vérifications de permission sont toujours appliquées en fonction des permissions de fichier et des ID utilisateur d'origine.
Comprendre le Problème
L'erreur de permission refusée se produit parce que :
- Le fichier sur votre hôte appartient à votre utilisateur (labex)
- Le fichier a des permissions définies sur 700 (seul le propriétaire peut y accéder)
- Le conteneur Docker s'exécute avec un ID utilisateur différent (généralement root, qui est UID 0)
- Même si l'utilisateur du conteneur est "root", il n'a pas les mêmes privilèges que l'utilisateur root de l'hôte lors de l'accès aux volumes montés
Vérifions les ID utilisateur pour mieux comprendre cela :
echo "Host user ID: $(id -u)"
docker run --rm ubuntu bash -c "echo Container user ID: \$(id -u)"
Cela montre que bien que vous vous exécutiez avec votre ID utilisateur sur l'hôte (probablement 1000), le conteneur s'exécute avec l'ID utilisateur 0 (root). Bien qu'étant "root" à l'intérieur du conteneur, lors de l'accès aux fichiers montés sur l'hôte, l'utilisateur root du conteneur est toujours soumis aux vérifications de permission de l'hôte.
Résolution des Erreurs de Permission Refusée
Maintenant que nous comprenons la cause de l'erreur de permission refusée, explorons plusieurs méthodes pour la résoudre.
Méthode 1 : Modification des Permissions de Fichier sur l'Hôte
L'approche la plus simple consiste à modifier les permissions des fichiers sur votre hôte pour permettre à d'autres utilisateurs d'y accéder :
chmod 755 ~/project/docker-test/testfile.txt
Cela modifie les permissions en 755 (-rwxr-xr-x), permettant à quiconque de lire et d'exécuter le fichier, mais seul le propriétaire peut le modifier.
Essayons d'accéder à nouveau au fichier depuis un conteneur :
docker run --rm -v ~/project/docker-test:/app ubuntu cat /app/testfile.txt
Vous devriez maintenant voir le contenu du fichier :
This is a test file.
Cela fonctionne car le fichier est maintenant lisible par "others" (autres) sur votre système hôte, ce qui inclut l'utilisateur du conteneur.
Méthode 2 : Utilisation du Flag --user
Une autre approche consiste à demander à Docker d'exécuter le conteneur avec le même ID utilisateur que votre utilisateur hôte :
## Reset the file permissions to be restrictive
chmod 700 ~/project/docker-test/testfile.txt
## Get your user ID and group ID
USER_ID=$(id -u)
GROUP_ID=$(id -g)
## Run the container with your user ID
docker run --rm --user $USER_ID:$GROUP_ID -v ~/project/docker-test:/app ubuntu cat /app/testfile.txt
Vous devriez maintenant être en mesure de lire le contenu du fichier malgré ses permissions restrictives :
This is a test file.
Cela fonctionne parce que :
- Nous exécutons le conteneur avec le même ID utilisateur que votre utilisateur hôte
- Les permissions sur le fichier permettent l'accès à cet ID utilisateur
- Docker transmet l'ID utilisateur aux processus du conteneur
Le flag --user est particulièrement utile lorsque vous devez maintenir des permissions restrictives sur vos fichiers hôtes.
Méthode 3 : Ajustement des ID de Propriétaire et de Groupe
Créons un nouveau fichier appartenant à un utilisateur différent pour démontrer cette méthode :
## Create a file as root
sudo bash -c 'echo "This is a root-owned file." > ~/project/docker-test/rootfile.txt'
sudo chown root:root ~/project/docker-test/rootfile.txt
sudo chmod 600 ~/project/docker-test/rootfile.txt
## Let's see what we have
ls -la ~/project/docker-test/
La sortie devrait montrer :
total 16
drwxr-xr-x 2 labex labex 4096 XXX XX XX:XX .
drwxr-xr-x X labex labex 4096 XXX XX XX:XX ..
-rw------- 1 root root 25 XXX XX XX:XX rootfile.txt
-rwx------ 1 labex labex 19 XXX XX XX:XX testfile.txt
Maintenant, essayez d'accéder au fichier appartenant à root depuis un conteneur s'exécutant en tant que root :
docker run --rm -v ~/project/docker-test:/app ubuntu cat /app/rootfile.txt
Vous devriez voir le contenu :
This is a root-owned file.
Cela fonctionne parce que :
- Le conteneur s'exécute en tant que root (UID 0) par défaut
- Le fichier appartient à root (UID 0) sur l'hôte
- Les permissions (600) permettent au propriétaire de lire le fichier
Cela démontre que les ID utilisateur réels sont importants, et pas seulement les noms. Lorsque l'ID utilisateur du conteneur correspond à l'ID du propriétaire du fichier, les vérifications de permission réussissent si le propriétaire dispose des permissions nécessaires.
Bonnes Pratiques pour les Permissions des Volumes Docker
Maintenant que nous comprenons comment résoudre les problèmes de permission, discutons de quelques bonnes pratiques pour configurer les volumes Docker avec des permissions appropriées.
Utilisation des Volumes Nommés
Les volumes nommés sont gérés par Docker et ont généralement une meilleure gestion des permissions que les montages de liaison (bind mounts). Créons un volume nommé et voyons comment il se comporte :
## Create a named volume
docker volume create data_volume
## Write to the volume as root in a container
docker run --rm -v data_volume:/data ubuntu bash -c "echo 'Created by root user' > /data/rootfile.txt && ls -la /data"
## Read from the volume as a non-root user
docker run --rm --user 1000:1000 -v data_volume:/data ubuntu cat /data/rootfile.txt
Vous remarquerez que les deux opérations fonctionnent sans problèmes de permission. Cela est dû au fait que Docker gère les permissions différemment pour les volumes nommés que pour les montages de liaison.
Création d'un Environnement de Développement Cohérent
Pour les environnements de développement, il est souvent utile de configurer un ID utilisateur cohérent entre votre hôte et le conteneur :
## Create a Dockerfile for a development container
mkdir -p ~/project/dev-container
cat > ~/project/dev-container/Dockerfile << EOF
FROM ubuntu:22.04
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN apt-get update && apt-get install -y sudo
## Create a non-root user with the same ID as the host user
RUN groupadd -g \${GROUP_ID} developer && \\
useradd -u \${USER_ID} -g \${GROUP_ID} -m -s /bin/bash developer && \\
echo "developer ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/developer
USER developer
WORKDIR /home/developer
CMD ["bash"]
EOF
## Build the development container
cd ~/project/dev-container
docker build -t dev-container .
Maintenant, vous pouvez exécuter ce conteneur avec votre répertoire hôte monté :
docker run --rm -it -v ~/project/docker-test:/home/developer/project dev-container bash
À l'intérieur du conteneur, essayez d'accéder aux fichiers :
ls -la ~/project
cat ~/project/testfile.txt
Cela fonctionne parce que :
- L'utilisateur du conteneur a le même UID que votre utilisateur hôte
- Les permissions du fichier permettent l'accès à cet UID
- Le répertoire monté conserve la même propriété et les mêmes permissions
Utilisation de Docker Compose pour des Configurations de Volume Cohérentes
Pour les applications plus complexes, Docker Compose peut aider à maintenir des configurations de volume cohérentes. Créons un simple fichier Docker Compose :
mkdir -p ~/project/compose-test
cat > ~/project/compose-test/docker-compose.yml << EOF
version: '3'
services:
app:
image: ubuntu
user: "\${UID}:\${GID}"
volumes:
- ./data:/app/data
command: ["bash", "-c", "echo 'Running as user \$(id -u):\$(id -g)' > /app/data/output.txt && cat /app/data/output.txt"]
volumes:
app_data:
EOF
## Create the data directory
mkdir -p ~/project/compose-test/data
## Run with your user ID
cd ~/project/compose-test
UID=$(id -u) GID=$(id -g) docker compose up
Cette approche :
- Utilise des variables d'environnement pour passer votre ID utilisateur et votre ID de groupe à Docker Compose
- Configure le conteneur pour qu'il s'exécute avec votre ID utilisateur
- Monte un répertoire local qui est accessible par votre utilisateur
Après l'exécution, vérifiez le fichier de sortie :
cat ~/project/compose-test/data/output.txt
Vous devriez voir :
Running as user 1000:1000
Cela confirme que le conteneur s'est exécuté avec votre ID utilisateur et avait les permissions appropriées pour écrire dans le volume monté.
Résumé
Dans ce lab, vous avez appris à identifier, dépanner et résoudre l'erreur "permission denied" (permission refusée) lors du montage de volumes dans Docker. Les points clés abordés incluent :
- Comprendre le fonctionnement des volumes Docker et leurs avantages pour la persistance des données
- Identifier les problèmes de permission lors du montage de répertoires hôtes en tant que volumes
- Résoudre les erreurs de permission en utilisant plusieurs techniques :
- Ajuster les permissions de fichiers sur l'hôte
- Exécuter des conteneurs avec des ID utilisateur spécifiques
- Gérer la propriété des fichiers et des répertoires
- Bonnes pratiques pour configurer les volumes Docker avec des permissions appropriées :
- Utiliser des volumes nommés pour une meilleure gestion des permissions
- Créer des environnements de développement cohérents avec des ID utilisateur correspondants
- Utiliser Docker Compose pour des configurations de volume complexes
Ces compétences sont essentielles pour travailler avec Docker dans des scénarios réels où la persistance des données et la gestion appropriée des permissions sont critiques. En comprenant comment Docker gère les permissions pour les volumes montés, vous pouvez éviter les problèmes courants et créer des applications conteneurisées plus robustes.



