J'essaie d'optimiser une application docker sur Heroku pour mettre en cache les dépendances installées entre les versions. Jusqu'à présent, je n'ai pas pu obtenir de versions ultérieures pour utiliser une forme de mise en cache. Par exemple, en utilisant le Dockerfile
suivant:
build: docker: web: Dockerfile
Si docker build -t test .
localement plusieurs fois je vois:
Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 16 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 697 bytes | 697.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 remote: Compressing source files... done. remote: Building source: remote: === Fetching app code remote: remote: === Building web (Dockerfile) remote: Sending build context to Docker daemon 7.168kB remote: Step 1/4 : FROM ruby:2.7.2-alpine remote: 2.7.2-alpine: Pulling from library/ruby remote: 188c0c94c7c5: Pulling fs layer remote: ba0772c8cbe1: Pulling fs layer remote: dcff69af93dc: Pulling fs layer remote: 16507e0b6111: Pulling fs layer remote: 6aadfa8ff2a8: Pulling fs layer remote: 16507e0b6111: Waiting remote: 6aadfa8ff2a8: Waiting remote: dcff69af93dc: Verifying Checksum remote: dcff69af93dc: Download complete remote: ba0772c8cbe1: Verifying Checksum remote: ba0772c8cbe1: Download complete remote: 188c0c94c7c5: Verifying Checksum remote: 188c0c94c7c5: Download complete remote: 6aadfa8ff2a8: Verifying Checksum remote: 6aadfa8ff2a8: Download complete remote: 16507e0b6111: Verifying Checksum remote: 16507e0b6111: Download complete remote: 188c0c94c7c5: Pull complete remote: ba0772c8cbe1: Pull complete remote: dcff69af93dc: Pull complete remote: 16507e0b6111: Pull complete remote: 6aadfa8ff2a8: Pull complete remote: Digest: sha256:f9f332eece9188d10abb30ff6b109a1b0fee9f3e82683df8df8bf81be8121567 remote: Status: Downloaded newer image for ruby:2.7.2-alpine remote: ---> 79f5adf3c887 remote: Step 2/4 : WORKDIR /app remote: ---> Running in e8d12e411b82 remote: Removing intermediate container e8d12e411b82 remote: ---> d5833157511c remote: Step 3/4 : COPY Gemfile Gemfile.lock ./ remote: ---> 47f0942ba73c remote: Step 4/4 : RUN bundle install remote: ---> Running in 15b1359b8240 remote: Fetching gem metadata from https://rubygems.org/.... remote: Using bundler 2.1.4 remote: Fetching ruby2_keywords 0.0.2 remote: Installing ruby2_keywords 0.0.2 remote: Fetching mustermann 1.1.1 remote: Installing mustermann 1.1.1 remote: Fetching rack 2.2.3 remote: Installing rack 2.2.3 remote: Fetching rack-protection 2.1.0 remote: Installing rack-protection 2.1.0 remote: Fetching tilt 2.0.10 remote: Installing tilt 2.0.10 remote: Fetching sinatra 2.1.0 remote: Installing sinatra 2.1.0 remote: Bundle complete! 1 Gemfile dependency, 7 gems now installed. remote: Use `bundle info [gemname]` to see where a bundled gem is installed. remote: Removing intermediate container 15b1359b8240 remote: ---> 318addc210bd remote: Successfully built 318addc210bd remote: Successfully tagged 31d653df6d02eb931fff2c0be8a4cc35b829ea54:latest remote: remote: === Pushing web (Dockerfile) remote: Tagged image "31d653df6d02eb931fff2c0be8a4cc35b829ea54" as "registry.heroku.com/secret-sierra-97497/web" remote: The push refers to repository [registry.heroku.com/secret-sierra-97497/web] remote: 0f8d2b92cc43: Preparing remote: 1fff78e61e17: Preparing remote: eebe8de04d9e: Preparing remote: 410b5fd47642: Preparing remote: 12b703c99815: Preparing remote: e44bb72897d4: Preparing remote: 720dc6953f4e: Preparing remote: ace0eda3e3be: Preparing remote: e44bb72897d4: Waiting remote: 720dc6953f4e: Waiting remote: ace0eda3e3be: Waiting remote: 12b703c99815: Layer already exists remote: 410b5fd47642: Layer already exists remote: e44bb72897d4: Layer already exists remote: 720dc6953f4e: Layer already exists remote: ace0eda3e3be: Layer already exists remote: 1fff78e61e17: Pushed remote: eebe8de04d9e: Pushed remote: 0f8d2b92cc43: Pushed remote: latest: digest: sha256:11214585c68599a907c5855a213dc3d0121d9f535cb9be8ec8ed6a6ba3998913 size: 1989 remote: remote: Verifying deploy... done. To https://git.heroku.com/secret-sierra-97497.git 933054c..19603ae master -> master
Déploiement sur Heroku plusieurs fois (avec des commits vides), je vois:
docker build -t test . Sending build context to Docker daemon 92.16kB Step 1/4 : FROM ruby:2.7.2-alpine ---> 79f5adf3c887 Step 2/4 : WORKDIR /app ---> Using cache ---> 1c42ebe94fa4 Step 3/4 : COPY Gemfile Gemfile.lock ./ ---> Using cache ---> 626c3092389f Step 4/4 : RUN bundle install ---> Using cache ---> 15e0dce9151b Successfully built 15e0dce9151b Successfully tagged test:latest
Mon fichier heroku.yml est:
FROM ruby:2.7.2-alpine WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle install
Est-il possible d'utiliser la mise en cache des couches avec le docker Heroku pour accélérer les builds?
3 Réponses :
Peut-être qu'au lieu d'utiliser la commande COPY
, vous pouvez ADD
les fichiers.
Cela devrait contourner le mécanisme de mise en cache Dockerfile pour éviter d'invalider l'intégralité de votre cache lorsque vous modifiez du code.
FROM ruby:2.7.2-alpine ADD Gemfile /app/ ADD Gemfile.lock /app/ RUN bundle install
PS Je ne suis pas très familier avec le système de docker de Heroku, mais idéalement ADD est meilleur que COPY et fonctionne bien avec la mise en cache.
Merci d'avoir répondu, mais ne voyant aucune différence entre COPY et ADD. Aussi - selon le guide du docker, je pense que COPY est préférable à moins d'utiliser certaines fonctions étendues offertes par ADD: docs.docker.com/develop/develop-images / ...
Peut-être que cela pourrait aider (j'ai adapté ma réponse d'ici): blog.heroku.com / ...
De plus, vous avez raison à propos de l'instruction COPY ... elle est préférable, mais pas à cause d'une différence de performances ou de mise en cache - docs.docker.com/develop/develop-images / ...
Pouvez-vous vérifier qu'après la construction, l'espace de travail est en cours d'effacement ou ce que cela peut être l'une des raisons pour lesquelles le cache docker est invalidé.
Je ne sais pas ce que cela signifie. Que dois-je vérifier dans les journaux pour voir cela?
Heroku se déploie généralement avec git . Vous poussez votre code source. Heroku détecte le type de votre projet et sélectionne le pack de construction approprié. Heroku construit un conteneur à l'aide du pack de construction. Le pack de construction sait comment le faire efficacement, en mettant en cache les dépendances, etc. Heroku déploie ensuite ce conteneur. Vous n'avez pas besoin d'écrire un Dockerfile.
Heroku prend en charge le déploiement avec docker pour les personnes qui ont besoin de plus de contrôle sur le conteneur. Ces builds s'exécutent dans un environnement propre et le comportement que vous voyez est correct. La mise en cache d'anciennes couches docker entre les versions de production est délicate. La même chaîne de commande (par exemple apt-get install
) exécutée ultérieurement peut donner des résultats différents.
Si une partie de votre Dockerfile prend beaucoup de temps, vous devrez peut-être attendre trop longtemps pour mettre à jour un déploiement au moment du développement. Ensuite, vous pouvez utiliser un flux différent dans lequel vous créez l'image localement et la transmettez au registre de conteneurs Heroku lorsque vous souhaitez qu'elle soit déployée.
Si vous êtes intéressé par ce dernier flux, jetez un œil aux packs de build natifs du cloud qui vous permettent de créer le conteneur pour votre code source à l'aide du pack
CLI.
Merci pour le flip de réponse. Pour clarifier - il semble que Heroku ne prend pas en charge la mise en cache de couches lors de la création d'une image Docker au meilleur de vos connaissances? La raison de mes efforts est de comparer les problèmes de performances avec les déploiements utilisant les packs de build traditionnels.
Avez-vous étiqueté et publié l'image du docker? Si oui à quel registre? Voir devcenter.heroku.com/articles/ ... Avez-vous spécifié manuellement la commande
docker build
sur Heroku ou est-elle automatiquement déduite? Sur le hub docker que je fais:docker build --pull --cache-from $(repo):amd64-dev -f Dockerfile.amd64 -t $(repo):amd64-dev .
suivi d'undocker push $(repo):amd64-dev
.Heroku construit l'image docker dans le cadre du processus de déploiement.