Mein Dockerfile ist so etwas wie
FROM my/base
ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install
ENTRYPOINT ["run_server"]
Jedes Mal, wenn ich ein neues Image erstelle, müssen Abhängigkeiten neu installiert werden, was in meiner Region sehr langsam sein kann.
Eine Möglichkeit cache
für installierte Pakete besteht darin, das my/base
Image mit neueren Images wie diesem zu überschreiben :
docker build -t new_image_1 .
docker tag new_image_1 my/base
Wenn ich das nächste Mal mit dieser Docker-Datei baue, sind auf meiner / base bereits einige Pakete installiert.
Diese Lösung hat jedoch zwei Probleme:
- Es ist nicht immer möglich, ein Basisbild zu überschreiben
- Das Basisbild wird immer größer, wenn neuere Bilder darauf geschichtet werden
Welche bessere Lösung könnte ich zur Lösung dieses Problems verwenden?
BEARBEITEN##:
Einige Informationen zum Docker auf meinem Computer:
☁ 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
Antworten:
Versuchen Sie, eine Docker-Datei zu erstellen, die ungefähr so aussieht:
Docker verwendet während der Pip-Installation den Cache, solange Sie keine Änderungen an der vornehmen
requirements.txt
, unabhängig davon, ob andere Codedateien bei.
geändert wurden oder nicht. Hier ist ein Beispiel.Hier ist ein einfaches
Hello, World!
Programm:Die Ausgabe von Docker Build:
Lassen Sie uns ändern
run.py
:Versuchen Sie erneut zu erstellen. Unten sehen Sie die Ausgabe:
Wie Sie oben sehen können, verwendet diesmal Docker während des Builds den Cache. Jetzt aktualisieren wir
requirements.txt
:Unten ist die Ausgabe von Docker Build:
Beachten Sie, dass Docker während der Pip-Installation keinen Cache verwendet hat. Wenn es nicht funktioniert, überprüfen Sie Ihre Docker-Version.
quelle
ADD
Cache immer dann ungültig wird , wenn Docker eine Anweisung sieht .ADD ./requirements.txt /srv/requirements.txt
) wird jedoch nichts geändert. Dann muss der Docker den Cache verwenden. Siehe Hinzufügen eines Abschnitts zum Dockerfile-Dokument.ADD requirements.txt /srv
bevor Sie pip (RUN pip install -r requirements.txt
) ausführen , und alle anderen Dateien nach dem Ausführen von pip hinzufügen . Daher sollten sie in der folgenden Reihenfolge vorliegen: (1)ADD requirements.txt /srv
; (2)RUN pip install -r requirements.txt
; ( 3)ADD . /srv
Um die Netzwerkaktivität zu minimieren, können Sie
pip
auf ein Cache-Verzeichnis auf Ihrem Host-Computer verweisen .Führen Sie Ihren Docker-Container mit der Pip-Cache-Verzeichnisbindung Ihres Hosts aus, die in das Pip-Cache-Verzeichnis Ihres Containers eingebunden ist.
docker run
Befehl sollte so aussehen:Installieren Sie dann in Ihrer Docker-Datei Ihre Anforderungen als Teil einer
ENTRYPOINT
Anweisung (oderCMD
Anweisung) anstatt alsRUN
Befehl. Dies ist wichtig, da (wie in den Kommentaren erwähnt) der Mount während der Image-Erstellung (wennRUN
Anweisungen ausgeführt werden) nicht verfügbar ist . Die Docker-Datei sollte folgendermaßen aussehen:quelle
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:Ein typisches Beispiel für Python
Dockerfile
könnte aussehen:Wenn BuildKit mithilfe der
DOCKER_BUILDKIT
Umgebungsvariablen aktiviert ist, können wir den nicht zwischengespeichertenpip
Schritt in ca. 65 Sekunden erstellen :Fügen wir nun den experimentellen Header hinzu und ändern den
RUN
Schritt zum Zwischenspeichern der Python-Pakete:Mach jetzt einen weiteren Build. Es sollte genauso lange dauern. Diesmal werden jedoch die Python-Pakete in unserem neuen Cache-Mount zwischengespeichert:
Ü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: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, damitpip
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:
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?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.
quelle
Dockerfile
der Docker-Version verpasst oder die Docker-Version ist zu alt. Ich würde eine neue Frage mit all Ihren Debugging-Informationen erstellen.Ich fand, dass ein besserer Weg darin besteht, einfach das Python-Site-Packages-Verzeichnis als Volume hinzuzufügen.
Auf diese Weise kann ich einfach neue Bibliotheken installieren, ohne eine vollständige Neuerstellung durchführen zu müssen.
EDIT : Ignorieren Sie diese Antwort, Jkukuls Antwort oben hat für mich funktioniert. Meine Absicht war es, den Site-Packages- Ordner zwischenzuspeichern. Das hätte eher so ausgesehen:
Das Zwischenspeichern des Download-Ordners ist jedoch viel sauberer. Dadurch werden auch die Räder zwischengespeichert, sodass die Aufgabe ordnungsgemäß ausgeführt wird.
quelle