FreeToGenerate.com

Les deux mêmes lignes n’ont pas le même sens dans un .dockerignore et dans un .gitignore. Voici les deux verdicts d’un coup. Rien n’est envoyé.

Essayez :

Un motif par ligne. Le croisillon n’ouvre un commentaire que s’il occupe la première colonne, et le point d’exclamation crée une exception à une ligne précédente.

Seul git s’en soucie : un motif terminé par une barre ne vise que les répertoires. Docker n’a pas de motif de ce genre, puisque la barre est effacée avant toute comparaison.

Ce que chaque fichier ferait de ce chemin

.dockerignore

Est envoyé au constructeur

Décidé par la ligne 2, !util/docker/weba correspondu à util/docker/web

.gitignore

Ignoré

Décidé par la ligne 1, **a correspondu à util

Ces deux fichiers ne disent pas la même chose de ce chemin. Les mêmes lignes n’ont pas le même sens dans un .dockerignore et dans un .gitignore, et rien ne vous prévient : la construction envoie simplement plus, ou moins, que prévu.

Comment chaque ligne a été lue

LigneTelle quelleAprès nettoyageComparée comme
1****suffixe
2!util/docker/webutil/docker/webexceptionchaîne exacte

Tout fonctionne dans votre navigateur. Rien de ce que vous collez n’est envoyé ailleurs.

Aussi disponible en : English · Español · Português · العربية

Fichier .dockerignore : générateur et vérificateur de chemins

Écrivez un .dockerignore, testez n’importe quel chemin contre lui, et voyez côte à côte ce que git aurait fait du fichier identique.

Qu’est-ce qu’un fichier .dockerignore ?

Le .dockerignore se place à côté de votre Dockerfile et énumère ce qui ne doit pas partir vers le constructeur. Tout le contexte de construction est empaqueté et transmis avant l’exécution de la première instruction : un node_modules oublié ou un répertoire .git coûte donc du temps d’envoi à chaque construction, se retrouve dans l’image si quelque chose le copie, et casse discrètement le cache de couches, puisque le contexte change dès que ces fichiers changent.

Il ressemble trait pour trait à un .gitignore : un motif par ligne, un croisillon pour les commentaires, un point d’exclamation pour les exceptions. C’est précisément là qu’est le piège. Les deux fichiers sont traités par des codes entièrement différents, et les mêmes lignes peuvent donner des réponses opposées. Rien ne vous alerte, puisque les deux fichiers sont valides des deux côtés.

Cette page fait tourner les deux moteurs à la fois. Écrivez votre .dockerignore, indiquez un chemin, et vous verrez la décision du comparateur de Docker, celle des règles de git, la ligne responsable dans chaque cas et — c’est ce qui explique tout — le chemin sur lequel chacun a réellement porté.

Comment l’utiliser

  1. Collez ou écrivez le fichier. Chaque ligne apparaît en dessous avec la forme qu’elle prend après nettoyage et la manière dont elle sera comparée : chaîne exacte, préfixe, suffixe ou motif. Les boutons d’exemple chargent les quatre cas où les deux fichiers divergent, plus un où ils s’accordent.
  2. Indiquez un chemin. Relatif au contexte de construction, avec des barres obliques normales. Cochez la case s’il s’agit d’un dossier : cela ne concerne que les règles de git, et l’outil explique pourquoi.
  3. Lisez les deux verdicts. Chaque panneau nomme la ligne qui a tranché et le chemin sur lequel elle a porté. Une divergence est une vraie différence de comportement, pas une bizarrerie d’affichage.

Les quatre différences qui piègent tout le monde

La première ne vient à l’esprit de personne, et la suite de tests de Docker elle-même la consigne. Excluez tout avec un double astérisque, réintégrez un répertoire avec un point d’exclamation, et un fichier situé à l’intérieur part bel et bien vers le constructeur. Donnez à git les deux mêmes lignes et le fichier reste ignoré, car git parcourt le chemin du haut vers le bas et ne regarde jamais dans un répertoire qu’il a déjà exclu. Le comparateur de Docker, lui, continue d’évaluer les motifs après qu’un ancêtre a correspondu, si bien que l’exception ultérieure s’applique encore. Deux lignes identiques, résultats opposés.

La deuxième est celle qui coûte le plus de temps de construction. Un motif sans joker est comparé au chemin par simple égalité de chaînes, puis à chacun de ses répertoires parents ; rien d’autre. Une ligne portant node_modules exclut donc celui qui se trouve à la racine de votre contexte, et aucun autre. La copie imbriquée dans un paquet est empaquetée et envoyée à chaque construction. Dans un .gitignore, cette même ligne correspond à n’importe quelle profondeur, ce qui explique que le fichier ait l’air de fonctionner. Mettez deux astérisques et une barre devant, et Docker atteint aussi les copies imbriquées.

La troisième est un caractère qui s’évapore. Tout motif passe par la fonction de nettoyage de chemins de Go avant d’être utilisé, et cette fonction supprime la barre finale. Une ligne terminée par une barre ne vise donc pas ici les seuls répertoires : c’est le même motif sans la barre, et il correspondra tout aussi bien à un fichier de ce nom. Dans git, la barre finale est justement ce qui restreint un motif aux répertoires.

La quatrième est un caractère qui ne veut rien dire. La barre initiale est retirée à la lecture du fichier, et les commentaires du code de Docker précisent que les deux écritures sont équivalentes. Dans git, la barre initiale ancre le motif au répertoire où se trouve le fichier, et son absence est ce qui fait correspondre à n’importe quelle profondeur. Le même caractère : déterminant d’un côté, inerte de l’autre.

Limites assumées

Ceci compare, cela ne construit pas. L’outil dit si un chemin partirait vers le constructeur ; il ignore si le fichier existe, ce que pèse réellement votre contexte et ce que votre Dockerfile fait de tout cela. Le Dockerfile et le .dockerignore lui-même sont toujours transmis, quoi qu’en disent les motifs, parce que le constructeur en a besoin.

Les chemins sont traités comme séparés par des barres obliques normales, ce qu’utilise le constructeur Linux. Le comportement reproduit ici est celui du comparateur propre à Docker, et autant le dire franchement : il n’existe aucune spécification de ce format. Le comparateur est la définition, et la documentation ne le décrit pas tout à fait — elle cite une fonction de la bibliothèque standard de Go dont les règles de motifs n’ont aucun joker récursif, alors que l’implémentation compile chaque motif en expression régulière et en accepte un. Vingt-trois des cas de test de l’implémentation de référence elle-même reposent sur ce comportement.

Une règle a l’air d’être une différence et n’en est pas une. Docker transmet les crochets tels quels à une expression régulière : une classe de caractères se nie donc avec un accent circonflexe plutôt qu’avec le point d’exclamation d’un motif de shell — sauf que git accepte lui aussi le circonflexe, si bien que les deux écritures se comportent pareil des deux côtés. C’est signalé ici parce que c’est la supposition évidente, et qu’elle serait fausse.

Enfin, un commentaire ne compte comme tel que si le croisillon occupe le tout premier caractère de la ligne. Décalez-le d’une seule espace et il cesse d’être un commentaire pour devenir un motif correspondant à un fichier de ce nom. Cet ordre vient directement de l’implémentation de référence, qui cherche le croisillon avant de rogner les espaces.

Pourquoi est-ce gratuit ?

Comparer un chemin à une liste de motifs représente quelques centaines de lignes de manipulation de chaînes, et votre navigateur s’en charge pendant que vous tapez. Aucun serveur ne voit votre fichier : il n’y a donc rien à facturer ni de compte à créer.

Rien n’est envoyé. Ce que vous collez reste dans cet onglet.