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:
Click==7.0
Django==2.2.3
django-appconf==1.0.3
django-compressor==2.3
django-debug-toolbar==2.0
django-filter==2.2.0
django-reversion==3.0.4
django-rq==2.1.0
pytz==2019.1
rcssmin==1.0.6
redis==3.3.4
rjsmin==1.1.0
rq==1.1.0
six==1.12.0
sqlparse==0.3.0
Un exemple typique de Python Dockerfile
pourrait ressembler à:
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt
COPY . /usr/src/app
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:
$ export DOCKER_BUILDKIT=1
$ docker build -t test .
[+] Building 65.6s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> [internal] load build context 0.6s
=> => transferring context: 899.99kB 0.6s
=> CACHED [internal] helper image for file operations 0.0s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.5s
=> [3/4] RUN pip install -r requirements.txt 61.3s
=> [4/4] COPY . /usr/src/app 1.3s
=> exporting to image 1.2s
=> => exporting layers 1.2s
=> => writing image sha256:d66a2720e81530029bf1c2cb98fb3aee0cffc2f4ea2aa2a0760a30fb718d7f83 0.0s
=> => naming to docker.io/library/test 0.0s
Maintenant, ajoutons l'en-tête expérimental et modifions l' RUN
étape pour mettre en cache les packages Python:
# syntax=docker/dockerfile:experimental
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
COPY . /usr/src/app
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:
$ docker build -t pythontest .
[+] Building 60.3s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 0.5s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> [internal] load build context 0.7s
=> => transferring context: 899.99kB 0.6s
=> CACHED [internal] helper image for file operations 0.0s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.6s
=> [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt 53.3s
=> [4/4] COPY . /usr/src/app 2.6s
=> exporting to image 1.2s
=> => exporting layers 1.2s
=> => writing image sha256:0b035548712c1c9e1c80d4a86169c5c1f9e94437e124ea09e90aea82f45c2afc 0.0s
=> => naming to docker.io/library/test 0.0s
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:
$ docker build -t pythontest .
[+] Building 15.9s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 1.1s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> CACHED [internal] helper image for file operations 0.0s
=> [internal] load build context 0.7s
=> => transferring context: 899.99kB 0.7s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.6s
=> [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt 8.8s
=> [4/4] COPY . /usr/src/app 2.1s
=> exporting to image 1.1s
=> => exporting layers 1.1s
=> => writing image sha256:fc84cd45482a70e8de48bfd6489e5421532c2dd02aaa3e1e49a290a3dfb9df7c 0.0s
=> => naming to docker.io/library/test 0.0s
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 de pip
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:
- Il s'agit d'une syntaxe expérimentale de Dockerfile et doit être traitée comme telle. Vous ne voudrez peut-être pas construire avec cela en production pour le moment.
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?
- Il n'y a pas d'interface directe pour gérer le cache pour le moment. Il est purgé lorsque vous effectuez un
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.