Variante vicieuse d’un piège classique. Docker a auto-créé un dossier vide à la place d’un fichier source manquant (cf [[66-docker-bind-mount-source-fichier-manquant]]). Je corrige la cause initiale, je commit le fichier dans git, je redéploie via un PaaS qui fait un git pull automatique. Et le déploiement échoue encore exactement de la même manière.
Symptôme
Au deploy après le fix :
Error response from daemon: failed to create task ...
not a directory: Are you trying to mount a directory onto a file ...
Le même message qu’au premier deploy. Je vérifie le repo distant, le fichier y est bien. Je SSH sur l’hôte, et là :
$ ls -la /data/app/conf/
drwxr-xr-x 2 root root 4096 traccar.xml ← dossier vide
drwxr-xr-x 2 root root 4096 traccar.xml.example ← dossier vide
Les fichiers du repo sont devenus (restés) des dossiers vides sur le serveur. Le git pull qu’a fait le PaaS n’a rien changé.
Cause
Une fois que Docker a posé un dossier (même vide) à un chemin, git refuse silencieusement de le remplacer par un fichier régulier lors d’un git pull ou git checkout. Ce n’est pas une faille — c’est une protection : git ne supprime pas un dossier non versionné (potentiellement créé par l’utilisateur) pour y poser un fichier suivi.
Le cycle complet du piège :
- Premier deploy : fichier manquant côté repo → Docker auto-crée un dossier vide
- Tu corriges, commits le fichier, push
- Deploy suivant :
git pullvoit qu’il faut écrire un fichierX, voit qu’Xexiste déjà comme dossier non versionné → skip silencieux ou warning facile à manquer - Compose up → même erreur de mount qu’au premier deploy
- Tu boucles indéfiniment
Les PaaS qui utilisent git pull (par opposition à un re-clone complet) sont particulièrement exposés. Avec git clean -fdx avant chaque pull le problème disparaît, mais c’est rarement le default.
Solution
Court terme : SSH sur l’hôte cible, rm -rf les dossiers fantômes, relancer le deploy. Marche jusqu’au prochain incident.
Long terme : éliminer le bind mount à la source. Embarquer le fichier dans une image custom :
FROM vendor/app:latest
COPY conf/app.xml /opt/app/conf/app.xml
Plus aucun bind mount → plus de mount-type-mismatch possible → plus de dossier fantôme. C’est la seule mitigation qui ne dépend pas du comportement du wrapper git du PaaS.
Lessons learned
- Git ne remplace pas un dossier non versionné par un fichier suivi lors d’un pull/checkout — c’est une protection délibérée, pas un bug
- Combiné avec l’auto-création de dossier par Docker (cf [[66-docker-bind-mount-source-fichier-manquant]]), tu obtiens un piège self-perpétuant d’un deploy à l’autre
- Un PaaS qui re-clone à chaque deploy (au lieu de
git pullincrémental) ne tombe PAS dans ce piège — vérifier le comportement de son PaaS git clean -fdxavantgit pullcasse le piège, mais c’est rarement le default des outils CI/CD- La seule mitigation robuste : ne plus bind-mounter un fichier qui pourrait manquer au clone — embarquer dans l’image (
COPY) ou monter un dossier complet