Capisco che questa domanda abbia già alcune risposte popolari. Ma c'è un modo più nuovo per memorizzare nella cache i file per i gestori di pacchetti. Penso che potrebbe essere una buona risposta in futuro quando BuildKit diventerà più standard.
A partire da Docker 18.09 è disponibile il supporto sperimentale per BuildKit . BuildKit aggiunge il supporto per alcune nuove funzionalità nel Dockerfile, incluso il supporto sperimentale per il montaggio di volumi esterni nei RUN
passaggi. Questo ci permette di creare cache per cose come $HOME/.cache/pip/
.
Useremo il seguente requirements.txt
file come esempio:
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 tipico esempio di Python Dockerfile
potrebbe assomigliare a:
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt
COPY . /usr/src/app
Con BuildKit abilitato utilizzando la DOCKER_BUILDKIT
variabile di ambiente possiamo creare il pip
passaggio non memorizzato nella cache in circa 65 secondi:
$ 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
Ora, aggiungiamo l'intestazione sperimentale e modifichiamo il RUN
passaggio per memorizzare nella cache i pacchetti 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
Vai avanti e fai un'altra build ora. Dovrebbe volerci la stessa quantità di tempo. Ma questa volta sta memorizzando nella cache i pacchetti Python nel nostro nuovo montaggio 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
Circa 60 secondi. Simile alla nostra prima build.
Apporta una piccola modifica a requirements.txt
(come l'aggiunta di una nuova riga tra due pacchetti) per forzare l'invalidazione della cache ed eseguire di nuovo:
$ 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
Solo circa 16 secondi!
Stiamo ottenendo questa velocità perché non stiamo più scaricando tutti i pacchetti Python. Sono stati memorizzati nella cache dal gestore dei pacchetti ( pip
in questo caso) e archiviati in un montaggio del volume della cache. Il montaggio del volume viene fornito alla fase di esecuzione in modo che pip
possa riutilizzare i nostri pacchetti già scaricati. Ciò accade al di fuori di qualsiasi memorizzazione nella cache del livello Docker .
I guadagni dovrebbero essere molto migliori su grandi requirements.txt
.
Appunti:
- Questa è la sintassi Dockerfile sperimentale e dovrebbe essere trattata come tale. Potresti non voler costruire con questo in produzione al momento.
Le cose di BuildKit non funzionano con Docker Compose o altri strumenti che utilizzano direttamente l'API Docker al momento. Ora è disponibile il supporto per questo in Docker Compose a partire dalla versione 1.25.0. Vedi Come si abilita BuildKit con docker-compose?
- Al momento non esiste alcuna interfaccia diretta per la gestione della cache. Viene eliminato quando si esegue un file
docker system prune -a
.
Si spera che queste funzionalità entrino in Docker per la creazione e BuildKit diventerà l'impostazione predefinita. Se / quando ciò accadrà, cercherò di aggiornare questa risposta.