Moby: Nouvelle demande de fonctionnalité : désactiver sélectivement la mise en cache pour des commandes RUN spécifiques dans Dockerfile

Créé le 24 sept. 2013  ·  245Commentaires  ·  Source: moby/moby

bifurquant de la discussion de #1384 :

Je comprends que -no-cache désactivera la mise en cache pour l'ensemble du Dockerfile. Mais serait-il utile si je pouvais désactiver le cache pour une commande RUN spécifique ? Par exemple, la mise à jour des référentiels ou le téléchargement d'un fichier distant, etc. D'après ce que j'ai compris, RUN apt-get update si mis en cache ne mettrait pas réellement à jour le référentiel ? Cela entraînera des résultats différents de ceux d'une VM ?

Si la désactivation de la mise en cache pour des commandes spécifiques dans le Dockerfile est rendue possible, les commandes suivantes dans le fichier n'utiliseraient-elles pas le cache ? Ou feraient-ils quelque chose d'un peu plus intelligent - par exemple, utiliser le cache si la commande précédente produisait les mêmes résultats (couche fs) par rapport à une exécution précédente ?

arebuilder kinfeature

Commentaire le plus utile

Qu'en est-il de CACHE ON et CACHE OFF dans le Dockerfile ? Chaque instruction affecterait les commandes suivantes.

Tous les 245 commentaires

Je pense que le moyen de lutter contre cela est de prendre le point dans le Dockerfile dans lequel vous voulez être mis en cache et de le marquer comme une image à utiliser dans votre futur Dockerfile FROM , qui peut ensuite être construit avec -no-cache sans conséquence, puisque l'image de base ne serait pas reconstruite.

Mais cela ne limiterait-il pas facilement l'entrelacement des commandes mises en cache et non mises en cache ?

Par exemple, disons que je veux mettre à jour mes fichiers repo et wget à partir d'un serveur et effectuer un tas d'étapes entre les deux - par exemple installer un logiciel à partir du repo (qui aurait pu être mis à jour) - effectuer des opérations sur le fichier téléchargé (qui aurait pu changer dans le serveur) etc.

Ce qui serait idéal, c'est un moyen de spécifier à docker dans le Dockerfile d'exécuter des commandes spécifiques sans cache à chaque fois et la seule réutilisation de l'image précédente s'il n'y a pas de changement (par exemple, pas de mise à jour dans le référentiel).

Ne serait-ce pas utile d'avoir ça ?

Qu'en est-il de CACHE ON et CACHE OFF dans le Dockerfile ? Chaque instruction affecterait les commandes suivantes.

Oui, j'utilise des commandes git clone dans mon Dockerfile, et si je veux qu'il se reclone avec les mises à jour, je dois, par exemple, ajouter un commentaire à la fin de la ligne pour déclencher une reconstruction à partir de cela ligne. Je ne devrais pas avoir besoin de créer un tout nouveau conteneur de base pour cette étape.

Un ID de conteneur peut-il être transmis à « docker build » en tant qu'instruction « ne pas mettre en cache après cet ID » ? Semblable à la manière dont « docker build » mettra en cache toutes les étapes jusqu'à une ligne modifiée dans un Dockerfile ?

Je suis d'accord que nous avons besoin d'un contrôle plus puissant et plus fin sur le cache de construction. Actuellement, je ne sais pas exactement comment exposer cela à l'utilisateur.

Je pense que cela deviendra plus facile avec les prochaines extensions d'API, en particulier le nommage et l'introspection.

Ce serait une excellente fonctionnalité. Actuellement, j'utilise des choses stupides comme RUN a=a some-command , puis RUN a=b some-command pour casser le cache

Obtenir un meilleur contrôle sur le cache rendrait l'utilisation de docker de CI beaucoup plus agréable.

@shykes

Que diriez-vous de changer --no-cache d'un bool à une chaîne et de lui faire prendre une regex pour savoir où dans le docker nous voulons casser le cache ?

docker build --no-cache "apt-get install" .

Je suis d'accord et j'ai suggéré cette fonctionnalité exacte sur IRC.

Sauf que je pense que pour préserver la compatibilité inverse, nous devrions créer un nouveau drapeau (disons "--uncache") afin que nous puissions conserver --cached comme un drapeau booléen (obsolète) qui se résout en "--uncache .*"

Le vendredi 7 février 2014 à 9h17, Michael Crosby [email protected]
a écrit:

@shykes
Que diriez-vous de changer --no-cache d'un bool à une chaîne et de lui faire prendre une regex pour savoir où dans le docker nous voulons casser le cache ?

docker build --no-cache "apt-get install" .

Répondez directement à cet e-mail ou consultez-le sur GitHub :
https://github.com/dotcloud/docker/issues/1996#issuecomment -34474686

Qu'est-ce que les autres pensent à propos de cela? Quelqu'un est-il prêt à implémenter la fonctionnalité ?

Je suis prêt à essayer de mettre cela en œuvre aujourd'hui si personne d'autre n'a commencé ?

J'ai commencé à travailler dessus - je voulais valider que l'approche semble bonne.

  • Le champ noCache de buildfile devient un *regexp.Regexp .

    • Une nil là-bas signifie ce que utilizeCache = true utilisé.

  • Passer une chaîne à docker build --no-cache envoie maintenant une chaîne d'expression régulière de validation au serveur.
  • Le simple fait d'appeler --no-cache donne une valeur par défaut de .*
  • L'expression régulière est ensuite utilisée dans une nouvelle méthode buildfile.utilizeCache(cmd []string) bool pour vérifier les commandes qui ignorent le cache

Une chose : pour autant que je sache, le package flag/mflag ne prend pas en charge les indicateurs de chaîne sans valeur, je vais donc devoir faire quelques manipulations supplémentaires pour prendre en charge à la fois --no-cache et --no-cache some-regex

Je pense vraiment que cela devrait être un nouveau drapeau distinct. Le comportement et la syntaxe de --no-cache sont déjà bien définis et utilisés dans de très nombreux endroits par de nombreuses personnes différentes. Je voterais pour --break-cache ou quelque chose de similaire, et je demanderais à --no-cache faire exactement ce qu'il fait aujourd'hui (car c'est un comportement très utile sur lequel beaucoup de gens s'appuient et qu'ils souhaitent toujours).

Quoi qu'il en soit, IANTM (je ne suis pas le mainteneur) donc ce ne sont que mes pensées personnelles. :)

@tianon --no-cache est actuellement bool, donc cela étend simplement le comportement existant.

  • docker build --no-cache - même comportement qu'avant : ignore le cache
  • docker build --no-cache someRegex - ignore toutes les commandes RUN ou ADD qui correspondent à someRegex

D'accord, tout va bien. Le problème est que --no-cache est un booléen, donc le comportement existant est en fait :

  • --no-cache=true - désactiver explicitement le cache
  • --no-cache=false - activer explicitement le cache
  • --no-cache - raccourci pour --no-cache=true

Je pense également que nous nous rendrions un mauvais service en créant des chaînes de regex de cas spéciaux "vrai" et "faux" pour résoudre ce problème, car cela créera un comportement potentiellement surprenant pour nos utilisateurs à l'avenir. ("Lorsque j'utilise --no-cache avec une expression régulière 'true' ou 'false', cela ne fonctionne pas comme il est censé le faire !")

@tianon oui tu as raison. J'ai jeté un coup d' œil rapide et les gens utilisent =true/false.

Heureux de modifier le PR pour ajouter un nouveau drapeau comme vous le suggérez, qu'en pensent les responsables ( @crosbymichael , @shykes) ? Cela signifierait également que je pourrais supprimer le code ajouté à mflag pour autoriser les drapeaux string/bool.

+1 pour l'approche @wagerlabs

@crosbymichael , @timruffles Ne

Considérez un environnement d'entreprise dans lequel quelqu'un souhaite simplement reconstruire une hiérarchie d'images existante pour mettre à jour certaines dépendances. L'arborescence Dockerfile existante peut être créée il y a des années par quelqu'un d'autre.

+1 pour l'approche @wagerlabs

+1 pour l'approche @wagerlabs bien que ce serait encore plus agréable s'il y avait un moyen de mettre en cache le buste sur un intervalle de temps également, par exemple

CACHE [interval | OFF]
RUN apt-get update
CACHE ON

Je comprends que cela puisse aller à l'encontre de l'idée que les conteneurs soient non déterministes, mais c'est exactement le genre de chose que vous voulez faire dans un scénario de déploiement continu où votre pipeline a de bons tests automatisés.

Comme solution de contournement, je génère actuellement des cache busters dans le script que j'utilise pour exécuter docker build et les ajoute dans le dockerfile pour forcer un cache bust

FROM ubuntu:13.10
ADD ./files/cachebusters/per-day /root/cachebuster
...
ADD ./files/cachebusters/per-build /root/cachebuster
RUN git clone [email protected]:cressie176/my-project.git /root/my-project

Je cherche à utiliser des conteneurs pour l'intégration continue et la possibilité de définir des délais d'expiration sur des éléments spécifiques dans le cache serait vraiment utile. Sans cela, je ne peux pas déployer. Forcer une reconstruction complète à chaque fois est beaucoup trop lent.

Mon plan actuel pour contourner ce problème consiste à injecter dynamiquement des commandes telles que RUN echo 2014-04-17-00:15:00 avec la ligne générée arrondie aux 15 dernières minutes pour invalider les éléments de cache lorsque le nombre arrondi saute. ala toutes les 15 minutes. Cela fonctionne pour moi car j'ai un script générant le fichier docker à chaque fois, mais cela ne fonctionnera pas sans ce script.

+1 pour la fonctionnalité.

Je veux aussi voter pour cette fonctionnalité. Le cache est ennuyeux lors de la construction de parties d'un conteneur à partir de référentiels git qui ne se mettent à jour que sur la branche master.
:+1:

@hiroprotagoniste Avoir un git pull dans votre ENTRYPOINT pourrait vous aider ?

@amarnus Je l'ai résolu de la même manière que l'idée de @tfoote . J'exécute la construction à partir d'un travail jenkins et au lieu d'exécuter la commande docker build directement, le travail démarre un script de construction qui génère le fichier Dockerfile à partir d'un modèle et ajoute la ligne 'RUN echo currentsMillies' au-dessus des commandes git. Grâce au sed et aux pipes, ce n'était qu'une question de minutes. Quoi qu'il en soit, je privilégie toujours cette fonctionnalité dans le cadre du Dockerfile lui-même.

Ajout de mon +1 pour l'approche @wagerlabs . J'ai aussi ce problème avec CI. J'utilise simplement une instruction echo RUN dynamique pour le moment, mais j'adorerais cette fonctionnalité.

+1 pour CACHE ON/OFF. Mon cas d'utilisation est également l'automatisation CI.

+1, en particulier la possibilité de définir un intervalle de cache de commandes d'exécution comme dans l'exemple de @cressie176

"Par exemple, la mise à jour des référentiels ou le téléchargement d'un fichier distant"

+1

Si cela peut aider quelqu'un, voici le morceau de code que j'utilise dans ma version Jenkins :

echo "Using build $BUILD_NUMBER for docker cachebusting"
sed -i s/cachebust_[0-9]*/cachebust_"$BUILD_NUMBER"/g Dockerfile

+1 pour CACHE ON/OFF

Comme alternative possible à l'approche CACHE ON/OFF, qu'en est-il d'un mot-clé supplémentaire comme "ALWAYS". Le mot-clé serait utilisé en combinaison avec une commande existante (par exemple "ALWAYS RUN" ou "ALWAYS ADD"). De par sa conception, le mot-clé "ALWAYS" ne va pas dans le cache pour terminer la commande adjacente. Cependant, il compare le résultat au CACHE (implicitement le cache pour les autres fois où la même ligne a été exécutée), en se liant à l'image mise en cache si le résultat de la commande ALWAYS est inchangé.

Je pense que le besoin sous-jacent est d'identifier des "instructions non idempotentes" . La commande ALWAYS le fait de manière très explicite. Mon impression est que l'approche CACHE ON/OFF pourrait tout aussi bien fonctionner, mais pourrait également nécessiter de nombreux basculements de blocs de code (ce qui peut encourager les utilisateurs à bloquer plus de lignes que nécessaire).

Je suis aussi plus pour un préfixe aux commandes, comme ALWAYS ou CACHE 1 WEEK ADD...

J'ai donc eu du mal avec ce problème pendant un certain temps et je voulais juste partager mon travail au cas où cela serait utile pendant que cela se règle. Je ne voulais vraiment pas ajouter quoi que ce soit en dehors du fichier docker à l'appel de construction ou modifier le fichier à chaque fois. Quoi qu'il en soit, c'est un exemple idiot mais il utilise le mécanisme d'ajout pour casser le cache et ne nécessite aucune manipulation de fichier.

From ubuntu:14.04

RUN apt-get -yqq update
RUN apt-get -yqq install git
RUN git clone https://github.com/coreos/fleet
ADD http://www.random.org/strings/?num=10&len=8&digits=on&upperalpha=on&loweralpha=on&unique=on&format=plain&rnd=new uuid
RUN cd fleet && git pull

Évidemment, vous pouvez choisir votre propre cas d'utilisation et la génération aléatoire du réseau. Quoi qu'il en soit, cela aidera peut-être certaines personnes.

Un autre +1 pour l'approche @wagerlabs

Un autre +1 à la fonctionnalité. Pendant ce temps, en utilisant la solution de contournement @cruisibesarescondev .

un +1 de plus pour la demande de fonctionnalité. Et merci à @cruisibesarescondev pour la solution de contournement

Un autre +1 pour la fonctionnalité.

Bravo @cruisibesarescondev pour la solution de contournement.

Je pense que le mot-clé ALWAYS est une bonne approche, d'autant plus qu'il a une sémantique simple et claire. Une approche légèrement plus compliquée serait d'ajouter un temps minimum (utile dans des choses comme une ferme de construction ou une intégration continue). Pour cela je proposerais une syntaxe "EVERY XXX" où XXX est un timeout. Et si cela fait plus de XXX depuis que le cache de cette commande a été construit, il doit réexécuter la commande. Et vérifiez si la sortie a changé. Si aucun changement, réutilisez le résultat mis en cache, en notant l'heure de la dernière mise à jour. Cela signifierait que CHAQUE 0 serait le même que TOUJOURS.

Pour une solution de contournement pour le moment, je génère mes Dockerfiles à l'aide de modèles empy en python et j'intègre les extraits suivants qui fonctionnent comme ci-dessus, sauf qu'ils ne détectent pas le même résultat lors de deux exécutions successives, mais forcent un redéclenchement toutes les XXX secondes. Au sommet:

@{
import time
def cache_buster(seconds):
    ts = time.time()
    return ts - ts % seconds
}@

Où je veux forcer une rediffusion :

RUN echo @(cache_buster(60))

Ce qui ressemble à ceci dans le Dockerfile

RUN echo 1407705360.0

Comme vous pouvez le voir, il arrondit aux 60 les plus proches, de sorte que chaque fois que 60 secondes s'écoulent, la prochaine exécution réexécute toutes les commandes suivantes.

+1 pour la syntaxe TOUJOURS. +.5 pour CACHE ON/CACHE OFF.

+1 pour la syntaxe TOUJOURS.

Oui, la syntaxe TOUJOURS semble très intuitive.

Je n'aime pas CACHE ON/OFF car je pense que les lignes devraient être "autonomes" et l'ajout de blocs à Dockerfiles introduirait beaucoup de "problèmes" (comme devoir vérifier "cette ligne est-elle couverte par le cache?" lors de la fusion .. .).

@kuon Je pense qu'il existe déjà un certain nombre de commandes qui affectent les instructions suivantes, par exemple USER et WORKDIR

Oui, c'est vrai, mais je ne les utilise pas pour la même raison. Je fais toujours RUN cd ... && ou RUN su -c ...&& .

Je préférerais une notation par blocs :

CACHE OFF {
    RUN ...
}

Ceci est plus explicite et évite d'avoir une ligne CACHE OFF insérée par erreur (cela déclencherait une erreur de syntaxe).

J'y réfléchis peut-être trop, les Dockerfiles ne sont pas réellement exécutés en production (juste lors de la création de l'image), donc désactiver le cache lors de la création ne fera pas beaucoup de mal. Mais je pense aussi que les Dockerfiles sont vraiment limitatifs (devoir enchaîner toutes les commandes avec un && en un seul RUN pour éviter de créer des milliards d'images, ne pas pouvoir utiliser de variables...).

Peut-être que ce problème est l'opportunité d'un nouveau format Dockerfile.

Je voudrais revenir sur ce que je viens de dire. J'ai lu ce que @shykes a dit dans un autre numéro https://github.com/docker/docker/pull/2266 et je suis également d'accord avec lui (Dockerfile doit rester un langage d'assemblage très simple).

J'ai dit que j'aimerais une variable ou des choses comme ça, mais cela peut être couvert par un autre langage, mais dans ce cas, chaque ligne d'un Dockerfile devrait être autonome, par exemple :

NOIMAGE ALWAYS RUN USER:jon  apt-get update

Ce qui exécuterait toujours la commande (pas de cache), mais ne créerait pas non plus d'image et n'utiliserait pas l'utilisateur jon.

Ce type de ligne autonome est beaucoup plus facile à générer à partir de n'importe quelle autre langue. Si vous devez vous soucier du contexte (utilisateur, cache, répertoire de travail), c'est plus sujet aux erreurs.

Cela peut-il être RUN! pour plus de facilité, s'il vous plaît ?

Une mise à jour sur celui-ci ?

La désactivation sélective du cache serait très utile. Je récupère des fichiers à partir d'un référentiel amazon s3 distant via la commande awscli (à partir de la boîte à outils amazon AWS), et je n'ai aucun moyen facile de supprimer le cache via une commande ADD (au moins je ne peux pas penser à un moyen sans modifier le Dockerfile pour le déclencher). Je pense qu'il existe de solides arguments pour que le contrôle soit rendu à l'utilisateur pour qu'il supprime sélectivement le cache lors de l'utilisation de RUN. Si quelqu'un a une suggestion pour moi, je serais heureux d'avoir de vos nouvelles.

Je voulais soulever un peu ce problème car c'est quelque chose dont nous avons un grand besoin.

Toujours convaincu que la syntaxe ALWAYS est l'idéale.

Que diriez-vous d'une simple déclaration BREAK .

@ cpuguy83 cela fonctionnerait également pour mon cas d'utilisation particulier.

Je ne sais pas s'il est techniquement possible d'avoir une seule commande à ne pas mettre en cache, mais les autres à mettre en cache. Probablement pas puisque docker est basé sur des différences incrémentielles.

La prise en charge de BREAK me donnerait cependant la parité des fonctionnalités avec ma solution de contournement actuelle basée sur la suggestion de @CheRuisiBesares.

En ce qui concerne mon post précédent, il suffirait en effet de simplement détruire le cache à partir de ce point du script, le reste serait simplement dû à une conception de script intelligente (et je pense que cela répondrait aux besoins de la plupart des gens). Est-ce faisable au lieu de désactiver sélectivement le bust de cache ?

@orrery Vous pourriez probablement « COPY _avant_ cette étape de construction. Si le(s) fichier(s) copié(s) sont différents, toutes les étapes suivantes ne devraient plus utiliser le cache (voir cette section ). Sale tour, mais peut résoudre votre cas.

Une clé de ALWAYS (ou de concepts similaires comme EVERY # DAYS ) est la comparaison de cache après la commande jointe. Pour moi (et je suppose que beaucoup d'autres), le but n'est pas de casser le cache en soi.

  • Le but est de s'assurer que nous arrêtons d'utiliser le cache si et quand le résultat de la commande (c'est-à-dire "mettre à niveau vers la version la plus récente") change.
  • En revanche, si le résultat correspond à une version mise en cache, nous souhaitons profiter du cache.

Cela répond au commentaire de @hellais puisque vous pouvez profiter du cache pour les commandes suivantes... si et seulement si la sortie de ALWAYS correspond à une version mise en cache (cela pourrait facilement être la majorité du temps).

Naturellement, la même logique _pourrait_ être incluse dans un modèle CACHE ON/OFF. La comparaison avec le cache est susceptible d'être moins chère que la réexécution de toutes les commandes suivantes, mais pourrait toujours être coûteuse. Si un bloc CACHE ON/OFF encourageait un utilisateur à inclure des commandes supplémentaires dans un bloc OFF (ce qui ne peut pas arriver avec ALWAYS ), cela pourrait contribuer à des différences significatives de performances.

Je suis exactement dans la même situation que @tfoote : j'utilise Docker pour CI et j'ai besoin de forcer l'expiration du cache.

+1 pour la syntaxe EVERY . La syntaxe ALWAYS ferait également le travail.

@claytondaley c'est un bon point. Cependant, il est toujours important d'avoir la possibilité de désactiver complètement la mise en cache d'une commande. Il y aura toujours un état caché qui est intrinsèquement invisible pour Docker. Par exemple, l'exécution d'une commande peut changer d'état sur un serveur distant.

@mkoval , vous _création _ d'états cachés comme un moment important pour utiliser ALWAYS , mais je ne pense pas que cela affecte ma logique de reprise du cache. Pour rendre l'exemple concret (bien qu'un peu trivial), une commande qui met à niveau un système tiers :

  • Crée un état caché (doit être exécuté ALWAYS ) et
  • Ne change pas le conteneur actuel

Si la prochaine commande n'implique pas un état caché (trivialement, une commande mv sur le conteneur), le cache sera fiable à 100%. Même conteneur, même commande, aucune dépendance vis-à-vis des informations cachées.

Si la commande suivante (ou toute commande ultérieure) implique des informations masquées, elle doit alors utiliser le mot-clé ALWAYS , en ne reprenant le cache que si le conteneur résultant correspond au cache.

@claytondaley ta solution

+1 pour cette fonctionnalité en utilisant TOUJOURS et CHAQUE X la syntaxe suggérée. CACHE ON/OFF me semble un peu maladroit, mais je l'utiliserais. J'aime aussi beaucoup la suggestion de @claytondaley de reprendre le cache dans la mesure du possible.

+1 pour la syntaxe TOUJOURS. en particulier pour les codes d'extraction de git repo.

+1 Pour l'une de ces solutions.

Je suis un peu confus. Comment la mise en cache peut-elle être réactivée une fois qu'elle a été désactivée ? Une fois que vous l'avez désactivé et que vous avez apporté une quelconque modification au conteneur, la réactivation de la mise en cache ne supprimerait-elle pas essentiellement les modifications apportées par ces commandes Dockerfile exécutées alors que la mise en cache était désactivée ? Je pensais que la seule raison pour laquelle nous pouvions faire de la mise en cache était que nous connaissions exactement la liste complète des commandes précédentes exécutées et pouvions garantir que ce qui se trouvait dans le conteneur était exactement le même. Si vous désactivez la mise en cache (et je parle du côté recherche), cela n'efface-t-il pas cette garantie? Ou s'agit-il simplement de ne pas remplir le cache ?

Ma compréhension des suggestions est que vous pouvez spécifier "TOUJOURS" dans le cadre d'une commande Dockerfile pour toujours exécuter à nouveau l'étape. Par exemple, "RUN ALWAYS git clone https://example.com/myrepo.git " sera toujours exécuté (clonant ainsi toujours le référentiel). Ensuite, ce que @claytondaley suggère, c'est qu'une fois cette commande réexécutée, Docker vérifie les modifications par rapport au cache. Si la somme de contrôle est la même (c'est-à-dire si le référentiel cloné n'a subi aucun changement, donc la couche la plus récente est identique à la même couche dans le cache), nous pouvons continuer avec le cache activé. Vous avez raison, une fois le cache invalidé, toutes les étapes suivantes ne peuvent pas utiliser le cache. Ces suggestions permettent simplement une plus grande granularité de contrôle sur le moment d'utiliser le cache, et sont également intelligentes pour reprendre à partir du cache lorsque cela est possible.

@curtiszimmerman... exactement

@duglin... L'idée peut être plus évidente si nous utilisons un proxy mathématique. Le cache (dans ce contexte) n'est que la mémoire du résultat de action B lorsqu'il est appliqué à state A afin que vous n'ayez pas à le retraiter. Supposons que j'exécute une séquence de commandes :

  • commencer par 6
  • TOUJOURS exécuter * x où la valeur de x est téléchargée à partir d'un dépôt git (et pourrait donc changer)
  • courir + 12

La première fois que j'exécute la commande, x vaut 8 donc j'obtiens (et mets en cache) la séquence suivante :

  • 6
  • 48 (comme résultat de * x appliqué à 6 )
  • 60 (comme résultat de + 12 appliqué à 48 )

Si ma machine atteint à nouveau l'état 48 (par n'importe quelle séquence)... et reçoit la commande + 12 , je n'ai pas à refaire le traitement. Mon cache sait que le résultat de cette commande est 60 .

La partie difficile est de savoir quand vous êtes à nouveau dans le même état ( 48 ).

  • Nous pourrions théoriquement comparer la machine après chaque commande à toutes les autres images mises en cache, mais cela demande beaucoup de ressources et a très peu de chances de trouver une correspondance.
  • Ma proposition est de rester simple. Chaque fois que nous sommes dans un état (par exemple 6 ) et que nous appuyons sur une commande (par exemple * x ), nous comparons le résultat au cache de la dernière fois (ou des fois) où nous étions dans le même état exécuter la même commande. Si l'état de la machine après ce processus est le même (par exemple toujours 48 ), nous reprenons le cache. Si la commande suivante est toujours + 12 , nous extrayons le résultat du cache au lieu de le traiter.

@claytondaley mais je ne comprends pas comment vous déterminez l'état actuel. Comme vous l'avez dit, nous ne comparons pas tous les fichiers du conteneur. La façon dont le cache fonctionne maintenant consiste essentiellement à strcmp la prochaine commande que nous voulons exécuter sur tous les conteneurs enfants connus du conteneur actuel. À la minute où vous sautez un conteneur dans le flux, je ne vois pas comment vous pouvez supposer que votre conteneur actuel est comme n'importe quel autre conteneur mis en cache sans vérifier tous les fichiers du système de fichiers. Mais peut-être que je ne comprends pas ce que vous faites.

Permettez-moi de le reformuler... étant donné un conteneur aléatoire (qui est essentiellement ce que vous avez si vous n'utilisez pas le cache), comment pouvez-vous trouver un conteneur dans le cache qui lui correspond sans différer tous les fichiers du récipient?

@claytondaley @duglin Déterminer si une opération "pas de cache" peut être mise en cache en l'absence de changement est un problème difficile, comme vous l'avez décrit. C'est aussi plus agréable à avoir que strictement nécessaire.

Personnellement, je serais plus qu'heureux si tout ce que j'avais était la capacité de garantir qu'une commande s'exécute toujours. Prenez un Dockerfile comme :

RUN install_stuff_take_forever
RUN always_do_it   #will not run every time
RUN more_stuff

Actuellement, la ligne always_do_it ne s'exécutera que la première fois, à moins que je modifie le texte pour forcer un buste de cache. Je pense que la plupart d'entre nous seraient heureux d'accepter que more_stuff s'exécute parfois inutilement (lorsque always_do_it n'a pas changé, si en échange nous pouvons conserver le cache pour install_stuff_take_forever .

RUN install_stuff_take_forever
NOCACHE
RUN always_do_it
RUN more_stuff

@pikeas, j'obtiens totalement une commande NOCACHE et c'est facile à faire. Ce que je ne reçois pas, c'est une commande qui le réactive sans diffr/hashing/quel que soit l'ensemble du système de fichiers.

J'ai lu l' explication de "couche" de Docker pour signifier que :

  • Docker crée une "couche" pour chaque commande.
  • Cette couche comprend uniquement les fichiers modifiés (ou éventuellement "enregistrés", qu'ils soient modifiés ou inchangés) par cette commande.
  • L'état actuel du système de fichiers est obtenu de manière logique (sinon opérationnelle) en vérifiant chaque couche dans l'ordre jusqu'à ce qu'elle trouve une version (la plus récemment mise à jour) de ce fichier particulier.

Dans ce cas, une comparaison de deux instances de la même commande est relativement bon marché. Vous n'avez qu'à comparer la couche supérieure (puisque chaque couche sous-jacente est partagée). Il existe une liste spécifique de fichiers qui ont été modifiés par la commande. Seuls ces fichiers sont inclus dans la couche. Certes... vous auriez besoin de comparer tous les fichiers de cette couche... mais pas l'ensemble du système de fichiers.

Il est également possible (bien qu'il ne soit pas garanti d'être exhaustif) de comparer uniquement la nouvelle couche à la dernière fois que la commande a été exécutée :

  • Dans la plupart des cas (git pull ou mise à niveau logicielle), la version actuelle sera soit (1) la même que les dernières versions ou (2) une nouvelle version... mais jamais - du moins rarement - un retour à une version précédente version.
  • Dans de rares cas (comme la mise à niveau vers dev-master puis le retour à une version stable), il est possible de revenir à une ancienne version. Cependant, ceux-ci sont assez rares, de sorte que la plupart des gens feraient probablement mieux de vérifier (fréquemment) uniquement la version la plus récente et de réexécuter les commandes dans les rares cas où ils effectuent une restauration.

Bien sûr, vous pouvez également effectuer une vérification de hachage sur toutes les versions précédentes... suivie d'une vérification complète des fichiers... pour offrir une prise en charge complète sans frais généraux.

si vous regardez en bas de https://github.com/docker/docker/pull/9934, vous verrez une discussion sur la prise en charge des options pour les commandes Dockerfile. Et s'il y avait une option --no-cache disponible sur tous (ou même juste RUN) qui signifiait "ne pas utiliser le cache" pour cette commande ? par exemple:
RUN --no-cache apt-get install -y my-favorite-tool
Cela désactiverait alors automatiquement le cache pour les commandes restantes également (je pense).
Cela résoudrait-il le problème ?

Entre "RUN ALWAYS" et "RUN --no-cache" qui sont sémantiquement identiques, je préférerais personnellement la syntaxe "RUN ALWAYS" plus naturelle. Je suis d'accord avec le dernier commentaire sur ce PR : je pense que --option casse la lisibilité et rendra Dockerfiles laid. De plus, je pense que les commandes Dockerfile devront être très distinctes des commandes réelles qui les suivent. Imaginez quelque chose comme "RUN --no-cache myapp --enable-cache" pour un exemple de syntaxe alambiquée qui commencerait à s'exprimer rapidement avec ce type d'option.

@curtiszimmerman votre exemple est très clair pour moi. --no-cache est pour RUN tandis que --enable-cache est pour myapp. Le placement compte. Par exemple, regardez :
docker exécuter -ti ubuntu ls -la
les gens comprennent que -ti est pour 'run' tandis que '-la' est pour 'ls'. C'est une syntaxe avec laquelle les gens semblent être à l'aise.
L'un des problèmes avec quelque chose comme RUN ALWAYS est l'extensibilité. Nous avons besoin d'une syntaxe qui puisse fonctionner pour toutes les commandes Dockerfile et prendre en charge la transmission de valeur. Par exemple, des personnes ont exprimé leur intérêt à spécifier l'UTILISATEUR pour certaines commandes.
RUN USER = foo myapp
est techniquement en train de définir un env var USER sur 'foo' dans le shell de myapp. Nous sommes donc ambigus ici.
Tandis que : RUN --user=foo myapp n'a pas ce problème.
Est : RUN var=foo myapp
essayer de définir et env var appelé 'var' ou une faute de frappe essayant d'obtenir une option RUN?
IOW, les chances de chevauchement avec une commande valide existante, IMO, sont bien moindres lorsque nous commençons les choses avec -- que de simplement autoriser un mot là-bas

Je préconise en fait la séquence inverse, EVERY <options> COMMAND . Plusieurs raisons:

  • Dans le cas de "user" et "cache" (au moins), ce sont vraiment des caractéristiques d'environnement qui pourraient envelopper n'importe quelle COMMANDE (bien qu'elles puissent ne pas affecter matériellement les autres).
  • La syntaxe RUN ALWAYS signifie changer l'interpréteur de commandes RUN , ce qui semble inutile.
  • Ce problème est encore pire avec RUN EVERY 5 days car les options attachées à EVERY créent encore plus d'ambiguïté. EVERY 5 days RUN est clair sur la commande que les options affectent. Nous avons le même problème avec RUN USER usr contre USER usr RUN . Tant que (1) les mots-clés de commande ne sont jamais des options ou (2) qu'il existe un moyen facile de les échapper, cela est sans ambiguïté.

Je pourrais commencer à préfixer les commandes avec leurs options ( ALWAYS AS user RUN ... ). Je suis juste très préoccupé par l'utilisation de longopts de style GNU pour les options, car ils ne sont pas très séparés des yeux anciens ou vitreux. Je peux m'imaginer en train de regarder une commande Dockerfile complexe après 20 heures en me demandant si wtf se passe. Mais je prédis -- les options vont se produire malgré tout.

Mais je prédis -- les options vont se produire malgré tout.

Rien n'est encore décidé, au contraire ; la syntaxe suggérée par @duglin est une _contre-proposition_ à une syntaxe qui a été proposée/décidée plus tôt. Veuillez lire #9934 pour plus d'informations à ce sujet.

De plus, @duglin n'est _pas_ la personne qui prend cette décision (du moins, pas seule). Certains des points que vous soulevez ont été mentionnés dans l'autre fil.

Je partage votre souci de lisibilité, mais je pense aussi que les autres syntaxes qui ont été proposées pourraient avoir le même problème si plusieurs options devaient être spécifiées.

Ce problème peut éventuellement être surmonté en formatant le Dockerfile pour plus de lisibilité. Je pense qu'il serait bon d'écrire quelques exemples supplémentaires pour tester/vérifier si la lisibilité est un problème lorsqu'il est correctement formaté.

Et, oui, votre contribution est la bienvenue à ce sujet.

Je suis toujours très -1 pour laisser le Dockerfile lui-même définir où le cache
devrait et ne devrait pas être appliqué. Je n'ai pas encore vu un bon exemple d'un
Dockerfile qui n'a pas pu être réécrit pour supprimer le cache de manière appropriée et
naturellement lorsque la ressource sous-jacente devait être mise à jour.

Avoir un drapeau sur "docker build" pour arrêter le cache à un endroit particulier
serait beaucoup plus flexible, IMO (et remettrait le contrôle du cache
entre les mains de l'opérateur système qui gère ce cache de toute façon).

+1 sur le -1 de @tianon (c'est donc un -1 !), et l'ajout d'un indicateur pour casser à l'étape N semble raisonnable. Considérant qu'une fois le cache cassé, il l'est de toute façon pour le reste du Dockerfile, je pense que cela a du sens.

Le principal besoin en est que le mécanisme de mise en cache de Docker est directement lié au stockage et au transport de l'image, ce qui permet une mise en cache efficace mais au détriment d'images beaucoup plus grandes. Alors corrigeons ça !

Sans dire ce que je ressens à propos de cette fonctionnalité - pas encore sûr, pour être honnête - comment imaginez-vous que quelqu'un dise (depuis "docker build") de s'arrêter à l'étape N ? Cela semble un peu fragile alors qu'aujourd'hui l'étape N serait l'étape N+1 demain.
Il semble que nous ayons besoin d'un moyen d'ajouter une "étiquette" quelconque dans le Dockerfile afin que les utilisateurs puissent référencer cette étiquette à partir de la ligne de commande de construction.
Si nous avions cela, je ne suis pas sûr de voir une grande différence entre cela et l'ajout d'une commande "STOP-CACHING" qui apparaît dans le Dockerfile.
Quel est un bon exemple de cmd Dockerfile qui casse le cache à chaque fois ?

Eh bien, c'est en fait pourquoi il a été initialement question d'en faire un
regexp basée sur le contenu de la ligne, avec laquelle je serais également d'accord (surtout depuis
c'est beaucoup plus facile à scripter que de savoir exactement quel numéro d'étape vous
je ne veux pas mettre en cache - pas moyen que j'écrive une copie complète de la version actuelle
Analyseur Dockerfile dans Bash, merci :D).

Tianon Gravi [email protected] a écrit :

Eh bien, c'est en fait pourquoi il a été initialement question d'en faire un
regexp basée sur le contenu de la ligne, avec laquelle je serais également bien (en particulier
puisque
c'est beaucoup plus facile à scripter que de savoir exactement quel numéro d'étape
vous
je ne veux pas mettre en cache - pas moyen que j'écrive une copie complète de la version actuelle
Analyseur Dockerfile dans Bash, merci :D).

J'aimerais réitérer ma suggestion précédente, que TOUJOURS/briseur de cache
"RUN" devrait juste être "RUN!" pour conserver la structure de commande à 1 mot (?).

Il semble fastidieux de devoir éditer un Dockerfile (en ajoutant quelque chose qui est fondamentalement aléatoire car il s'agit d'un espace réservé) afin de casser le cache à une étape spécifique. J'utiliserais une option CLI docker build qui exécute toujours une certaine étape, mais je suis tout à fait d'accord avec dire qu'il est difficile de rechercher le numéro de ligne spécifique afin de le git clone juste pour pousser Docker à cloner le référentiel au lieu de travailler à partir du cache.

@curtiszimmerman J'ai suggéré (!) Parce que cela indique quelque chose qui s'apparente à l'urgence en anglais. ("Vous devriez faire ceci!")

Je pense que le Dockerfile est au moins un endroit approprié pour définir quelles commandes ne doivent pas être mises en cache. Devoir construire avec "--no-cache=git" (je me rends compte que ce n'est pas quelque chose que vous avez suggéré, mais vous ne m'avez rien suggéré à citer/comparer) semble plus fastidieux.

Pourquoi se concentrer sur RUN ? Pourquoi ne pas autoriser la suppression du cache pour n'importe quelle commande ?
Cela ressemble à l'ajout d'un :
BUSTE-CACHE
type de commande Dockerfile serait beaucoup plus flexible. Et pour vraiment ajouter de la flexibilité, il pourrait éventuellement autoriser un indicateur :
BUSTE-CACHE $doit
où cela ne s'applique que si $doit est défini - alors si nous ajoutons la prise en charge d'une option -e lors de la construction ( https://github.com/docker/docker/pull/9176 ) alors les gens pourraient faire :
docker build -e doit=true ...

@zamabe Oh, j'utiliserais totalement RUN! , désolé. Ici, j'utilisais (!) pour dire "C'est inhabituel!" à propos de l'édition d'un Dockerfile chaque fois que je veux casser le cache à une étape spécifique. De toute façon, je pourrais casser le cache dans un Dockerfile avant une étape spécifique serait utile (et pour une victoire supplémentaire, si l'étape après cette commande de suppression de cache est le même résultat que ce qui se trouve dans le cache, soyez assez intelligent pour continuer à partir du cache ). BUST-CACHE ou ALWAYS RUN (ou RUN ALWAYS ) ou RUN! ... Vraiment n'importe quel mécanisme supportant cette fonctionnalité, je l'utiliserais.

@duglin Désolé ? Le titre du bogue dit RUN, ce qui est juste plus facile à donner à titre d'exemple.

@curtiszimmerman ah.

En aparté; Je pense que la revalidation du cache (?) est un peu au-delà de l'invalidation du cache recherchée par ce bogue. Bien que j'aime ce que vous suggérez, je réorganiserais simplement mon Dockerfile pour placer les commandes de suppression de cache aussi près que possible de la fin. Cela annule les avantages tirés d'un _possible_ accès au cache puisque vous effectuez _toujours_ les calculs/comparaisons nécessaires, ce qui est probablement une pénalité plus lourde que de terminer la construction Dockerfile normalement, car les personnes utilisant le cache-busting espèrent/attendent probablement un échec du cache.

@zamabe D'accord. Je suggère que si la mise en œuvre est assez triviale pour faire cela, peut-être une commande spéciale pour continuer à partir du cache, qui est distincte de l'identifiant de contournement du cache. Quelque chose comme DISABLE-CACHE à un certain moment pour désactiver le cache à chaque fois, et si vous avez un cas d'utilisation où le reste du Dockerfile serait coûteux par rapport à continuer à partir du cache, quelque chose comme DISABLE-CACHE? serait continuer à partir du cache si possible. Ce n'est pas une suggestion, juste une démonstration pour transmettre ce dont je parle.

+1 pour les codes d'extraction de git repo

+1

Ce serait énorme ! En ce moment, j'ai une partie de mon intégration continue en écrivant le hachage git commit dans le Dockerfile (en écrasant un espace réservé) juste pour casser le cache des clones git.

J'ai soumis ce PR : https://github.com/docker/docker/pull/10682 pour résoudre ce problème.
Bien qu'il ne prenne pas en charge la réactivation de la mise en cache, je ne pense pas que ce soit possible aujourd'hui.

+1

Je génère un nombre aléatoire dans le Dockerfile et il est mis en cache...
+1 pour une instruction NOCACHERUN

+1
Devrait être vraiment utile pour certains RUN que nous devons faire à chaque fois sans tout reconstruire

J'ai remarqué que git clone atteindra le cache mais pas go get -d . des idées pourquoi?

_Revue collective avec @LK4D4 @calavera @jfrazelle @crosbymichael @tiborvass_

Clôturez ceci car nous ne voyons pas beaucoup de cas d'utilisation dans le monde réel (voir le n° 10682 connexe pour plus de détails).

+1 pour RUN. Ce serait sympa.

+1

docker 1.9 introduit des variables de temps de construction ; il est possible de (mal) utiliser ceux-ci pour forcer la rupture du cache ; pour plus d'informations, voir https://github.com/docker/docker/issues/15182

Comment ce n'est pas encore une fonctionnalité ?

@hacksaw6 Vous pouvez jeter un œil à ce qui a été dit ici : https://github.com/docker/docker/pull/10682

+1

+1

+1 comment est-ce que ce n'est même pas encore une chose!!!!?!

+1 Nous avons besoin de cette fonctionnalité pour fournir un contrôle plus granulaire pour la construction.

+1

+1

+1

+1

+1 très utile
(en utilisant la solution de contournement @timruffles pour le moment)

+1

+1

+1

il pourrait être utile que les gens publient leurs cas d'utilisation au lieu de simplement +1 afin que les gens puissent voir pourquoi il s'agit simplement d'une fonctionnalité nécessaire.

+1, est arrivé ici via Google à la recherche d'une solution à un clone git en cache.

Mon cas d'utilisation :
J'ai une configuration docker qui, lors de sa construction, appellera via gradle une application de microservice groovy en mode de fonctionnement à sec. Il en résultera que toutes les bibliothèques Java dépendantes (à partir d'un référentiel mvn distant) seront téléchargées dans le référentiel mvn docker local. L'essai à sec exécutera simplement l'application et revient immédiatement, mais garantit que toutes les dépendances de la bibliothèque Java sont chargées.
Pendant la phase d'exécution du docker, la même application sera exécutée via le mode gradle --offline. C'est-à-dire que l'application de microservice se chargera simplement à partir du répertoire du référentiel mvn local. aucune récupération de bibliothèque à distance coûteuse et longue n'aura lieu. Lorsque je publie maintenant une nouvelle version d'instantané d'une telle bibliothèque, docker ne déclenchera pas de récupération à distance lors d'une construction (c'est-à-dire qu'il n'appellera pas mon cmd gradle dryrun), à moins que je modifie le répertoire docker.

Mon cas d'utilisation : récupérer la dernière version tierce d'une bibliothèque à utiliser sur une image. J'utilise docker hub pour cela et AFAIK, il ne mettra rien en cache. Mais qui sait quand cela peut changer.
S'il y avait un indicateur de commande tel que NOCACHE dans docker, cela le garantirait, peu importe où l'image est construite.

Il est pire de dépendre d'une "fonctionnalité" du système de construction que d'une dernière version, à mon humble avis.

Que diriez-vous d'ajouter une nouvelle syntaxe : FORCE RUN git clone .... ?

En ce moment, j'utilise RUN _=$(date) git clone ... pour invalider le cache.

@c9s est-ce que ça marche vraiment ? Je ne pense pas.

@duglin définissant la variable d'environnement fonctionne pour moi. le "FORCE RUN" n'est qu'une proposition :]

@c9s Je ne vois pas comment la définition de la RUN _=$(date) echo hi il utilise le cache de la 2ème version.

@duglin tu as raison :| cela n'invalide pas le cache

@c9s essayez ceci à la place

FROM foo
ARG CACHE_DATE=2016-01-01
RUN git clone ...
docker build --build-arg CACHE_DATE=$(date) ....

@thaJeztah Merci ! Ça marche!

+1 clonage git repos (cas d'utilisation)

Tant de +1, si vous extrayez le dépôt git dans votre fichier docker, le cache empêche la construction de vos images. Il est assez difficile de pousser les builds via CI.

+1 clonage git repos (c'est très ennuyeux que l'image doive être construite à partir de zéro chaque fois qu'une petite modification a été faite dans un git repo)

@Vingtoft Si vous mettez à jour les fichiers du référentiel, votre cache est invalidé.

@itsprdp Je ne le savais pas, merci d'avoir clarifié.

@itsprdp je viens de tester. Lorsque je mets à jour le référentiel et que je crée l'image, Docker utilise toujours le cache.
Peut-être que j'ai mal compris quelque chose ?

@itsprdp Ce n'est pas correct d'après mon expérience. J'ai fait un nouveau commit dans un dépôt à tester, et lors de la construction à nouveau, il utilise le même cache.

Si je modifie le fichier docker avant le dépôt, il sera bien sûr supprimé du cache, mais la simple mise à jour d'un dépôt ne semble pas résoudre ce problème.

@RyanHartje Désolé pour la confusion. Il est censé invalider le cache si le référentiel est mis à jour et c'est quelque chose à considérer par les contributeurs.
Le cas d' utilisation attendu par

@itsprdp Seule la mise à jour des fichiers modifiés dans un référentiel serait génial, mais moins (ou devrais-je dire plus ?) ferait aussi bien.
Dans mon cas d'utilisation (et bien d'autres), le véritable git pull ne prend pas longtemps : c'est la construction de tout le reste qui tue le flux de développement.

+1, cache utilisé lors du clonage git :(

Une solution intégrée serait bien, mais en attendant, vous pouvez casser le cache à une instruction Dockerfile spécifique en utilisant ARG .

Dans le Dockerfile :

ARG CACHEBUST=1
RUN git clone https://github.com/octocat/Hello-World.git

Sur la ligne de commande :

docker build -t your-image --build-arg CACHEBUST=$(date +%s) .

Définir CACHEBUST sur l'heure actuelle signifie qu'il sera toujours unique et que les instructions après la déclaration ARG dans le Dockerfile ne seront pas mises en cache. Notez que vous pouvez également compiler sans spécifier le CACHEBUST build-arg, ce qui l'obligera à utiliser la valeur par défaut de 1 et à préserver le cache. Cela peut être utilisé pour toujours vérifier les nouvelles copies des dépôts git, extraire les dernières dépendances SNAPSHOT, etc.

Edit: Ce qui, euh, est exactement ce que @thaJeztah a dit. Je vais laisser cela comme une description supplémentaire de sa solution.

@shane-axiom Que diriez-vous d'utiliser le hachage git commit comme valeur pour CACHEBUST ?

export CACHEBUST=`git ls-remote https://[email protected]/username/myRepo.git | grep refs/heads/develop | cut -f 1` && \
echo $CACHEBUST && \
docker build -t myDockerUser/myDockerImage \
   --build-arg blah=blue \
   --build-arg CACHEBUST=$CACHEBUST \
   .

Basé sur des indices de http://stackoverflow.com/questions/15677439/how-to-get-latest-git-commit-hash-command#answer -15679887

@pulkitsinghal Cela semble merveilleux pour casser le cache des dépôts git. Pour d'autres utilisations (telles que l'extraction de dépendances SNAPSHOT, etc.), l'approche d'horodatage toujours éclatante fonctionne bien.

+1 pour CACHE ON | DÉSACTIVÉ

+1

+1

N'oubliez pas à propos de l'approche @CheRuisiBesares , vous pouvez toujours utiliser ADD https://www.random.org/strings/?num=16&len=16&digits=on&upperalpha=on&loweralpha=on&unique=on&format=plain&rnd=new uuid comme solution de contournement pour les problèmes de cache.

Pour poster un cas d'utilisation supplémentaire...

COPY package.json /usr/src/
RUN npm install

Dans notre package.json nous pointerons généralement vers une balise master pour certaines de nos dépendances privées de github. Cela signifie que nous n'obtenons jamais vraiment le dernier master moins que nous ne modifiions le fichier package.json (généralement il suffit d'ajouter à la description un - à la description puis de le supprimer pendant le test).

Un RUN NO CACHE à la place de RUN semble être une bonne solution.

+1

J'ai un problème similaire pour l'installation de npm qui utilise le cache et n'utilise pas ma nouvelle bibliothèque publiée dans npm.

Ce serait formidable si je pouvais désactiver le cache par commande RUN dans le fichier docker.

@brycereynolds @mmobini voir https://github.com/docker/docker/issues/1996#issuecomment -172606763 pour casser manuellement le cache. Cependant, _ne pas_ spécifier une version spécifique des packages qui doivent être installés peut ne pas être une bonne pratique, car le résultat final de votre Dockerfile (et du code source) n'est plus garanti d'être reproductible (c'est-à-dire qu'il se construit avec succès aujourd'hui, mais ne pas demain, car l'un des packages a été mis à jour). Je peux voir que cela est "ok" pendant le développement, mais pour la production (et les versions automatisées sur Docker Hub), la meilleure approche consiste à spécifier explicitement une version. Cela permet également aux utilisateurs de vérifier les packages exacts qui ont été utilisés pour produire l'image.

J'ai un cas d'utilisation où le fait de ne pas pouvoir invalider le cache cause des problèmes. J'exécute des applications Dropwizard (Java REST Services construits avec Maven) à partir de Docker et un système automatisé effectue toutes les constructions et le déploiement de conteneurs pour moi. J'inclus un Dockerfile dans mon repo et il fait le reste. Le système exécute une version de production et une ou plusieurs versions de développement de mon application. Les versions de développement sont là où j'ai des problèmes.

Pendant le développement, certaines dépendances du projet ont SNAPSHOT dans leurs numéros de version. Cela indique à Maven que la version est en cours de développement et qu'il devrait en sortir une nouvelle version à chaque build. Par conséquent, une structure de fichier identique peut donner lieu à deux versions distinctes. C'est le comportement souhaité, car des bogues peuvent avoir été corrigés dans une dépendance SNAPSHOT. Pour prendre en charge cela, il serait utile de forcer Docker à exécuter une commande particulière, car il n'y a aucun moyen de déterminer l'effet de la commande en fonction de l'état actuel du système de fichiers. La majorité des projets Java vont se heurter à cela, car les dépendances SNAPSHOT de style Maven sont utilisées par plusieurs systèmes de construction différents.

@ctrimble Vous pouvez utiliser --no-cache , ou --build-arg pour invalider le cache.
Vous pouvez minimiser l'effet de --no-cache en ayant une image de base avec toutes les commandes pouvant être mises en cache.

@cpuguy83 merci pour la réponse. J'ai lu le fil et je comprends les options actuelles. J'ai ouvert un ticket avec le système de construction que j'utilise pour fournir un argument de contournement du cache. Produire deux images distinctes pour une seule application semble être de nombreux obstacles à franchir pour accélérer les builds. Il serait beaucoup plus simple de pouvoir spécifier quelque chose comme :

  1. faire des choses qui peuvent être mises en cache si le système de fichiers est identique
  2. faire une chose qui pourrait changer le système de fichiers en fonction du moment où il est exécuté
  3. faire d'autres choses qui pourraient être mises en cache si l'étape précédente n'a pas modifié le système de fichiers

Ce modèle apparaîtra fréquemment dans les versions de développement. Ce serait bien d'avoir une sémantique pour cela dans le Dockerfile.

@ctrimble La suppression du cache sur une étape entraînera toujours la

@ cpuguy83 exactement. La sémantique de mon système de build est temporelle pour les builds de développement. Je dois sélectionner les versions correctes plutôt que la mise en cache. J'aimerais vraiment avoir les deux.

Il y a eu une discussion considérable ici, désolé si cela a déjà été suggéré, mais que se passe-t-il s'il y avait quelque chose comme ça :

CHECK [FILE_PATH]

Tout ce que docker ferait est de stocker le MD5 (ou tout autre hachage) du fichier et s'il change, toutes les étapes suivantes sont invalidées.

Je ferais probablement quelque chose comme :

CHECK Gemfile
CHECK package.json
CHECK composter.json
CHECK project.json

Peut également vouloir activer une vérification qui s'écoule après une période de temps. Le paramètre cache_valid_time Ansible pour le plugin apt pourrait vous inspirer : http://docs.ansible.com/ansible/apt_module.html

Pour cela, la syntaxe serait :

EXPIRE 1234567 
RUN apt-get update
RUN bundle install

Docker connaîtrait l'heure de la dernière exécution et calculerait si le temps s'était écoulé en fonction de « maintenant ».

@atrauzzi Nous prenons simplement en charge --squash sur build now en 1.13 (expérimental uniquement pour l'instant).

@cpuguy83 Y a-t-il des documents ou des explications sur --squash n'importe où sur lesquels je peux lire ? Au début, le nom ne donne pas l'impression qu'il fait ce que je pense. Mais je peux me tromper (et je me trompe très probablement) !

@atrauzzi oui, dans la référence de construction.

Fondamentalement, --squash préserve à la fois le cache des calques et crée une 2ème image qui est comme si tout dans le Dockerfile se passait dans un seul calque.

Je ne vois pas pourquoi il faudrait vérifier qu'un cache de fichiers est toujours valide individuellement, ADD et COPY font déjà pour tout ce qui est copié.

@ cpuguy83 Bon point, je ne le pensais même pas, et bien sûr je l'utilise déjà.

Qu'en est-il de l'approche horodatage/durée ? Est-ce faisable avec ce qui est déjà disponible ?

Qu'en est-il de l'approche horodatage/durée ? Est-ce faisable avec ce qui est déjà disponible ?

Grâce à build-args ;

ARG expire_after=never
RUN do some thing
docker build --build-arg expire_after=2016-12-01 -t foo .

changer l'argument de construction pour casser le cache

+1 pour une manière plus propre

+1 pour une manière plus propre

Il devrait également y avoir des options distinctes pour désactiver la lecture du cache et pour désactiver l'écriture dans celui-ci. Par exemple, vous pouvez vouloir recréer une image à partir de zéro et ignorer les couches mises en cache, tout en écrivant les nouvelles couches résultantes dans le cache.

+1

Puis-je suggérer de transmettre le numéro d'étape à la commande de construction ?

Quelque chose comme ça:
docker build --step 5 .

Il ignorerait tous les caches après et y compris l'étape 5 pendant la construction.

+1
S'il te plaît.

CACHE ON|OFF +1

Le problème avec ces commandes CACHE ON|OFF est qu'à quelque étape que le cache soit désactivé, il n'y a aucun moyen de mettre en cache d'autres étapes. La seule commande sensée serait ENDCACHE .

C'est une idée/ethos valable. La commande est censée regrouper toutes les couches non mises en cache en une seule couche au moment où le cache est réactivé. Bien sûr, vous pouvez toujours discuter de la meilleure dénomination/correction de la sémantique/syntaxe préférée de la fonctionnalité.

+1

+1 la fonctionnalité indispensable

D'accord pour CACHE ON|OFF +1

+1 serait incroyable.

Je n'ai pas vraiment compris la façon dont Docker met en cache les étapes précédentes et j'ai passé une demi-journée à rechercher pourquoi mon système ne se construit pas correctement. C'était la mise en cache "git clone".

J'adorerais avoir le mot-clé ALWAYS .

Comment c'est fermé ?

Quelle est la meilleure solution de contournement ?

J'ai essayé https://github.com/moby/moby/issues/1996#issuecomment -185872769 et cela a fonctionné
Dans le Dockerfile :

ARG CACHEBUST=1
RUN git clone https://github.com/octocat/Hello-World.git

Sur la ligne de commande :

docker build -t your-image --build-arg CACHEBUST=$(date +%s)

Pourquoi ne pas créer une nouvelle commande similaire à RUN mais ne met jamais en cache RUNNC pour RUN NO CACHE ?

Je peux confirmer, @habeebr (https://github.com/moby/moby/issues/1996#issuecomment-295683518) - je l'utilise en combinaison avec https://github.com/moby/moby/issues/1996# questioncommentaire -191543335

+1

RUNNC est une excellente idée !

Pourquoi ce problème a-t-il été clos ? Entre la myriade de doublons demandant essentiellement la même chose et le long historique de commentaires de plusieurs de ces doublons, il semble évident qu'il existe un intérêt sain à voir cette fonctionnalité disponible.

Je comprends que c'est difficile, et peut-être que personne n'a suggéré une solution suffisamment élégante qui à la fois réponde au besoin et soit suffisamment propre pour être un ajout Docker attrayant... mais cela ne signifie pas _qu'il n'y en a pas_.

Le seul autre argument que j'ai entendu en faveur de la clôture est qu'il existe d'autres moyens d'y parvenir ... mais cet argument ne passe pas vraiment non plus. Créer plusieurs images de base dans le seul but de contourner le manque de contrôle du cache est difficile à manier, inventer une invalidation via un ARG est obtus et peu intuitif. J'imagine que les utilisateurs veulent utiliser ces "solutions de contournement" à peu près autant que les développeurs Docker veulent incorporer officiellement un hack bâclé dans l'outil.

ce n'est pas difficile : https://github.com/moby/moby/pull/10682
solution facile, UX facile. Tout simplement pas de consensus clair sur l'opportunité de le faire.

Wow, juste wow...

Je l'aurais déjà mis en œuvre juste pour ne pas avoir à en entendre parler, peu importe qu'il y ait un consensus clair sur le fait que la base d'utilisateurs le veut. Je n'ai pas été du côté des développeurs d'un si grand projet open source, seulement des projets beaucoup plus petits, alors peut-être que j'ai raté quelque chose.

+1

+1 pour une sécurité raisonnable et de meilleures performances

+1

+1

+1

+1

+1

+1

Pouvez-vous arrêter de spammer le +1 ? Utilisez simplement la fonction de réaction pour voter.

Tout changement?
Je ne sais toujours pas pourquoi ce problème est fermé.
À mon avis, c'est une fonctionnalité indispensable qui gère parfaitement l'extraction de version à partir du référentiel git distant.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

Pourquoi fermer ça ? je pense que c'est utile

+1

+1

+1

Actuellement, le moyen le plus simple de désactiver le cache pour une couche (et les suivants) :

Dockerfile

ARG CACHE_DATE
RUN wget https://raw.githubusercontent.com/want/lastest-file/master/install.sh -O - | bash

Et lorsque vous construisez l'image, --build-arg doit être ajouté

docker build  --build-arg CACHE_DATE="$(date)"

Ensuite, la commande wget sera exécutée à chaque fois que vous créez l'image, plutôt que d'utiliser un cache.

RUNNC ou CACHE OFF serait bien

en attendant, ça a l'air prometteur :
http://dev.im-bot.com/docker-select-caching/

C'est:

screenshot 2018-05-26 19 03 09

je vais aller me calmer et rejoindre le troupeau :

+1

Oui, j'ai besoin d'une mise en cache sélective sur les commandes. Mon COPY échoue 80% du temps si je ne change qu'un mot dans un fichier de configuration. Je voudrais ne jamais mettre en cache mon COPY mais mettre en cache tout le reste. Avoir un CACHE ON et un CACHE OFF serait génial.

RUN X
RUN X
CACHE OFF
COPY /config /etc/myapp/config
CACHE ON

@shadycuz Vous ne pourrez jamais "réactiver" le cache après l'avoir désactivé/invalidé à l'aide de n'importe quelle méthode. La construction ne pourra pas vérifier (dans un laps de temps raisonnable avec une quantité raisonnable de ressources) que la couche non mise en cache n'a pas changé quelque chose d'autre dans le système de fichiers qu'elle devrait prendre en compte dans les nouvelles couches. Afin de minimiser l'impact de devoir toujours extraire un fichier de configuration externe, vous devez placer votre directive COPY aussi loin que possible dans le Dockerfile (afin que Docker puisse utiliser le cache de construction pour autant de la processus de construction que possible avant que le cache ne soit invalidé).

Pour invalider le cache à un moment spécifique du processus de construction, vous pouvez vous référer à l'un des autres commentaires sur l'utilisation de --build-arg et ARG mentionnés précédemment ici.

@shadycuz @curtiszimmerman Oui, nous ne pouvons conserver que CACHE OFF mais pas CACHE ON , car les couches suivantes doivent être reconstruites si une ancienne couche est modifiée.

Je suis d'accord que CACHE ON n'a aucun sens d'un point de vue technique. Cela aide à exprimer plus clairement l'intention, quelles couches sont en réalité destinées à être invalidées cependant.

Une solution plus flexible serait une commande similaire à RUN qui permettrait à un code shell de déterminer si le cache doit être invalidé. Un code de sortie de 0 pourrait signifier « utiliser le cache » et 1 « invalider le cache ». Si aucun code shell n'est fourni, la valeur par défaut pourrait être d'invalider le cache à partir de maintenant. La commande pourrait être appelée INVALIDATE par exemple.

pourquoi cela a-t-il été fermé sans commentaire ?

Il y avait un commentaire, mais il est caché par github
https://github.com/moby/moby/issues/1996#issuecomment -93592837

+1

Cette fonctionnalité serait une bouée de sauvetage pour moi en ce moment.

+1

Fermer ceci car nous ne voyons pas beaucoup de cas d'utilisation dans le monde réel

212 commentaires et comptage, mais toujours pas de cas d'utilisation ? Cela semble assez ignorant.

+1

+1

+1

+1

+1

le problème est toujours là et nécessite toujours une solution. Il existe encore de nombreuses utilisations dans le monde réel.

+1

Je soupçonne que les développeurs Docker ne sont pas incités à mettre en œuvre cela, pour protéger leur infrastructure de bâtiment centralisée contre les DDsS par des demandes sans cache.

Je soupçonne également qu'une infrastructure parallèle facilitant les builds sans cache serait intéressante pour les utilisateurs d'entreprise.

Dans l'ensemble, ce problème ne concerne pas une fonctionnalité logicielle, mais un problème de mise à l'échelle du service.

@jaromil Ce n'est pas tout à fait vrai, car ce n'est pas non plus possible sur les référentiels auto-hébergés.

Quel logiciel existe-t-il pour exécuter un référentiel auto-hébergé ? Je ne sais pas trop à quoi vous faites référence.
Une solution simple auto-hébergée pourrait être un cron clonage git repos et runnig docker build --no-cache - je suis sûr que ce problème ne peut pas se produire sur un logiciel open source : n'importe qui est alors capable de modifier la ligne de commande de docker build.

@jaromil Je ne pense pas que ce soit le problème. Il serait plus efficace de l'avoir pour les projets open source de DockerHub (ainsi que les projets payants, ils ne facturent pas le nombre de versions). Dans un environnement CI/CD avec des builds fréquents, cela devient encore pire.

Tant que vous devez le faire (vous utilisez docker et git et ne voulez pas avoir 5 conteneurs exécutant des volumes partagés), vous devez reconstruire le conteneur et télécharger à chaque fois que vous téléchargez une nouvelle version. L'ensemble du conteneur.
Avec un indicateur de non-cache dans le code, chaque fois que vous exécutez la version, vous construisez et remplacez simplement cette couche unique au lieu du conteneur entier pour mettre à jour la version.

À propos du représentant auto-hébergé, vous seriez surpris. Je comprends le commentaire de @bluzi , il n'y a pas d'impact ddos ​​si vous vous auto-hébergez (ou utilisez aws ecr).

Ok, c'est certainement un scénario plus complexe que j'envisageais. maintenant, je pense... télécharger avec une sorte de hachage à une seule couche nocache... pousser et remplacer, vous l'appelez. Je ne suis pas sûr

TLDR : Je pense que certaines améliorations de la documentation Docker pourraient beaucoup aider.

Je me suis retrouvé ici après avoir rencontré mes propres problèmes/confusion avec la mise en cache. Après avoir lu tous les commentaires ici et sur https://github.com/moby/moby/pull/10682, j'ai trouvé une solution viable pour mon cas d'utilisation particulier. Pourtant, d'une manière ou d'une autre, je me sentais toujours frustré par la réponse de Docker à cela, et il semble que beaucoup d'autres ressentent la même chose.

Pourquoi? Après avoir réfléchi à cela sous plusieurs angles différents, je pense que le problème ici est une combinaison de cas d'utilisation vagues, d'arguments trop généralisés contre les changements proposés (qui peuvent être valables mais ne traitent pas directement les cas d'utilisation présentés), et un manque de documentation pour les recommandations de Docker pour certains cas d'utilisation courants. Peut-être que je peux aider à clarifier les choses et à identifier la documentation qui pourrait être améliorée pour aider dans cette situation.

En lisant entre les lignes, il me semble que la plupart des premiers commentateurs sur cette demande de fonctionnalité seraient satisfaits d'une solution qui utilise des arguments supplémentaires à docker image build pour désactiver le cache à un point spécifique du Dockerfile. Il semble que la solution actuelle de Docker pour cela (décrite dans https://github.com/moby/moby/issues/1996#issuecomment-172606763) devrait être suffisante dans la plupart de ces cas, et il semble que de nombreux utilisateurs en soient satisfaits . (Si quelqu'un a un cas d'utilisation où il peut fournir des arguments supplémentaires à docker image build mais que cette solution est toujours inadéquate, il serait probablement utile d'ajouter un commentaire expliquant pourquoi cela est inadéquat.)

Toute la frustration persistante semble être liée à la nécessité de transmettre des arguments supplémentaires à docker image build pour contrôler le comportement de la mise en cache. Cependant, les cas d'utilisation liés à cela n'ont pas été très bien décrits.

En relisant entre les lignes, il me semble que tous ces cas d'utilisation sont soit liés à des services qui exécutent docker image build au nom d'un utilisateur, soit liés à des Dockerfiles qui sont distribués à d'autres utilisateurs qui exécutent ensuite docker image build eux-mêmes. (Si quelqu'un a d'autres cas d'utilisation où passer des arguments supplémentaires à docker image build est un problème, il serait probablement utile d'ajouter un commentaire expliquant votre cas d'utilisation en détail.)

Dans bon nombre de ces cas, il semble que le cas d'utilisation ne nécessite pas réellement la possibilité de désactiver la mise en cache à un point spécifique du Dockerfile (qui était le point d'origine de cette demande de fonctionnalité). Au lieu de cela, il semble que de nombreux utilisateurs seraient satisfaits de la possibilité de désactiver entièrement la mise en cache à partir du Dockerfile, sans utiliser l'argument "--no-cache" pour docker image build et sans nécessiter de modifications manuelles du Dockerfile avant chaque construire. (Lors de la description des cas d'utilisation, il serait probablement utile de mentionner si la mise en cache partielle est réellement requise ou si la désactivation complète du cache serait suffisante pour votre cas d'utilisation.)

Dans les cas où un service exécute docker image build au nom d'un utilisateur, il semble que Docker s'attend à ce que tous ces services désactivent inconditionnellement le cache ou donnent à l'utilisateur la possibilité de désactiver le cache. Selon https://github.com/moby/moby/pull/10682#issuecomment-73777822, Docker Hub désactive inconditionnellement le cache. Si un service ne le fait pas déjà, Docker a suggéré https://github.com/moby/moby/pull/10682#issuecomment-159255451 de se plaindre au fournisseur de services à ce sujet.

Cela me semble être une position raisonnable pour Docker concernant les services qui exécutent docker image build . Cependant, cette position doit vraiment être officiellement documentée dans un endroit bien en vue afin que les fournisseurs de services et les utilisateurs sachent à quoi s'attendre. Il ne semble pas que cette position ou le comportement de mise en cache de Docker Hub soient actuellement documentés ailleurs que dans ces commentaires improvisés enfouis au plus profond de cette demande d'extraction énorme/ancienne/fermée, il n'est donc pas surprenant que les fournisseurs de services et les utilisateurs aient régulièrement se tromper. Peut-être que l'ajout d'informations à la référence docker build décrivant l'opinion de Docker sur l'utilisation de la mise en cache par les services de build, et l'ajout d'informations à la documentation de build automatisée Docker Hub sur le comportement de mise en cache de Docker Hub pourraient éliminer ce problème ?

Pour les cas où les Dockerfiles sont distribués à d'autres utilisateurs qui exécutent ensuite docker image build eux-mêmes, certaines personnes ont fait valoir que l'utilisation de la simple commande docker build . (sans arguments supplémentaires) est si courante qu'elle serait déraisonnable pour les constructeurs Dockerfile d'exiger des utilisateurs qu'ils ajoutent des arguments, tandis que d'autres personnes (par exemple : https://github.com/moby/moby/issues/1996#issuecomment-72238673 https://github.com/moby/moby/pull /10682#issuecomment-73820913 https://github.com/moby/moby/pull/10682#issuecomment-73992301) ont fait valoir qu'il serait inapproprié d'empêcher inconditionnellement les utilisateurs d'utiliser la mise en cache par des remplacements de cache de codage en dur dans le Dockerfile. En l'absence de cas d'utilisation détaillés / convaincants pour cela, Docker a pris la décision exécutive d'exiger des arguments de ligne de commande supplémentaires pour contrôler la mise en cache, ce qui semble être la source d'une grande partie de la frustration persistante. (Si quelqu'un a un cas d'utilisation convaincant lié à cela, il serait probablement utile d'ajouter un commentaire l'expliquant en détail.)

Cependant, il me semble que Docker peut être en mesure de rendre tout le monde heureux simplement en brisant l'habitude des utilisateurs d'exécuter docker build . sans arguments supplémentaires. Le comportement de mise en cache et l'argument "--no-cache" ne sont mentionnés dans aucun des didacticiels Docker pertinents (tels que celui-ci ou celui-ci
ou ceci ). De plus, bien que la documentation docker build répertorie l'argument "--no-cache", elle n'explique pas sa signification ni ne souligne le fait qu'il est important dans de nombreux cas d'utilisation courants. (Notez également que la documentation docker image build est vide. Elle doit au moins référencer la documentation docker build .) Il semble que seule la référence Dockerfile et la documentation sur les meilleures pratiques décrivent réellement le comportement de mise en cache et mentionnent le rôle de l'argument "--no-cache". Cependant, ces documents sont susceptibles d'être lus uniquement par des rédacteurs Dockerfile avancés. Il n'est donc pas surprenant que seuls les utilisateurs avancés connaissent l'argument "--no-cache", et que la plupart des utilisateurs n'exécuteraient que docker build . sans arguments supplémentaires et seraient ensuite confus lorsqu'il ne se comporte pas comment ils ou l'écrivain Dockerfile attendent/veulent. Peut-être que la mise à jour des didacticiels et de la documentation docker build pour mentionner l'argument "--no-cache" et sa signification pourrait éliminer ce problème ?

+1

+1

L'outil officiel de docker bashbrew ne vous permet pas d'ajouter des arguments lors de la création d'images, donc la réponse "officiellement pris en charge" ne fonctionne pas.

+1

+1

Le cas d'utilisation auquel je suis confronté en ce moment est de vouloir transmettre des secrets transitoires et de courte durée en tant qu'arguments de construction pour l'installation de packages privés. Cela interrompt complètement la mise en cache car cela signifie qu'à chaque fois que le secret change (essentiellement à chaque build), le cache est détruit et les packages sont réinstallés à nouveau, même si le seul changement est le secret.

J'ai essayé de contourner cela en consommant l'ARG dans un script qui obtient COPY avant de spécifier l'ARG, mais Docker semble tout invalider après la déclaration de l'ARG si l'entrée ARG a changé.

Le comportement que j'aimerais voir est de pouvoir marquer un ARG comme toujours en cache, soit dans le Dockerfile, soit sur la CLI lors de l'appel de build. Pour les cas d'utilisation comme les secrets, c'est souvent ce que vous voulez ; le contenu de la liste des packages doit dicter quand le cache est invalidé, pas l'argument passé à ARG.

Je comprends la théorie selon laquelle ces sections pourraient être extraites dans une deuxième image qui est ensuite utilisée comme image de base, mais c'est plutôt gênant lorsque les packages sont utilisés par un projet, comme dans un package.json, requirements.txt, Gemfile, etc. Cette image de base serait aussi continuellement reconstruite.

+1 à CACHE OFF de cette directive de ligne - j'attends cela depuis littéralement des années.

J'ai dû désactiver le cache sur docker hub / docker cloud et cela permettrait de gagner du temps et de construire si je pouvais mettre en cache la grande couche, puis exécuter une commande de mise à jour nocache vers la fin du fichier docker.

Le comportement que j'aimerais voir est de pouvoir marquer un ARG comme toujours en cache, soit dans le Dockerfile, soit sur la CLI lors de l'appel de build. Pour les cas d'utilisation comme les secrets, c'est souvent ce que vous voulez ; le contenu de la liste des packages doit dicter quand le cache est invalidé, pas l'argument passé à ARG.

--build-arg PASSWORD=<wrong> pourrait produire un résultat différent de --build-arg PASSWORD=<correct> , donc je ne suis pas sûr que le simple fait de regarder le contenu de la liste des packages fonctionnerait pour cela. Le constructeur ne peut pas anticiper par lui-même l'effet qu'aurait la définition/modification d'une variable d'environnement sur les étapes exécutées (les make DEBUG=1 foo et make DEBUG=0 foo -ils identiques ?). La seule exception actuellement faite est pour les variables d'environnement xx_PROXY , où l'on suppose qu'un proxy peut être nécessaire pour les connexions réseau, mais le passage à un proxy différent devrait produire le même résultat. Donc, pour que cela fonctionne, un moyen d'indiquer une variable d'environnement spécifique (/ build arg) à ignorer pour la mise en cache serait nécessaire.

notez que BuildKit a maintenant un support expérimental pour RUN --mount=type=secret et RUN --mount=type=ssh , ce qui peut être utile pour transmettre des secrets/informations d'identification, mais peut toujours invalider le cache si ces secrets changent (pas sûr ; cela pourrait être quelque chose à afficher dans le suivi des problèmes de buildkit https://github.com/moby/buildkit/issues).

J'ai dû désactiver le cache sur docker hub / docker cloud

Docker Hub/Cloud utilise-t-il réellement la mise en cache ? Je pense qu'aucune mise en cache n'y est utilisée (comme dans ; il utilise des environnements de construction éphémères)

Je me souviens que DockerHub n'utilisait pas la mise en cache des builds, mais j'avais regardé mes builds automatisés sur Docker Cloud juste avant ce ticket et il y a maintenant un curseur Building Caching à côté du curseur Autobuild de chaque branche, bien qu'il soit désactivé par défaut.

Je n'ose pas activer la mise en cache des builds car des étapes telles que git clone n'obtiendront pas le dernier téléchargement du référentiel car il compare uniquement la chaîne de directive qui ne changera pas. Expliquant ce problème à un collègue aujourd'hui qui est une épine dans le pied depuis des années, il a été surpris car cela semble être une grande imperfection pour de nombreux cas d'utilisation.

Je préférerais de loin que le git clone && make build initial soit mis en cache, puis faire un NO CACHE sur une étape git pull && make build pour n'obtenir qu'une mise à jour de code beaucoup plus petite + des dépendances pas déjà installées comme la dernière couche, mettant ainsi efficacement en cache la majeure partie de l'image, non seulement pour les versions, mais plus important encore pour tous les clients qui doivent actuellement télécharger à nouveau et remplacer des centaines de Mo de couches à chaque fois, ce qui est extrêmement inefficace.

La taille est due au fait que de nombreux projets ont un grand nombre de dépendances, par exemple. packages système + modules Perl CPAN + modules Python PyPI, etc.

Même en utilisant Alpine n'est pas beaucoup plus petit une fois que vous avez ajouté les dépendances du package système et les dépendances CPAN et PyPI, car j'utilise Alpine depuis des années pour essayer de voir si je pouvais créer des images plus petites, mais une fois que vous avez beaucoup de dépendances, ce n'est pas le cas. fait une grande différence si la base commence plus petite, car l'ajout de packages système en ajoute la plupart en retour.

Mettre en cache les couches précédentes qui incluent tous les packages système + modules CPAN + PyPI signifierait que très peu de choses devraient finir par changer dans la dernière couche de mises à jour car je ne mettrai pas à jour les modules installés qui fonctionnent dans la plupart des cas (j'ai utilisé des scripts de mes outils bash référentiel de sous-module utilitaire pour installer uniquement les packages qui ne sont pas déjà installés pour éviter d'installer des mises à jour inutiles sans correction de bogues)

Je cherchais à utiliser une astuce comme changer ARG pendant un certain temps (une idée que j'ai eue en cherchant sur des blogs comme http://dev.im-bot.com/docker-select-caching/) :

Dans Dockerfile :

ARG NOCACHE=0

Ensuite, lancez docker build comme ceci :

docker build --build-arg NOCACHE=$(date +%s) ...

mais je ne pense pas que cela soit possible dans Docker Cloud.

Il existe des variables d'environnement, mais il ne semble pas possible d'utiliser des contenus dynamiques tels que l'époque ci-dessus (ou du moins pas documentés que j'ai pu trouver), et avec les variables d'environnement, je ne suis pas sûr que cela invaliderait la mise en cache pour cette ligne de directive.

@thaJeztah Oui, ce type de comportement pourrait facilement avoir des conséquences négatives s'il est mal compris ou maltraité, mais il résoudrait très bien certains cas d'utilisation.

--build-arg PASSWORD=<wrong> pourrait produire un résultat différent de --build-arg PASSWORD=<correct> , donc je ne sais pas si le simple fait de regarder le contenu de la liste des packages fonctionnerait pour cela

Bien que vous ayez raison de dire que cela produirait des résultats différents, si la liste des packages n'a pas changé, je ne me soucie pas vraiment de savoir si le mot de passe est bon ou mauvais ; les packages sont déjà dans l'image précédente, donc l'utilisateur qui l'exécute a déjà accès (c'est-à-dire que ce n'est pas un problème de sécurité), et si le mot de passe était erroné auparavant, je m'attendrais à ce que l'auteur de Dockerfile fasse échouer l'installation si cela est requis, cela signifierait que vous auriez toujours la possibilité d'installer correctement les packages après avoir corrigé le mot de passe.

Oui, j'imaginais quelque chose comme docker build --force-cache-build-arg SECRET=supersecret . C'est assez maladroit, je suis sûr que quelqu'un pourrait trouver quelque chose de mieux.

@HariSekhon Il semble que votre cas d'utilisation soit en fait le contraire du mien, n'est-ce pas ? Vous voulez forcer sélectivement à manquer le cache, plutôt que forcer sélectivement à frapper le cache ?

L'ajout de ceci a fonctionné pour moi:

ADD http://date.jsontest.com/ /tmp/bustcache

mais ce site est en panne en ce moment. Cela devrait fonctionner

ADD http://api.geonames.org/timezoneJSON?formatted=true&lat=47.01&lng=10.2&username=demo&style=full /tmp/bustcache

@itdependsnetworks

Parfait, c'est une bonne solution de contournement et le site est de retour maintenant. Il est également utile d'enregistrer la date de construction de l'image.

J'avais essayé ceci et d'autres fichiers spéciaux similaires devraient changer à chaque fois

COPY /dev/random ...

mais cela n'a pas fonctionné même si RUN ls -l -R /etc montré que de tels fichiers étaient présents, ils n'ont toujours pas été trouvés, je soupçonne qu'il existe une certaine protection contre l'utilisation de fichiers spéciaux.

Maintenant, j'y pense plus sur DockerHub / Docker Cloud, vous pouvez probablement également utiliser un crochet de pré-construction pour générer un fichier contenant un horodatage, puis le COPIER sur l'image juste avant le calque que vous souhaitez mettre en cache, en obtenant un résultat similaire, bien que l'AJOUTER montré ci-dessus, je pense qu'il est plus portable pour les builds docker et cloud locaux.

Nous devons trouver un site d'impression de date plus fiable pour cette solution de contournement de cache - les deux ci-dessus semblent être des démos / ont des quotas et sont donc peu fiables et cassent de manière aléatoire des versions.

Le premier casse son quota quotidien tout le temps et le second donne maintenant cette erreur

{"status": {
  "message": "the daily limit of 20000 credits for demo has been exceeded. Please use an application specific account. Do not use the demo account for your application.",
  "value": 18
}}

Je pense que ce serait formidable d'avoir une instruction que je puisse mettre dans un fichier docker qui s'exécutera à chaque construction et si la sortie diffère de la dernière construction, les couches suivantes sont reconstruites.

Exemple d'utilisation serait :

FROM something
... 
CACHE_BUST git ls-remote my-git-repo HEAD
RUN git clone --depth=1 my-git-repo ...
...
CMD ["my-cmd"]

La commande dans l'instruction CACHE_BUST ci-dessus produira le SHA du HEAD du référentiel spécifié, de cette façon mon fichier docker peut savoir s'il faut cloner ou non en fonction des modifications apportées au référentiel.

Tous mes cas d'utilisation ici sont liés à des couches liées au réseau non déterministes, comme indiqué ci-dessus. Actuellement, je peux utiliser ARG pour tous mes besoins ici, mais cela signifie que j'ai souvent besoin d'un script de construction qui utilise un fichier docker, alors qu'il serait bien de n'avoir que le fichier docker lui-même à maintenir. (et certains outils n'autorisent pas les arguments)

Mon flux de travail actuel ressemblerait à ceci :

ARG SHA_TO_BUILD
RUN echo SHA_TO_BUILD
RUN git clone ...
...everything else reliant on that clone
$> ./build-my-image.sh $(get-latest-sha)

Je pense que l'activation et la désactivation de la mise en cache pour chaque commande est une mauvaise idée, les fichiers doivent être écrits de manière à ce que si une couche a besoin d'être reconstruite, les autres doivent également être reconstruites. Mais je pense qu'il serait bien de pouvoir forcer une reconstruction à un certain point du fichier.

une si grande fonctionnalité, pourquoi toujours en attente?

Un autre cas d'utilisation est lorsque le contenu d'un fichier change mais pas le Dockerfile .

Par exemple, si j'ai un COPY file.txt . et que je modifie file.txt Docker utilisera toujours l'ancienne version mise en cache.

Si Docker devait effectuer une somme de contrôle des fichiers qu'il a copiés et utilisé la prochaine fois pour déterminer s'il doit utiliser la couche mise en cache qui résoudrait le problème.

Pour le moment, je suis obligé d'utiliser --no-cache et cela télécharge et fonctionne bien plus que nécessaire (perte de temps et de bande passante).

@brnnancheung si c'est le cas, c'est un bug. N'hésitez pas à ouvrir un numéro séparé avec des étapes reproductibles.

Je pense que le point principal de ce que @brnnancheung
https://github.com/brennancheung dit, par exemple, lorsque vous êtes
charger un fichier de configuration (ou quelque chose de similaire). Vous n'avez pas besoin de
réinstaller toute l'application, il suffit de mettre à jour ces fichiers et les commandes
associé à celui-ci, lancez le docker et le tour est joué, le système est réglé.
Bien sûr, vous pouvez souvent placer le fichier de configuration plus près de la fin de
votre pile, mais ce n'est pas toujours le cas.

Suis Mi., 20. Mars 2019 à 00:10 Uhr schrieb Tibor Vass <
[email protected]> :

@brennancheung https://github.com/brennancheung si c'est le cas,
c'est un bug. N'hésitez pas à ouvrir un numéro séparé avec des étapes reproductibles.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/1996#issuecomment-474666893 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/ALBon0edO9m5BU3C5Ik2i__9eogZc1Jiks5vYaaNgaJpZM4BB_sR
.

--
Thiago Rodrigues

J'ai essayé ceci https://github.com/moby/moby/issues/1996#issuecomment -185872769

Mais cela n'affecte le cache que lors de/après la première utilisation et pas seulement sa définition.

https://docs.docker.com/engine/reference/builder/#impact -on-build-caching

Si un Dockerfile définit une variable ARG dont la valeur est différente de celle d'une version précédente, alors un « manque de cache » se produit lors de sa première utilisation, et non lors de sa définition.

@samstav "first use" il y a le premier RUN après le ARG (si ce ARG est avec une étape de construction), donc :

ARG FOO=bar

FROM something
RUN echo "this won't be affected if the value of FOO changes"
ARG FOO
RUN echo "this step will be executed again if the value of FOO changes"

FROM something-else
RUN echo "this won't be affected because this stage doesn't use the FOO build-arg"

Ce qui précède dépend un peu si vous utilisez le constructeur de nouvelle génération (BuildKit), donc avec DOCKER_BUILDKIT=1 activé, car le BuildKit peut sauter les étapes de construction s'ils ne sont pas nécessaires pour la phase finale (ou sauter les étapes de construction s'ils peuvent être entièrement mis en cache)

Cette page vous a été utile?
0 / 5 - 0 notes