Optimierungen am Dockerfile für NPM-Projekte
Bestimmt nutzt ihr Jenkins, Bamboo, GitLab oder andere Tools, um eure NPM-basierten Projekte automatisiert zu testen und zu bauen. Dabei müssen immer Voraussetzungen erfüllt sein, um den Build-Prozess durchführen zu können. Zum Beispiel wollt ihr eine bestimmte Node.js-Version zum Bauen der Anwendung einsetzen. Oder ihr müsst einen Proxy konfigurieren, um eure NPM-Abhängigkeiten aus dem Unternehmens-Repository zu laden. Wie man ein Nexus für NPM-Pakete vorbereitet, habe ich in einem anderen Post beschrieben.
Eine häufige Lösung ist, den Build-Prozess durch ein Dockerfile zu beschreiben. Das Dockerfile liegt direkt beim Quellcode und wird beim Start des Build-Prozesses von den oben genannten Tools ausgeführt. Nachfolgend möchte ich euch zeigen, wie ein Dockerfile für NPM-Projekte aussehen kann. Dabei möchte ich auf ein paar Aspekte genauer hinweisen, um den Build-Prozess möglichst schnell und performant zu gestalten. Das fertige Beispiel ist wie immer auf GitHub zu finden.
Der Build-Prozess
Als Beispielprojekt dient uns ein einfaches Angular Projekt. Für unser Projekt legen wir uns ein Dockerfile an. In dieser Datei beschreiben wir gleich den (vereinfachten) Build-Vorgang.
FROM node:12.16.1-buster-slim
FROM node:12.16.1-buster-slim ADD . /app RUN npm install
docker build -t angular-build-via-docker .
Führen wir diesen Befehl nun aus, so wird als erstes das node:12.16.1-buster-slim Image geladen. Das Image wird von den Node.Js Entwicklern selbst bereitgestellt. Danach wird durch die ADD Angabe der Inhalt unseres Repositories zum Container hinzugefügt. Das kann man auch an der folgenden Ausgabe nachvollziehen.
Dockerignore
Sending build context to Docker daemon 406.1MB
Über 400 MB werden zum Container hinzugefügt? Kann das sein? Anscheinend schon. Denn unter anderem wird der Inhalt des node_modules/ und .git/ Verzeichnisse hinzugefügt. Gerade das node_modules/ Verzeichnis brauchen wir nicht für den Build-Prozess. Das Beziehen der Abhängigkeiten soll während des Bauens des Docker Images passieren.
Was dem Image hinzugefügt wird, können wir durch die Datei .dockerignore steuern. Die Datei funktioniert nach dem gleichen Prinzip wie die .gitignore. Die beiden aufgeführten Ordner werden somit nicht mehr dem Image hinzugefügt. Nachfolgend der Inhalt unserer .dockerignore.
node_modules/ .git/
Der Docker Cache
FROM node:12.16.1-buster-slim ADD package.json /app/ WORKDIR /app RUN npm install ADD . /app RUN npm run build
Nachfolgend fehlt nur noch der Befehl, um den Build des Angular Projektes auszuführen. Das ist in der letzten Zeile im Dockerfile zu finden.
Ausprobieren kann man das nun ganz einfach. Nachdem der docker build Befehl fertig ist, einfach nochmal ausführen. Dann sieht man folgende Zeile:
Step 2/6 : ADD package.json /app/ ---> Using cache
Man erkennt sofort, dass der zweite Schritt nun viel schneller erledigt ist.
Das Ende vom Lied
Wir haben durch zwei einfache Anpassungen erreicht, dass unser Build-Prozess effizienter und schneller durchgeführt werden kann.
Durch die .dockerignore Datei können wir einfach steuern, welche Inhalte dem Image hinzugefügt werden. Außerdem können wir den Caching-Mechanismus ausnutzen und Teile des Build-Prozesses beschleunigen, indem sie nur ausgeführt werden, wenn zwingend erforderlich.
Ausblick
Sie haben Interesse an einer Weiterbildung oder Fragen zum Thema Docker? Sprechen Sie uns an oder besuchen Sie einen unserer Kurse aus unserem Seminarshop:
Zum Docker Seminar
Senior Chief Consultant bei ORDIX
Bei Updates im Blog, informieren wir per E-Mail.
Kommentare