Mon Dockerfile est quelque chose comme
FROM my/base
ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install
ENTRYPOINT ["run_server"]
Chaque fois que je construis une nouvelle image, les dépendances doivent être réinstallées, ce qui peut être très lent dans ma région.
Une façon dont je pense aux cache
packages qui ont été installés est de remplacer l' my/base
image par des images plus récentes comme celle-ci:
docker build -t new_image_1 .
docker tag new_image_1 my/base
Donc, la prochaine fois que je construis avec ce Dockerfile, mon / base a déjà quelques packages installés.
Mais cette solution présente deux problèmes:
- Il n'est pas toujours possible de remplacer une image de base
- L'image de base devient de plus en plus grande à mesure que de nouvelles images y sont superposées
Alors, quelle meilleure solution pourrais-je utiliser pour résoudre ce problème?
ÉDITER##:
Quelques informations sur le docker sur ma machine:
☁ test docker version
Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070
☁ test docker info
Containers: 0
Images: 56
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Dirs: 56
Execution Driver: native-0.2
Kernel Version: 3.13.0-29-generic
WARNING: No swap limit support
my/base
Réponses:
Essayez de créer un Dockerfile qui ressemble à ceci:
Docker utilisera le cache pendant l'installation de pip tant que vous n'apportez aucune modification au
requirements.txt
, indépendamment du fait que d'autres fichiers de code.
aient été modifiés ou non. Voici un exemple.Voici un
Hello, World!
programme simple :La sortie de la construction de docker:
Modifions
run.py
:Essayez de construire à nouveau, voici la sortie:
Comme vous pouvez le voir ci-dessus, cette fois, le docker utilise le cache pendant la construction. Maintenant, mettons à jour
requirements.txt
:Voici la sortie de la construction de docker:
Remarquez comment docker n'a pas utilisé le cache lors de l'installation de pip. Si cela ne fonctionne pas, vérifiez la version de votre docker.
la source
ADD
instruction, le cache est invalidé.ADD ./requirements.txt /srv/requirements.txt
), alors docker doit utiliser le cache. Voir ajouter une seciton sur le document Dockerfile.ADD requirements.txt /srv
avant d'exécuter pip (RUN pip install -r requirements.txt
), et ajoutez tous les autres fichiers après l' exécution de pip. Ainsi, ils doivent être dans l'ordre suivant: (1)ADD requirements.txt /srv
; (2)RUN pip install -r requirements.txt
; ( 3)ADD . /srv
Pour minimiser l'activité réseau, vous pouvez pointer
pip
vers un répertoire de cache sur votre machine hôte.Exécutez votre conteneur docker avec la liaison du répertoire de cache pip de votre hôte monté dans le répertoire de cache pip de votre conteneur.
docker run
La commande devrait ressembler à ceci:Ensuite, dans votre Dockerfile, installez vos exigences en tant que partie d'une
ENTRYPOINT
instruction (ouCMD
instruction) au lieu d'uneRUN
commande. Ceci est important, car (comme indiqué dans les commentaires) le montage n'est pas disponible pendant la construction de l'image (lorsque lesRUN
instructions sont exécutées). Le fichier Docker devrait ressembler à ceci:la source
Je comprends que cette question a déjà des réponses populaires. Mais il existe une nouvelle façon de mettre en cache des fichiers pour les gestionnaires de packages. Je pense que cela pourrait être une bonne réponse à l'avenir lorsque BuildKit deviendra plus standard.
Depuis Docker 18.09, il existe un support expérimental pour BuildKit . BuildKit ajoute la prise en charge de certaines nouvelles fonctionnalités du Dockerfile, y compris la prise en charge expérimentale du montage de volumes externes en
RUN
étapes. Cela nous permet de créer des caches pour des choses comme$HOME/.cache/pip/
.Nous utiliserons le
requirements.txt
fichier suivant comme exemple:Un exemple typique de Python
Dockerfile
pourrait ressembler à:Avec BuildKit activé à l'aide de la
DOCKER_BUILDKIT
variable d'environnement, nous pouvons créer l'pip
étape non mise en cache en environ 65 secondes:Maintenant, ajoutons l'en-tête expérimental et modifions l'
RUN
étape pour mettre en cache les packages Python:Allez-y et faites une autre construction maintenant. Cela devrait prendre le même temps. Mais cette fois, il met en cache les packages Python dans notre nouveau montage de cache:
Environ 60 secondes. Similaire à notre première version.
Apportez une petite modification au
requirements.txt
(comme l'ajout d'une nouvelle ligne entre deux packages) pour forcer une invalidation du cache et réexécutez:Seulement environ 16 secondes!
Nous obtenons cette accélération car nous ne téléchargeons plus tous les packages Python. Ils ont été mis en cache par le gestionnaire de packages (
pip
dans ce cas) et stockés dans un montage de volume de cache. Le montage du volume est fourni à l'étape d'exécution afin depip
pouvoir réutiliser nos packages déjà téléchargés. Cela se produit en dehors de la mise en cache de la couche Docker .Les gains devraient être bien meilleurs sur les plus gros
requirements.txt
.Remarques:
Les éléments BuildKit ne fonctionnent pas sous Docker Compose ou d'autres outils qui utilisent directement l'API Docker pour le moment.Il existe désormais une prise en charge pour cela dans Docker Compose à partir de la version 1.25.0. Voir Comment activer BuildKit avec docker-compose?docker system prune -a
.Espérons que ces fonctionnalités en feront un Docker pour la construction et BuildKit deviendra la valeur par défaut. Si / quand cela se produit, j'essaierai de mettre à jour cette réponse.
la source
Dockerfile
ou la version de Docker est trop ancienne. Je créerais une nouvelle question avec toutes vos informations de débogage.J'ai trouvé qu'un meilleur moyen consiste simplement à ajouter le répertoire des packages de site Python en tant que volume.
De cette façon, je peux simplement installer de nouvelles bibliothèques sans avoir à faire une reconstruction complète.
EDIT : Ne tenez pas compte de cette réponse, la réponse de jkukul ci-dessus a fonctionné pour moi. Mon intention était de mettre en cache le dossier site-packages . Cela aurait ressemblé à quelque chose de plus comme:
La mise en cache du dossier de téléchargement est cependant beaucoup plus propre. Cela met également en cache les roues, de sorte qu'il accomplit correctement la tâche.
la source