Ich verstehe, dass diese Frage bereits einige populäre Antworten hat. Es gibt jedoch eine neuere Möglichkeit, Dateien für Paketmanager zwischenzuspeichern. Ich denke, es könnte in Zukunft eine gute Antwort sein, wenn BuildKit mehr Standard wird.
Ab Docker 18.09 gibt es experimentelle Unterstützung für BuildKit . BuildKit bietet Unterstützung für einige neue Funktionen in der Docker-Datei, einschließlich experimenteller Unterstützung für das Bereitstellen externer Volumes in RUN
Schritten. Dies ermöglicht es uns, Caches für Dinge wie zu erstellen $HOME/.cache/pip/
.
Wir werden die folgende requirements.txt
Datei als Beispiel verwenden:
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
Ein typisches Beispiel für Python Dockerfile
könnte aussehen:
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt
COPY . /usr/src/app
Wenn BuildKit mithilfe der DOCKER_BUILDKIT
Umgebungsvariablen aktiviert ist, können wir den nicht zwischengespeicherten pip
Schritt in ca. 65 Sekunden erstellen :
$ 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
Fügen wir nun den experimentellen Header hinzu und ändern den RUN
Schritt zum Zwischenspeichern der Python-Pakete:
# 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
Mach jetzt einen weiteren Build. Es sollte genauso lange dauern. Diesmal werden jedoch die Python-Pakete in unserem neuen Cache-Mount zwischengespeichert:
$ 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
Über 60 Sekunden. Ähnlich wie bei unserem ersten Build.
Nehmen Sie eine kleine Änderung an vor requirements.txt
(z. B. Hinzufügen einer neuen Zeile zwischen zwei Paketen), um eine Cache-Ungültigmachung zu erzwingen und erneut auszuführen:
$ 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
Nur ca. 16 Sekunden!
Wir bekommen diese Beschleunigung, weil wir nicht mehr alle Python-Pakete herunterladen. Sie wurden ( pip
in diesem Fall) vom Paketmanager zwischengespeichert und in einem Cache-Volume-Mount gespeichert. Die Volume-Bereitstellung wird für den Ausführungsschritt bereitgestellt, damit pip
unsere bereits heruntergeladenen Pakete wiederverwendet werden können. Dies geschieht außerhalb des Docker-Layer-Caching .
Die Gewinne sollten bei größeren viel besser sein requirements.txt
.
Anmerkungen:
- Dies ist eine experimentelle Dockerfile-Syntax und sollte als solche behandelt werden. Möglicherweise möchten Sie im Moment nicht damit in der Produktion bauen.
Das BuildKit-Material funktioniert derzeit nicht unter Docker Compose oder anderen Tools, die die Docker-API direkt verwenden. Dies wird jetzt in Docker Compose ab 1.25.0 unterstützt. Siehe Wie aktivieren Sie BuildKit mit Docker-Compose?
- Derzeit gibt es keine direkte Schnittstelle für die Verwaltung des Caches. Es wird gelöscht, wenn Sie a
docker system prune -a
.
Hoffentlich schaffen es diese Funktionen in Docker zum Erstellen und BuildKit wird zum Standard. In diesem Fall werde ich versuchen, diese Antwort zu aktualisieren.