Changer le thème

Comparaison des montages Docker : Volume vs Bind Mount — guide de choix (avec tests de performance)

Easton editorial illustration: criteria lens and candidate cards

La première fois avec Docker, le montage de données est souvent le plus déroutant. Un jour, un conteneur de test redémarre — page blanche. La base de données ? Vide. On apprend vite : un redémarrage de conteneur peut faire disparaître les données.

×3
Gain de performance
npm install sur Mac : Volume 3× plus rapide que Bind Mount

Vous avez peut-être déjà vécu ça :

  • Vous montez un répertoire avec -v sans savoir où vont les données
  • Sur Mac, npm install traîne interminablement
  • Vous voyez --mount type=volume chez d’autres sans comprendre la différence avec -v
  • Vous hésitez entre Volume et Bind Mount

Tout cela vient d’une compréhension insuffisante des trois montages Docker. Aujourd’hui, comparons Volume, Bind Mount et tmpfs, avec un arbre de décision et des scénarios réels pour choisir en quelques minutes.

Bases de la gestion des données Docker

Pourquoi les données disparaissent au redémarrage ?

Fait brutal : un conteneur n’est pas fait pour stocker des données.

Imaginez un conteneur comme une boîte jetable. On jette la boîte, le contenu part avec. Même sans suppression, un simple redémarrage peut faire perdre certaines données.

D’où la persistance : placer les données importantes hors du conteneur, qui va et vient, tandis que les données restent.

-v vs --mount : quelle différence ?

Au début, ces deux paramètres me donnaient mal à la tête. Ils font à peu près la même chose, mais la syntaxe diffère.

Exemple : monter un volume sur /data :

# Méthode 1 : -v (concis, mais ambigu)
docker run -v myvolume:/data nginx

# Méthode 2 : --mount (verbeux, mais clair)
docker run --mount type=volume,source=myvolume,target=/data nginx

-v : un seul :, source à gauche, cible à droite. Simple — mais impossible de savoir si c’est un Volume ou un Bind Mount.

--mount indique explicitement type=volume. Chaque paramètre est lisible. Plus long à taper, mais six mois plus tard, la commande se comprend d’un coup d’œil.

Mon conseil : --mount en production, -v pour bricoler.

Critère-v--mount
Syntaxe-v source:target:options--mount type=xxx,source=xxx,target=xxx
Lisibilité🤨 Concis mais flou✅ Clair
Volume-v myvolume:/data--mount type=volume,source=myvolume,target=/data
Bind Mount-v /host/path:/data--mount type=bind,source=/host/path,target=/data
RecommandationCompatibilité anciennes versions✅ Nouveaux projets

[Image : schéma comparatif des commandes]
Prompt : terminal screen showing docker run commands with -v and —mount side by side, modern tech style, blue and green colors, high quality

Comparaison approfondie des trois montages

Docker propose trois montages : Volume, Bind Mount et tmpfs. Chacun a son tempérament — le bon choix simplifie la vie, le mauvais crée des pièges.

Volume : laissez Docker gérer

Un Volume, c’est comme un majordome. Vous lui confiez vos données, il les range dans un endroit dédié (sous Linux : /var/lib/docker/volumes/), sans que vous ayez à vous soucier des détails.

Ce que j’apprécie : performances stables cross-plateforme. Linux, Mac ou Windows — le comportement reste similaire. Idéal en équipe, sans le classique « chez moi ça marche ».

Les Volumes se gèrent aussi via Docker :

# Créer un Volume
docker volume create my-data

# Lister tous les Volumes
docker volume ls

# Détails (où sont les données)
docker volume inspect my-data

# Sauvegarder (très simple)
docker run --rm -v my-data:/data -v $(pwd):/backup alpine tar czf /backup/backup.tar.gz /data

Quand utiliser un Volume ?

  • Bases MySQL, PostgreSQL (sécurité des données)
  • Données partagées entre conteneurs (répertoire d’upload)
  • Données persistantes en production (sauvegarde et migration faciles)

[Image : schéma du fonctionnement d’un Volume]
Prompt : Docker volume management diagram, Docker managing storage volumes, clean infographic style, blue and white colors, high quality

Bind Mount : vous gardez la main

Le Bind Mount monte directement un répertoire de l’hôte dans le conteneur. Vous choisissez le chemin, Docker n’intervient pas.

Avantage majeur : synchronisation en temps réel. Vous modifiez le code localement, le conteneur voit le changement immédiatement. En dev, c’est idéal — modifier, rafraîchir, voir le résultat sans rebuild.

Attention Mac et Windows.

Paolo Mainardi a testé en 2025 : sur Mac, npm install via Bind Mount est 3,5× plus lent qu’avec un Volume. Pourquoi ? Docker Desktop sur Mac/Windows passe par une couche de virtualisation ; chaque accès Bind Mount traverse cette frontière — surcoût énorme.

# Bind Mount (monter le répertoire courant)
docker run -d \
  --name my-app \
  --mount type=bind,source=$(pwd),target=/app \
  node:18

# Ou avec -v (même effet)
docker run -d --name my-app -v $(pwd):/app node:18

Quand utiliser un Bind Mount ?

  • Environnement de dev local (voir les changements de code en direct)
  • Fichiers de config (nginx.conf, .env)
  • Logs sur l’hôte pour consultation facile

Quand l’éviter ?

  • Sur Mac/Windows : ne pas monter node_modules, vendor, etc. en Bind Mount (catastrophe de performance)
  • Production : prudence (forte dépendance aux chemins)

tmpfs : le post-it en mémoire

tmpfs stocke les données en RAM. Le conteneur s’arrête, tout disparaît. Utile pourtant dans certains cas.

La RAM est des dizaines à centaines de fois plus rapide que le disque. Données temporaires (cache Redis, token, session) ? Autant utiliser le stockage le plus rapide.

# tmpfs (100 Mo en mémoire)
docker run -d \
  --name fast-cache \
  --mount type=tmpfs,target=/cache,tmpfs-size=100M \
  redis:7

Quand utiliser tmpfs ?

  • Cache temporaire (pas besoin de persistance)
  • Données sensibles éphémères (RAM effacée à l’arrêt)
  • Exigences de performance extrêmes (analyse de logs temps réel)

Note : tmpfs fonctionne sur les conteneurs Linux ; Docker Desktop Mac/Windows ne le supporte pas.

Tableau comparatif

CaractéristiqueVolumeBind Mounttmpfs
GestionDockerUtilisateurMémoire
Emplacement/var/lib/docker/volumes/Chemin hôte libreRAM
Perf. (Linux)ÉlevéeÉlevéeTrès élevée
Perf. (Mac/Win)ÉlevéeFaible (×3,5 plus lent)Très élevée
Cross-plateforme✅ Parfait⚠️ Dépend des chemins⚠️ Linux seulement
Persistance✅ Oui✅ Oui❌ Temporaire
Sauvegarde✅ Simple⚠️ Variable❌ Impossible
Sync temps réel❌ Non✅ Oui-
Cas d’usageBDD, productionDev, configCache, temporaire

Guide de choix par scénario

Encore hésitant ? Voici un arbre de décision en trois questions :

Arbre de décision rapide

Question 1️⃣ : Les données doivent-elles persister ?
  ├─ Non (cache, fichiers temporaires) → tmpfs
  └─ Oui → Question 2️⃣

Question 2️⃣ : Dev ou production ?
  ├─ Production → Volume
  └─ Dev → Question 3️⃣

Question 3️⃣ : Modifications de fichiers en temps réel (code) ?
  ├─ Oui → Bind Mount
  │   └─ Mac/Windows ? → Volume pour node_modules, etc.
  └─ Non → Volume

Trop abstrait ? Quelques scénarios concrets.

Scénario 1 : base MySQL

Une base de données — perdre les données serait fatal. Volume sans hésiter.

# Conteneur MySQL (recommandé)
docker run -d \
  --name mysql \
  --mount type=volume,source=mysql-data,target=/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  mysql:8.0

# Infos du Volume
docker volume inspect mysql-data

Pourquoi Volume ?

  • ✅ Données sécurisées, gérées par Docker
  • ✅ Sauvegarde simple (une commande)
  • ✅ Performances cohérentes cross-plateforme
  • ✅ Migration facile vers un autre serveur

[Image : schéma MySQL + Volume]
Prompt : MySQL database with Docker volume storage, data persistence visualization, professional tech illustration, blue and orange colors, high quality

Scénario 2 : dev Node.js (Mac)

Cas classique : voir le code en direct sur Mac, sans npm install interminable.

Approche mixte : code en Bind Mount, dépendances en Volume.

# Conteneur Node.js de dev
docker run -d \
  --name my-node-app \
  --mount type=bind,source=$(pwd)/src,target=/app/src \
  --mount type=bind,source=$(pwd)/package.json,target=/app/package.json \
  --mount type=volume,source=node-modules-cache,target=/app/node_modules \
  -p 3000:3000 \
  node:18 \
  npm run dev
  • src en Bind Mount → changements de code immédiats
  • package.json en Bind Mount → voir les changements de dépendances
  • node_modules en Volume → éviter le piège Mac

Première exécution, installer les dépendances :

docker exec my-node-app npm install

Résultat : npm install peut être 3× plus rapide. Chez moi : 2 minutes → 40 secondes.

Scénario 3 : configuration Nginx

Modifier la config Nginx, redémarrer le conteneur — config perdue ? Bind Mount avec readonly.

# Config Nginx (lecture seule)
docker run -d \
  --name nginx \
  --mount type=bind,source=$(pwd)/nginx.conf,target=/etc/nginx/nginx.conf,readonly \
  -p 80:80 \
  nginx:latest

# Recharger sans redémarrer
docker exec nginx nginx -s reload

Pourquoi Bind Mount ?

  • ✅ Config modifiée = effet immédiat
  • ✅ Fichier sur l’hôte, facile à gérer
  • readonly empêche le conteneur de modifier la config

Scénario 4 : cache Redis temporaire

Redis en cache — les données sont jetables. tmpfs convient parfaitement.

# Redis avec tmpfs
docker run -d \
  --name redis-cache \
  --mount type=tmpfs,target=/data,tmpfs-size=512M \
  -p 6379:6379 \
  redis:7 \
  redis-server --save ""

# --save "" désactive la persistance RDB

Pourquoi tmpfs ?

  • ✅ Vitesse mémoire maximale
  • ✅ Pas besoin de persistance pour un cache
  • ✅ Redémarrage = vidage automatique, sémantique de cache

Attention : tmpfs Linux seulement. Docker Desktop Mac ne le supporte pas.

Scénario 5 : collecte de logs

Voir les logs sans docker logs à répétition ? Monter le répertoire de logs sur l’hôte.

docker run -d \
  --name my-app \
  --mount type=bind,source=$(pwd)/logs,target=/app/logs \
  my-app:latest

# Consulter en temps réel sur l'hôte
tail -f logs/app.log

Logs locaux : VSCode, grep, plateforme d’analyse — à vous de choisir.

Optimisation et pièges courants

Pièges que j’ai moi-même rencontrés — les connaître à l’avance fait gagner du temps.

Piège 1 : catastrophe de performance Mac/Windows

Rappel : sur Mac, Bind Mount est 3,5× plus lent qu’un Volume. npm install en 40 s peut passer à 2 minutes.

Pourquoi ?

Docker sur Mac/Windows tourne dans une VM. Chaque lecture/écriture Bind Mount traverse la frontière VM — surcoût énorme pour node_modules et ses milliers de petits fichiers.

Solutions :

# Méthode 1 : dépendances en Volume, code en Bind Mount (recommandé)
docker run -d \
  --mount type=bind,source=$(pwd)/src,target=/app/src \
  --mount type=volume,source=deps,target=/app/node_modules \
  node:18

# Méthode 2 : Bind Mount obligatoire → option :cached (Docker Desktop)
docker run -d -v $(pwd):/app:cached node:18

:cached indique à Docker : l’hôte fait autorité, le conteneur peut synchroniser avec retard. Moins efficace qu’un Volume pur.

Piège 2 : permissions (écriture impossible)

Très fréquent : « Permission denied » dans le conteneur.

Cause : UID du conteneur ≠ UID de l’hôte.

Vous (UID 1000) créez un répertoire monté ; le processus dans le conteneur tourne en UID 0 ou 999 — conflit de permissions.

Solutions :

# Méthode 1 : lancer avec votre UID
docker run --user $(id -u):$(id -g) \
  --mount type=bind,source=$(pwd),target=/app \
  node:18

# Méthode 2 : définir l'utilisateur dans le Dockerfile
FROM node:18
RUN useradd -m -u 1000 appuser
USER appuser
WORKDIR /app

Je privilégie la méthode 1. La 2 convient aux images à distribuer.

Piège 3 : chemins Windows

Sous Windows, C:\Users\... dans une commande Docker provoque des erreurs.

Syntaxe correcte :

# PowerShell (recommandé)
docker run -v ${PWD}:/app node:18

# CMD
docker run -v %cd%:/app node:18

# Git Bash
docker run -v /c/Users/yourname/project:/app node:18

# Ou double slash
docker run -v //c/Users/yourname/project:/app node:18

Perdu ? docker-compose gère souvent les chemins automatiquement.

Piège 4 : Volumes qui s’accumulent

Conteneur supprimé, Volume conservé. /var/lib/docker/volumes/ peut saturer le disque.

Nettoyage régulier :

docker volume ls
docker volume ls -f dangling=true
docker volume prune
docker system prune -a --volumes

Mon habitude : docker volume prune chaque semaine.

Piège 5 : où sont les données Volume ?

docker volume inspect my-data
# Chercher "Mountpoint" : /var/lib/docker/volumes/my-data/_data

Évitez d’éditer ce répertoire directement (permissions). Sauvegarde via Docker :

# Sauvegarder en tar
docker run --rm \
  -v my-data:/source \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/my-data-backup.tar.gz -C /source .

# Restaurer sur un nouveau Volume
docker run --rm \
  -v new-data:/target \
  -v $(pwd):/backup \
  alpine \
  tar xzf /backup/my-data-backup.tar.gz -C /target

Utile pour migrer une base de production.

[Image : flux de sauvegarde Volume]
Prompt : Docker volume backup workflow diagram, tar archive process, clean technical illustration, green and blue colors, high quality

Bonnes pratiques docker-compose

En projet réel, docker-compose est souvent préféré à docker run. Exemple complet couvrant les trois montages.

Exemple docker-compose.yml complet

Architecture type : frontend Node.js + API + PostgreSQL + Redis.

version: '3.8'

services:
  # Application web (dev)
  web:
    image: node:18
    container_name: my-web-app
    working_dir: /app
    command: npm run dev
    ports:
      - "3000:3000"
    volumes:
      # Code source : Bind Mount
      - type: bind
        source: ./src
        target: /app/src
      - type: bind
        source: ./package.json
        target: /app/package.json
      # node_modules : Volume (évite le piège Mac)
      - type: volume
        source: node-modules
        target: /app/node_modules
    environment:
      - NODE_ENV=development
    depends_on:
      - db
      - cache

  # Base de données
  db:
    image: postgres:15
    container_name: postgres-db
    ports:
      - "5432:5432"
    volumes:
      - type: volume
        source: postgres-data
        target: /var/lib/postgresql/data
      - type: bind
        source: ./init.sql
        target: /docker-entrypoint-initdb.d/init.sql
        read_only: true
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
      - POSTGRES_DB=mydb

  # Cache Redis
  cache:
    image: redis:7
    container_name: redis-cache
    ports:
      - "6379:6379"
    volumes:
      - type: tmpfs
        target: /data
        tmpfs:
          size: 100M
    command: redis-server --save ""

  # Nginx reverse proxy
  nginx:
    image: nginx:latest
    container_name: nginx-proxy
    ports:
      - "80:80"
    volumes:
      - type: bind
        source: ./nginx.conf
        target: /etc/nginx/nginx.conf
        read_only: true
      - type: bind
        source: ./logs/nginx
        target: /var/log/nginx
    depends_on:
      - web

volumes:
  node-modules:
    driver: local
  postgres-data:
    driver: local

Points clés

Web :

  • src en Bind Mount : hot reload immédiat
  • node_modules en Volume : indispensable sur Mac
  • package.json en Bind Mount : npm install dans le conteneur après changement de dépendances

Base de données :

  • Données en Volume : persistance production
  • Script d’init en Bind Mount + read_only : exécuté à la création uniquement

Redis :

  • tmpfs : pas de persistance, vitesse mémoire
  • size: 100M : limite la consommation RAM

Nginx :

  • Config en read_only
  • Logs en Bind Mount pour tail -f sur l’hôte

Commandes utiles

docker-compose up -d
docker-compose exec web ls -la /app/node_modules
docker-compose exec web npm install
docker-compose exec nginx nginx -s reload

docker run --rm \
  -v blog-write-agent_postgres-data:/source \
  -v $(pwd):/backup \
  alpine tar czf /backup/db-backup.tar.gz -C /source .

docker-compose down
docker-compose down -v  # supprime aussi les Volumes — attention !

Optimisation Mac/Windows

volumes:
  - ./src:/app/src:cached

:cached : l’hôte prioritaire, sync différée côté conteneur. Gain de 20 à 30 %.

[Image : architecture docker-compose]
Prompt : Docker compose multi-container architecture, web app database redis nginx, professional system diagram, blue and purple gradient, high quality

Résumé

Trois montages, trois outils :

  • Volume : Docker gère — fiable, stable, cross-plateforme
  • Bind Mount : vous gérez — flexible, temps réel, attention aux perfs
  • tmpfs : en mémoire — ultra-rapide, éphémère

Trois règles :

  1. Production → Volume (BDD, fichiers persistants)
  2. Dev → Bind Mount (modifications temps réel, hot reload)
  3. Temporaire → tmpfs (cache, données sensibles)

Mac/Windows :

  • node_modules, vendor : jamais en Bind Mount — Volume 3× plus rapide ou plus
  • Bind Mount obligatoire : option :cached

Action : prenez un projet en cours, passez de docker run à docker-compose.yml, testez les trois montages. Le bon choix améliore les performances et clarifie la structure.

Des questions ? Commentez — j’ai aussi appris en trébuchant.

Guide complet pour choisir un montage Docker

Comparez Volume, Bind Mount et tmpfs, et résolvez npm install 3× plus lent sur Mac

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Comprendre les trois montages

    Comparaison des trois montages :

    Volume
    • Géré par Docker, stocké dans le répertoire de données Docker
    • Adapté à la production, npm install ×3 plus rapide sur Mac
    • Bonnes performances, haute sécurité

    Bind Mount
    • Monte directement un répertoire de l'hôte
    • Adapté au dev, modifications en temps réel
    • Mais surcoût de performance sur Mac

    tmpfs
    • Montage en mémoire, données temporaires
    • Très rapide mais perdu à la suppression du conteneur
  2. 2

    Step 2: Performance et optimisations Mac/Windows

    Problème de performance :
    • npm install 3× plus lent sur Mac car Bind Mount a un surcoût
    • Volume peut être 3× plus rapide ou plus
    • Ne montez jamais node_modules, vendor, etc. en Bind Mount

    Attention Mac/Windows :
    • node_modules, vendor — jamais en Bind Mount
    • Volume peut être 3× plus rapide ou plus
    • Si Bind Mount obligatoire, ajoutez l'option :cached

    Recommandations :
    • Données de prod → Volume
    • Code de dev → Bind Mount
    • Données temporaires → tmpfs
  3. 3

    Step 3: Arbre de décision et bonnes pratiques

    Arbre de décision :
    • Données de prod → Volume (persistance, sécurité)
    • Code de dev → Bind Mount (modifications temps réel, hot reload)
    • Données temporaires → tmpfs (cache, infos sensibles)

    Bonnes pratiques :
    • Données de prod → Volume
    • Code de dev → Bind Mount
    • Données temporaires → tmpfs
    • Attention aux performances sur Mac/Windows

    Action : prenez un projet en cours, convertissez docker run en docker-compose.yml, testez Volume, Bind Mount et tmpfs — le bon choix améliore les perfs et clarifie la structure.

FAQ

Quels sont les trois montages Docker et leurs caractéristiques ?
Comparaison des trois montages :

Volume :
• Géré par Docker, stocké dans le répertoire de données Docker
• Adapté à la production, npm install ×3 plus rapide sur Mac
• Bonnes performances, haute sécurité

Bind Mount :
• Monte directement un répertoire de l'hôte
• Adapté au dev, modifications en temps réel
• Mais surcoût de performance sur Mac

tmpfs :
• Montage en mémoire, données temporaires
• Très rapide mais perdu à la suppression du conteneur
Pourquoi npm install est-il 3× plus lent sur Mac ? Comment optimiser ?
Problème de performance :
• npm install 3× plus lent sur Mac car Bind Mount a un surcoût
• Volume peut être 3× plus rapide ou plus
• Ne montez jamais node_modules, vendor, etc. en Bind Mount

Attention Mac/Windows :
• node_modules, vendor — jamais en Bind Mount
• Volume peut être 3× plus rapide ou plus
• Si Bind Mount obligatoire, ajoutez l'option :cached

Recommandations :
• Données de prod → Volume
• Code de dev → Bind Mount
• Données temporaires → tmpfs
Comment choisir le montage adapté ?
Arbre de décision :
• Données de prod → Volume (persistance, sécurité)
• Code de dev → Bind Mount (modifications temps réel, hot reload)
• Données temporaires → tmpfs (cache, infos sensibles)

Bonnes pratiques :
• Données de prod → Volume
• Code de dev → Bind Mount
• Données temporaires → tmpfs
• Attention aux performances sur Mac/Windows

Action : convertissez docker run en docker-compose.yml, testez les trois montages — le bon choix améliore les perfs et clarifie la structure.

11 min de lecture · Publié le: 17 déc. 2025 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog