[{"data":1,"prerenderedAt":178},["ShallowReactive",2],{"seo-verification":3,"blog-docker-volume-permissions-self-hosted-vps-fr":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-docker-volume-permissions-self-hosted-vps-fr",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":135,"ctaBody":136,"ctaButton":137,"ctaUrl":138,"relatedPosts":139},395,"docker-volume-permissions-self-hosted-vps",{"fr":10,"en":12,"ar":13,"es":14},"docker-volume-permissions-vps","اذونات-مجلدات-docker-vps","permisos-volumenes-docker-vps","Docker volumes : corriger les permissions en 3 commandes","Permission denied dans vos logs Docker ? Comprenez le mécanisme UID\u002FGID et corrigez les permissions de volumes sans jamais élever les privilèges.",10,0,false,"2026-09-28T00:00:00+00:00","2026-09-29T14:40:42+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},3,"Déploiement","deploiement","bg-success\u002F10 text-success",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdocker-volume-permissions-self-hosted-vps-poster.svg","L'application démarre, le conteneur tourne, mais les logs affichent `Permission denied` et rien ne se sauvegarde. Ce problème touche la quasi-totalité des applications self-hostées dès que vous montez un répertoire hôte dans Docker. La cause est toujours la même : l'UID de l'utilisateur qui tourne à l'intérieur du conteneur ne correspond pas au propriétaire du répertoire sur l'hôte. Ce guide explique le mécanisme, donne les commandes de diagnostic et propose les corrections adaptées à chaque cas — sans jamais faire tourner vos conteneurs en root.",[34,38,41,49,52,70,73,90,93,96,120,123,129,132],{"type":35,"title":36,"body":37},"h2","Le mécanisme : pourquoi Docker refuse d'écrire","Docker partage le noyau Linux de l'hôte. Il n'existe pas de couche de virtualisation des utilisateurs : chaque processus dans un conteneur possède un UID et un GID réels, visibles depuis l'hôte. Quand un conteneur monte un répertoire hôte (`bind-mount`), le système de fichiers ne fait aucune magie : il applique les mêmes règles de permissions POSIX que pour n'importe quel processus local. Un fichier appartenant à l'UID 1000 sur l'hôte reste la propriété de l'UID 1000, peu importe que ce soit un utilisateur qui s'appelle `alice` côté hôte ou `paperless` côté conteneur. Si le processus dans le conteneur tourne sous l'UID 472 et que le répertoire appartient à root (UID 0), l'écriture est refusée — même si vous avez utilisé `chmod 755`.\n\nPourquoi les images n'utilisent-elles pas root par défaut ? La majorité des images Docker bien maintenues créent un utilisateur applicatif dédié pour respecter le principe de moindre privilège : un processus compromis ne peut pas modifier les binaires système du conteneur ni, si les options de sécurité sont correctes, accéder aux fichiers root de l'hôte. C'est une bonne pratique — mais elle introduit précisément ce décalage d'UID.\n\nLe piège classique : vous créez le répertoire avec votre session SSH (UID 1000), puis vous lancez un conteneur Grafana qui tourne en UID 472. Grafana tente d'écrire sa base SQLite dans `\u002Fvar\u002Flib\u002Fgrafana` monté depuis `\u002Fopt\u002Fgrafana\u002Fdata` — qui appartient à votre utilisateur SSH. Résultat : `GF_PATHS_DATA='\u002Fvar\u002Flib\u002Fgrafana' is not writable.` Le conteneur démarre, répond sur le port 3000, mais toute configuration est perdue au redémarrage suivant car rien n'a jamais été écrit sur le disque.",{"type":35,"title":39,"body":40},"Les applications les plus touchées et leur UID","Les problèmes de permissions Docker touchent principalement les applications qui s'exécutent avec un UID spécifique différent de celui de l'hôte.",{"type":42,"items":43},"ul",[44,45,46,47,48],"**Paperless-ngx** — UID `1000` (utilisateur `paperless`) : gère les répertoires `consume`, `export`, `media` et `data`","**Grafana** — UID `472` (utilisateur `grafana`) : écrit sa base SQLite et ses plugins dans `\u002Fvar\u002Flib\u002Fgrafana`","**Nextcloud** (image Debian) — UID `33` (utilisateur `www-data`) : répertoire de données, config et logs","**Immich** — UID `1000` (utilisateur `node`) : librairie photos, miniatures et base de données ML","**Gitea** — UID `1000` (utilisateur `git`) : dépôts, SSH keys, logs et base SQLite par défaut",{"type":35,"title":50,"body":51},"Diagnostic : identifier le problème en moins de 2 minutes","Avant de corriger, confirmez que c'est bien un problème de permissions et identifiez l'UID en cause. Trois commandes suffisent.",{"type":53,"steps":54},"steps",[55,58,61,64,67],{"title":56,"body":57},"Lire le message d'erreur exact","Consultez les logs du conteneur incriminé :\n```\ndocker logs \u003Cnom-du-conteneur> 2>&1 | grep -i 'permission\\|denied\\|cannot\\|mkdir'\n```\nUn message `permission denied` ou `cannot create directory` confirme le diagnostic.",{"title":59,"body":60},"Identifier l'UID du processus dans le conteneur","```\ndocker exec \u003Cnom-du-conteneur> id\n```\nSortie typique : `uid=472(grafana) gid=0(root)`. Notez l'UID — ici `472`.",{"title":62,"body":63},"Vérifier le propriétaire du répertoire hôte","```\nls -ln \u002Fopt\u002Fgrafana\u002Fdata\n```\nLa sortie `drwxr-xr-x 2 0 0 ...` indique que le répertoire appartient à root (UID 0). L'UID 472 n'a que les droits « other » — lecture et exécution, pas d'écriture.",{"title":65,"body":66},"Vérifier avec stat pour un diagnostic complet","```\nstat \u002Fopt\u002Fgrafana\u002Fdata\n```\nRegardez les lignes `Uid:` et `Gid:`. Si elles affichent `(0\u002Froot)` alors que votre conteneur tourne en 472, le problème est confirmé.",{"title":68,"body":69},"Inspecter la configuration du conteneur","```\ndocker inspect \u003Cnom-du-conteneur> | grep -A5 'Mounts'\n```\nCette commande liste tous les bind-mounts et volumes nommés actifs, avec leur source sur l'hôte et leur destination dans le conteneur.",{"type":35,"title":71,"body":72},"Correction cas par cas : chown sur le répertoire hôte","La correction de base est un `chown` du répertoire hôte vers l'UID attendu par le conteneur. Voici les commandes pour les applications les plus courantes.",{"type":53,"steps":74},[75,78,81,84,87],{"title":76,"body":77},"Grafana (UID 472)","```\nmkdir -p \u002Fopt\u002Fgrafana\u002Fdata\nchown -R 472:472 \u002Fopt\u002Fgrafana\u002Fdata\n```\nDans votre `compose.yml` :\n```yaml\nvolumes:\n  - \u002Fopt\u002Fgrafana\u002Fdata:\u002Fvar\u002Flib\u002Fgrafana\n```",{"title":79,"body":80},"Nextcloud (UID 33, image Debian)","```\nmkdir -p \u002Fopt\u002Fnextcloud\u002F{data,config,apps}\nchown -R 33:33 \u002Fopt\u002Fnextcloud\u002Fdata\nchown -R 33:33 \u002Fopt\u002Fnextcloud\u002Fconfig\n```\nAttention : l'image Alpine utilise l'UID 82. Vérifiez avec `docker exec \u003Cconteneur> id www-data` si vous n'êtes pas sûr de la variante utilisée.",{"title":82,"body":83},"Paperless-ngx (UID 1000)","```\nmkdir -p \u002Fopt\u002Fpaperless\u002F{consume,export,media,data}\nchown -R 1000:1000 \u002Fopt\u002Fpaperless\u002Fconsume\nchown -R 1000:1000 \u002Fopt\u002Fpaperless\u002Fexport\nchown -R 1000:1000 \u002Fopt\u002Fpaperless\u002Fmedia\nchown -R 1000:1000 \u002Fopt\u002Fpaperless\u002Fdata\n```",{"title":85,"body":86},"Immich (UID 1000)","```\nmkdir -p \u002Fopt\u002Fimmich\u002F{library,thumbnails,encoded-video,profile}\nchown -R 1000:1000 \u002Fopt\u002Fimmich\n```\nNote : les variables d'environnement `PUID`\u002F`PGID` ne fonctionnent PAS avec les images officielles Immich. Elles sont spécifiques aux images LinuxServer.io.",{"title":88,"body":89},"Vérifier après correction","```\nls -ln \u002Fopt\u002Fgrafana\u002Fdata\n```\nDoit afficher `drwxr-xr-x 2 472 472 ...`. Redémarrez ensuite le conteneur :\n```\ndocker compose restart grafana\ndocker logs grafana --tail 20\n```",{"type":35,"title":91,"body":92},"Variantes selon l'app : bind-mounts, volumes nommés et user:","Le `chown` sur le répertoire hôte fonctionne pour les bind-mounts, mais Docker propose trois autres approches selon le contexte et l'image utilisée.\n\n**Directive `user:` dans compose.yml.** Certaines images sont conçues pour accepter un UID arbitraire passé via `user:`. Cela évite le `chown` si votre répertoire appartient à votre utilisateur hôte :\n```yaml\nservices:\n  app:\n    image: mon-image\n    user: \"1000:1000\"\n    volumes:\n      - \u002Fhome\u002Fuser\u002Fdata:\u002Fapp\u002Fdata\n```\nCette approche fonctionne uniquement si l'image ne requiert pas de fichiers internes appartenant à un UID spécifique (binaires SUID, sockets, etc.). Paperless-ngx supporte ce mode via sa variable `USERMAP_UID` ; Grafana ne le supporte pas proprement car son image modifie des permissions lors de son `entrypoint`. Si vous forcez `user: 472:472` sur Grafana, le conteneur échoue au démarrage avec des erreurs sur `\u002Fvar\u002Flib\u002Fgrafana`.\n\n**Variables d'environnement PUID\u002FPGID.** Les images de la communauté LinuxServer.io exposent les variables `PUID` et `PGID` : l'entrypoint de l'image reçoit un processus root, change dynamiquement l'UID de l'utilisateur applicatif avec `usermod`\u002F`groupmod`, puis descend de privilèges. C'est pratique mais ces variables sont propres aux images LinuxServer.io — elles n'ont aucun effet sur les images officielles de Grafana, Nextcloud ou Immich. Ne les mélangez pas.\n\n**Volumes nommés.** Avec un volume Docker nommé (`docker volume create`), Docker gère lui-même le répertoire sous `\u002Fvar\u002Flib\u002Fdocker\u002Fvolumes\u002F`. À la première écriture, le répertoire est créé avec les permissions du processus du conteneur. Résultat : pas de problème de permissions au démarrage, mais la migration des données existantes nécessite une étape de copie explicite :\n```\ndocker run --rm \\\n  -v mon-ancien-repertoire:\u002Ffrom \\\n  -v mon-volume-nomme:\u002Fto \\\n  alpine sh -c 'cp -a \u002Ffrom\u002F. \u002Fto\u002F'\n```\nLes volumes nommés conviennent bien aux nouvelles installations ; pour les données existantes, le bind-mount avec un `chown` préalable reste plus prévisible.",{"type":35,"title":94,"body":95},"Cas NFS et montages distants","Les montages NFS et CIFS (partages Samba\u002FWindows) ajoutent une couche de complexité car l'arbitrage des permissions se fait à deux endroits : le système de fichiers local ET le serveur distant. Comprendre lequel des deux bloque est essentiel avant de chercher une correction.\n\n**Problème NFS — `root_squash`.** Par défaut, un serveur NFS exporte avec `root_squash` : tout accès qui arrive avec UID 0 (root) est automatiquement réattribué à l'utilisateur `nobody` (UID 65534). Si votre conteneur tourne en UID 472 et que le partage NFS n'a pas de mapping UID côté serveur, le client monte le partage, voit les fichiers, mais l'écriture est refusée — parce que le serveur NFS considère que l'UID 472 du client n'a pas les droits sur ce partage.\n\nSolutions :\n1. Configurer l'export NFS avec `all_squash,anonuid=472,anongid=472` pour Grafana, ou l'UID correspondant à votre application.\n2. Créer un utilisateur côté serveur NFS avec le même UID que dans le conteneur et lui attribuer la propriété des répertoires partagés.\n3. Utiliser `no_root_squash` uniquement si vous contrôlez complètement le réseau interne — cette option permet à root sur le client d'agir comme root sur le serveur, ce qui est un risque de sécurité significatif.\n\n**Problème CIFS — options de montage figées.** Contrairement à ext4 ou XFS, un montage CIFS ne supporte pas le `chown` après montage : la propriété est fixée par les options passées à la commande de montage. Si vous montez un partage Windows sans spécifier d'UID, les fichiers apparaissent en root (UID 0) et les conteneurs Nextcloud (UID 33) ne peuvent pas y écrire, quelle que soit la permission POSIX visible côté client.\n\nPour les montages CIFS dans `\u002Fetc\u002Ffstab` :\n```\n\u002F\u002Fserveur\u002Fpartage \u002Fopt\u002Fnextcloud\u002Fdata cifs uid=33,gid=33,credentials=\u002Fetc\u002Fcifs-creds,iocharset=utf8 0 0\n```\nVérifiez toujours que le fichier de credentials (`\u002Fetc\u002Fcifs-creds`) n'est lisible que par root (`chmod 600`).",{"type":97,"title":98,"headers":99,"rows":103},"comparison","Méthodes de correction : comparaison",[100,101,102],"Méthode","Avantages","Risques \u002F Limites",[104,108,112,116],[105,106,107],"chown UID:GID sur le répertoire hôte","Simple, universelle, compatible toutes images","Nécessite de connaître l'UID exact ; à refaire si le répertoire est recréé",[109,110,111],"user: UID:GID dans compose.yml","Pas de chown à gérer ; portable entre hôtes","L'image doit supporter les UIDs arbitraires ; peut casser des fichiers internes",[113,114,115],"Volumes nommés Docker","Permissions gérées automatiquement au premier démarrage","Moins lisible ; migration de données existantes plus complexe",[117,118,119],"--privileged ou chmod 777","Résout le problème immédiatement","DANGER : expose l'hôte et tous ses processus ; ne jamais utiliser en production",{"type":35,"title":121,"body":122},"Dépannage : 4 erreurs classiques avec leur message exact","Voici les quatre erreurs Docker les plus courantes liées aux permissions, avec le message d'erreur exact et sa solution.",{"type":42,"items":124},[125,126,127,128],"**`mkdir: cannot create directory '\u002Fvar\u002Flib\u002Fgrafana\u002Fplugins': Permission denied`** → Le répertoire hôte n'appartient pas à l'UID 472. Appliquez `chown -R 472:472 \u002Fopt\u002Fgrafana\u002Fdata`.","**`[Errno 13] Permission denied: '\u002Fusr\u002Fsrc\u002Fpaperless\u002Fmedia'`** → Paperless-ngx ne peut pas écrire dans son répertoire media. Vérifiez que le bind-mount appartient à l'UID 1000 sur l'hôte.","**`Could not create lock file \u002Fvar\u002Flib\u002Fgrafana\u002F.~lock.grafana.db`** → Grafana peut lire le répertoire mais pas y écrire. Problème de permissions sur les fichiers existants : `chown 472:472 \u002Fopt\u002Fgrafana\u002Fdata\u002F*.db` ou supprimez le lock file.","**`chown: changing ownership of '\u002Fdata': Operation not permitted`** (au démarrage du conteneur) → L'image tente elle-même de corriger les permissions mais ne peut pas car elle ne tourne pas en root. Effectuez le `chown` manuellement sur l'hôte AVANT de démarrer le conteneur.",{"type":130,"body":131},"tip","**SELinux et AppArmor : les flags `:z` et `:Z` dans les bind-mounts.** Sur les systèmes avec SELinux actif (CentOS, RHEL, Fedora), un bind-mount peut être bloqué même si les permissions POSIX sont correctes. Docker fournit deux suffixes : `:z` relabellise le contenu pour le partager entre plusieurs conteneurs, et `:Z` relabellise en accès privé (un seul conteneur). Exemple : `- \u002Fopt\u002Fgrafana\u002Fdata:\u002Fvar\u002Flib\u002Fgrafana:z`. Sans ce flag sur un système SELinux, vous obtiendrez `Permission denied` même après un `chown` correct. Pour vérifier si SELinux bloque : `ausearch -m AVC -ts recent | grep docker`.",{"type":35,"title":133,"body":134},"Conclusion","Le `Permission denied` dans les logs Docker n'est jamais une fatalité. La solution tient en trois commandes : `docker exec \u003Cconteneur> id` pour connaître l'UID, `ls -ln \u003Crépertoire-hôte>` pour confirmer le propriétaire actuel, puis `chown -R \u003CUID>:\u003CGID> \u003Crépertoire-hôte>` pour corriger. La règle d'or : créer les répertoires hôtes avec le bon propriétaire avant de démarrer le conteneur, pas après.\n\nPour éviter de reproduire le problème à chaque nouvelle installation, documentez les UIDs dans votre `compose.yml` sous forme de commentaires et intégrez le `chown` dans votre script de provisionnement ou votre playbook Ansible. Un rôle Ansible qui crée les répertoires de données avec `owner: 472` et `group: 472` (pour Grafana) avant le `docker compose up` élimine la cause à la racine.\n\nSur un VPS dédié, cette discipline évite 90 % des incidents de données silencieusement perdues au redémarrage — des incidents qui ne produisent aucune alerte car le conteneur est vert, le service répond, mais tout ce qui a été configuré depuis le dernier démarrage a disparu. Un `chown` de deux secondes avant le premier lancement vous en épargne des heures de débogage.","Un VPS prêt pour le self-hosting","Déployez vos applications Docker sur un VPS ServOrbit avec accès root, IPv4 dédiée et snapshots automatiques. À partir de 99 DH\u002Fmois.","Voir les offres VPS","\u002Fvps-cloud",[140,162],{"id":141,"slug":142,"slugs":143,"title":147,"excerpt":148,"readTime":149,"views":150,"isPinned":19,"publishedAt":151,"updatedAt":152,"category":153,"categories":159,"featuredImage":29,"bgImage":30,"posterImage":161,"relatedSolution":29},369,"docker-secrets-securite-vps-production",{"fr":142,"en":144,"ar":145,"es":146},"docker-secrets-production-protecting-credentials-on-vps","اسرار-docker-في-الانتاج-حماية-بيانات-الاعتماد-على-vps","docker-secrets-produccion-proteger-credenciales-vps","Docker Secrets en production : protéger ses secrets sur VPS","Gérez vos secrets Docker en production sans les exposer dans docker-compose.yml. Docker Secrets sans Swarm, .env.vault et SOPS : méthode et comparatif.",7,1,"2026-09-20T00:00:00+00:00","2026-09-20T21:13:51+00:00",{"id":154,"name":155,"slug":156,"color":157,"icon":158},8,"Sécurité & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[160],{"id":154,"name":155,"slug":156,"color":157,"icon":158},"\u002Fblog\u002Fcovers\u002Fdocker-secrets-securite-vps-production-poster.svg",{"id":163,"slug":164,"slugs":165,"title":169,"excerpt":170,"readTime":171,"views":18,"isPinned":19,"publishedAt":172,"updatedAt":173,"category":174,"categories":175,"featuredImage":29,"bgImage":30,"posterImage":177,"relatedSolution":29},229,"docker-compose-production-checklist",{"fr":164,"en":166,"ar":167,"es":168},"docker-compose-in-production-10-point-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","checklist-docker-compose-en-produccion","Docker Compose en production : checklist des 10 points","Checklist Docker Compose en production : 10 réglages essentiels, health checks, secrets sans downtime, rollback, dépannage des erreurs courantes, CVE-2026-17106.",12,"2026-08-06T00:00:00+00:00","2026-09-29T14:40:45+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[176],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",1790693200297]