vendredi 25 septembre 2026

À propos

Contact

Outils & workflow

Un pipeline qui reconstruit l’image Docker seulement si le Dockerfile a changé

Ajouter une condition de cache qui évite de rebâtir une image identique à chaque exécution, pour accélérer nettement la CI.

Par Clément Hadrot • 28 décembre 2025 • 5 min de lecture • Aucun commentaire
Un pipeline qui reconstruit l'image Docker seulement si le Dockerfile a changé

Un pipeline CI qui reconstruit l’image Docker de base à chaque exécution, même quand le Dockerfile n’a pas bougé depuis des semaines, gaspille un temps précieux : sur un projet de l’agence, ce rebuild systématique ajoutait environ trois minutes quarante à chaque exécution du pipeline de déploiement, pour un résultat strictement identique à l’image déjà poussée au registre la veille.

Ce texte ne traite pas du registre de conteneurs privé lui-même, déjà couvert par ailleurs. Il s’agit ici d’une condition ajoutée en amont dans le pipeline : détecter que le Dockerfile n’a pas changé, et dans ce cas, sauter purement et simplement l’étape de build pour réutiliser l’image déjà existante au registre.

Le principe : un hash comme empreinte de décision

L’idée consiste à calculer une empreinte (un hash SHA-256) du contenu du Dockerfile, et à comparer cette empreinte à celle utilisée lors du dernier build réussi, stockée quelque part de façon persistante entre deux exécutions du pipeline. Si l’empreinte est identique, le Dockerfile n’a pas changé et l’image existante convient encore. Si elle diffère, un rebuild s’impose.

Stocker l’empreinte du dernier build

GitHub Actions propose un mécanisme de cache natif, actions/cache, qui convient parfaitement pour persister un simple fichier texte contenant le dernier hash connu entre deux exécutions :

L'essentiel à retenir : Un hash du Dockerfile décide si un rebuild est nécessaire ; L'image précédente est réutilisée telle quelle si rien n'a changé ; Le gain se compte en minutes économisées à chaque exécution
jobs:
  verifier-et-construire:
    runs-on: ubuntu-latest
    outputs:
      rebuild_necessaire: ${{ steps.comparaison.outputs.rebuild }}
    steps:
      - uses: actions/checkout@v4

      - name: Calculer le hash actuel du Dockerfile
        id: hash
        run: echo "actuel=$(sha256sum Dockerfile | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"

      - name: Récupérer le dernier hash connu
        uses: actions/cache@v4
        with:
          path: .dernier-hash-dockerfile
          key: hash-dockerfile-${{ steps.hash.outputs.actuel }}
          restore-keys: hash-dockerfile-

      - name: Comparer les deux hashs
        id: comparaison
        run: |
          if [ -f .dernier-hash-dockerfile ] && \
             [ "$(cat .dernier-hash-dockerfile)" = "${{ steps.hash.outputs.actuel }}" ]; then
            echo "rebuild=non" >> "$GITHUB_OUTPUT"
            echo "Dockerfile inchangé, rebuild inutile."
          else
            echo "rebuild=oui" >> "$GITHUB_OUTPUT"
            echo "${{ steps.hash.outputs.actuel }}" > .dernier-hash-dockerfile
            echo "Dockerfile modifié ou premier build, rebuild nécessaire."
          fi

Pourquoi la clé de cache inclut déjà le hash

La clé de cache hash-dockerfile-${{ steps.hash.outputs.actuel }} intègre volontairement le hash courant. Si ce hash a déjà servi de clé lors d’un run précédent, actions/cache restaure directement le fichier correspondant sans même nécessiter la comparaison manuelle qui suit, ce qui rend la vérification redondante mais robuste : même en cas d’incohérence rare entre le cache et le fichier restauré, la comparaison explicite tranche en dernier recours.

Conditionner le job de build sur ce résultat

Le job de construction proprement dit ne se déclenche que si la sortie rebuild_necessaire vaut oui :

  construire-image:
    needs: verifier-et-construire
    if: needs.verifier-et-construire.outputs.rebuild_necessaire == 'oui'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Connexion au registre
        run: echo "${{ secrets.REGISTRE_TOKEN }}" | docker login registre.agence.example -u agence --password-stdin
      - name: Construire et pousser
        run: |
          docker build -t registre.agence.example/base/php-fpm-wordpress:latest .
          docker push registre.agence.example/base/php-fpm-wordpress:latest

Le job suivant, celui qui déploie effectivement le site, ne dépend jamais directement de ce job de build : il pointe simplement vers le tag latest de l’image au registre, qu’elle vienne d’être reconstruite à l’instant ou qu’elle date de plusieurs semaines, ce qui rend le mécanisme totalement transparent pour la suite du pipeline.

Le piège à éviter : ignorer les dépendances indirectes

Un Dockerfile qui référence un fichier externe, par exemple une liste d’extensions PHP dans un fichier php-extensions.txt copié dans l’image, peut rester inchangé lui-même alors que ce fichier annexe a évolué. Le hash calculé uniquement sur le Dockerfile manquerait alors ce changement. La correction consiste à inclure dans le calcul de hash tous les fichiers réellement pertinents pour le build :

echo "actuel=$(cat Dockerfile php-extensions.txt docker/*.conf | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"

Sur un projet de l’agence, cet oubli initial a laissé passer une modification de la configuration PHP-FPM pendant plusieurs jours avant d’être repérée, le pipeline continuant benoîtement à réutiliser une image obsolète parce que seul le Dockerfile faisait partie du calcul de hash.

Mesurer le gain réel

ScénarioDurée du job
Rebuild systématique (avant)4 min 05
Rebuild sauté grâce au cache (après, cas fréquent)0 min 25
Rebuild réel nécessaire (Dockerfile modifié)4 min 10

Reconstruire une image identique à celle déjà poussée la veille ne teste rien de plus, ça consomme juste du temps de CI pour produire le même résultat une deuxième fois.

En résumé

Cette condition de cache, une vingtaine de lignes de configuration YAML supplémentaires, a réduit le temps moyen du pipeline de l’agence de plusieurs minutes sur la majorité des exécutions, celles où le Dockerfile n’a pas bougé. Le seul point de vigilance réel consiste à englober dans le calcul de hash tous les fichiers qui influencent réellement le contenu de l’image, pas uniquement le Dockerfile lui-même.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi