NPM und der Docker Cache


Docker-Logo

NPM ist mit seinem package.json nicht sonderlich docker freundlich was das Caching der Layer angeht, viele Webseiten versprechen Hilfe aber machen den Job nur halb.
Hier der korrekte (aber etwas aufwändigere) Weg um die Layer in NPM korrekt zu cachen.

Die Anleitung die üblicherweise im Netz zu finden ist sieht wie folgt aus:

Um npm install zu cachen wird zuerst die package.json kopiert und installiert. Erst dann der Source der eigentlichen App. Dadurch kann man im Sourcecode etwas ändern ohne das npm install erneut ausgeführt wird. Dabei entsteht aber ein gravierendes Problem. in der package.json befindet sich  auch die Versionsnummer der App die sich mit jedem Update ändert. Dadurch verwirft Docker bei jedem Versionsupdate (also auch X.Y.Z+1 Patch Updates) den gesamten npm install Layer und generiert einen neuen.

Da sich die Dependencies jedoch sehr selten ändern dupliziert man hier Layer die nicht nötig sind.
Die Lösung ist einfach aber selten zu finden.
Man legt ein zusätzliches package_docker_cache.json file an in dem nur die dependencies des Projekts hinterlegt sind. Name, Version und andere Felder sind nicht wichtig da wir die Datei nach der npm installation überschreiben. Das ganze sieht dann so aus:

Das Dockerfile passen wir dann mit zwei zusätzlichen Zeilen an:

Indem wir zuerst das package_docker_cache.json file kopieren und installieren bleibt der npm install Layer erhalten und wir können in der echten package.json die Version nach belieben hoch ziehen. Das spart auf dauer viel Build Zeit und Speicher in der Registry.

Solltet ihr einmal vergessen eine Abhängigkeit in das docker cache package zu übertragen macht das für den Prozess im übrigen keinen Unterschied da wir die richtige package.json über das Cache-Package installieren. Wenn ihr nur testen wollt ist das sogar besser da ihr eure Produktions-Abhängigkeiten nicht verändert.

Haben sie Fragen oder Kommentare?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*