Retour au cours

infra / docker-compose

Compose Watch : boucle de développement rapide

Leçon 141 exercice

Explication

Ce que vous allez apprendre

  • Comprendre pourquoi un bind mount seul ne suffit pas toujours à voir un changement de code
  • Utiliser docker compose watch pour synchroniser automatiquement les fichiers modifiés
  • Choisir la bonne action (sync, sync+restart, rebuild) selon le type de fichier modifié
  • Exclure des dossiers volumineux comme node_modules/ de la synchronisation avec ignore
  • Combiner Compose Watch avec un outil à hot-reload natif (Vite, nodemon)

Dans quel contexte ?

Un développeur du projet boutique-api modifie un fichier dans ./api/src/routes/users.js et doit relancer manuellement docker compose up --build pour voir l'effet, ce qui prend 30 secondes à chaque changement, même le plus minime. Avec docker compose watch, ce même changement se répercute dans le conteneur en cours d'exécution en une fraction de seconde, sans reconstruire toute l'image.

Le problème, très concrètement

En développement, on modifie un fichier de code et on veut en voir l'effet immédiatement. Avec un bind mount classique, vu dans la leçon sur les volumes, ça fonctionne pour beaucoup de langages interprétés. Mais certaines applications ne rechargent rien toutes seules, et un changement de dépendances demande carrément de reconstruire l'image.

Une première solution naïve : tout reconstruire à chaque fois

On pourrait se dire qu'il suffit de relancer docker compose up --build à chaque modification. Mais reconstruire toute l'image pour un simple changement de texte est beaucoup trop lent pour être utilisable au quotidien.

L'idée de Compose Watch

docker compose watch observe en continu tes fichiers source et réagit automatiquement dès qu'un fichier change. Plus besoin de taper une commande à chaque modification : Compose s'en charge tout seul, en arrière-plan.

Première action possible : sync

La plus légère des trois actions s'appelle sync. Elle copie simplement le fichier modifié dans le conteneur déjà en cours d'exécution, sans rien redémarrer. C'est parfait pour un outil qui a déjà son propre hot-reload, comme Vite ou nodemon.

Deuxième action : sync+restart

Certains process ne relisent leur code qu'à leur démarrage. Pour eux, sync+restart copie le fichier ET redémarre le process applicatif à l'intérieur du conteneur, sans reconstruire toute l'image.

Troisième action : rebuild, pour les cas plus lourds

Il reste un cas que les deux premières actions ne couvrent pas : un changement de dépendances, comme un nouveau package dans package.json. Là, il faut vraiment reconstruire l'image, ce que fait l'action rebuild, la plus lente des trois mais aussi la plus complète.

Bien choisir son action selon le fichier

Une fois ces trois actions connues, il reste à les associer au bon chemin : sync sur le code source, rebuild sur les fichiers de dépendances, sync+restart sur les fichiers de configuration qui doivent être relus par le process. C'est cette association fine qui remplace le simple bind mount permanent des leçons précédentes.

ActionCe qu'elle faitExemple de chemin concerné
syncCopie le fichier dans le conteneur en cours d'exécution./api/src
sync+restartCopie puis redémarre le process applicatif./api/config/
rebuildReconstruit l'image et recrée le conteneur./api/package.json

Prérequis

Cette leçon suppose que tu es à l'aise avec build et les bind mounts (leçons précédentes) : Compose Watch en est un raffinement, pas un mécanisme totalement différent.

Les pièges à connaître

Un piège fréquent est d'oublier ignore: sur des dossiers volumineux comme node_modules/, ce qui ralentit inutilement toute la synchronisation. Un autre est d'utiliser rebuild par réflexe pour un simple changement de code, alors qu'un sync suffirait et serait bien plus rapide.

Maintenant que la boucle de développement est optimisée, la leçon suivante s'intéresse à un problème différent mais toujours lié au fichier YAML lui-même : éviter de dupliquer une configuration entre plusieurs services.

Commandes & code

Compose Watch : boucle de développement rapide

docker compose watch synchronise le code source dans les conteneurs en direct, sans rebuild manuel ni volume bind mount permanent.

yaml
# compose.yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    develop:
      watch:
        # sync : copie les fichiers modifiés DANS le conteneur en cours d'exécution
        - action: sync
          path: ./api/src
          target: /app/src
          ignore:
            - node_modules/
            - "*.test.js"

        # rebuild : reconstruit l'image ET recrée le conteneur (ex: changement de dépendances)
        - action: rebuild
          path: ./api/package.json

        # sync+restart : copie le fichier puis redémarre le process (sans rebuild complet)
        - action: sync+restart
          path: ./api/config/
          target: /app/config/
bash
# Démarrer la stack en mode watch (build initial + observation continue)
docker compose watch

# Combiner avec les logs pour tout voir dans un seul terminal
docker compose up -d --watch
yaml
# Cas concret : frontend avec hot-reload natif (Vite) + backend qui nécessite un restart process
services:
  frontend:
    build: ./frontend
    develop:
      watch:
        - action: sync           # Vite gère déjà le hot-reload, on synchronise juste les fichiers
          path: ./frontend/src
          target: /app/src

  backend:
    build: ./backend
    develop:
      watch:
        - action: sync+restart    # pas de hot-reload natif -> on redémarre le process Node
          path: ./backend/src
          target: /app/src

Résumé

  • develop.watch remplace les bind mounts manuels pour la boucle de développement.
  • sync copie sans rebuild, sync+restart copie puis redémarre le process, rebuild reconstruit l'image.
  • ignore: évite de synchroniser node_modules/ ou les fichiers de test inutiles au runtime.
  • Adapté au type d'application : sync seul avec un outil à hot-reload natif (Vite, nodemon).

Exercices pratiques

1 disponible
1

Mission : une boucle de développement inutilement lente

Objectif : Choisir la bonne action Compose Watch selon le type de fichier et le type d'application.

Contexte

Sur boutique-api, un développeur configure action: rebuild sur le chemin ./api/src, pour chaque changement de code JavaScript, ce qui rend chaque sauvegarde très lente. Le service frontend utilise Vite (hot-reload natif), tandis que backend n'a aucun hot-reload.

Corrige la configuration watch pour retrouver une boucle de développement rapide.

Résoudre l’exercice →