Der Autor des Materials, dessen Übersetzung wir heute veröffentlichen, ist ein DevOps-Ingenieur. Er sagt, er muss
Docker benutzen. Insbesondere wird diese Containerverwaltungsplattform in verschiedenen Phasen des Lebenszyklus von Node.js-Anwendungen verwendet. Mit Docker, einer Technologie, die in letzter Zeit sehr beliebt war, können Sie den Entwicklungs- und Ausgabeprozess von Node.js Projekten in der Produktion optimieren.

Wir veröffentlichen jetzt eine
Reihe von Artikeln über Docker, die für diejenigen gedacht sind, die diese Plattform für den Einsatz in verschiedenen Situationen erlernen möchten. Das gleiche Material konzentriert sich hauptsächlich auf den professionellen Einsatz von Docker in der Entwicklung von Node.j.
Was ist ein Docker?
Docker ist ein Programm zur Organisation der Virtualisierung auf Betriebssystemebene (Containerisierung). Das Herzstück von Containern sind geschichtete Bilder. Einfach ausgedrückt ist Docker ein Tool, mit dem Sie Anwendungen mithilfe von Containern erstellen, bereitstellen und ausführen können, unabhängig vom Betriebssystem, auf dem sie ausgeführt werden. Der Container enthält ein Image des Basisbetriebssystems, das für das Funktionieren der Anwendung erforderlich ist, die Bibliothek, von der diese Anwendung abhängt, und diese Anwendung selbst. Wenn mehrere Container auf demselben Computer ausgeführt werden, verwenden sie die Ressourcen dieses Computers zusammen. Docker-Container können Projekte packen, die mit einer Vielzahl von Technologien erstellt wurden. Wir sind an Projekten interessiert, die auf Node.js basieren.
Erstellen eines Node.js-Projekts
Bevor wir ein Node.js-Projekt in einen Docker-Container packen, müssen wir dieses Projekt erstellen. Lass es uns tun. Hier ist die Datei
package.json
dieses Projekts:
{ "name": "node-app", "version": "1.0.0", "description": "The best way to manage your Node app using Docker", "main": "index.js", "scripts": { "start": "node index.js" }, "author": "Ankit Jain <ankitjain28may77@gmail.com>", "license": "ISC", "dependencies": { "express": "^4.16.4" } }
Führen Sie den Befehl
npm install
um die Projektabhängigkeiten zu
npm install
. Im Verlauf dieses Befehls wird unter anderem die Datei
package-lock.json
erstellt. Erstellen Sie nun die Datei
index.js
, die den Projektcode enthält:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('The best way to manage your Node app using Docker\n'); }); app.listen(3000); console.log('Running on http://localhost:3000');
Wie Sie sehen können, haben wir hier einen einfachen Server beschrieben, der als Antwort auf Anforderungen Text zurückgibt.
Erstellen Sie eine Docker-Datei
Nachdem die Anwendung fertig ist, sprechen wir darüber, wie Sie sie in einen Docker-Container packen. Es geht nämlich darum, was der wichtigste Teil eines Docker-basierten Projekts ist, nämlich die Docker-Datei.
Eine Docker-Datei ist eine Textdatei, die Anweisungen zum Erstellen eines Docker-Images für eine Anwendung enthält. Die Anweisungen in dieser Datei beschreiben, wenn sie nicht auf Details eingehen, die Erstellung von Ebenen eines mehrstufigen Dateisystems, das alles enthält, was eine Anwendung zum Arbeiten benötigt. Die Docker-Plattform kann Bildebenen zwischenspeichern, was bei der Wiederverwendung von Ebenen, die sich bereits im Cache befinden, das Erstellen von Bildern beschleunigt.
In der objektorientierten Programmierung gibt es so etwas wie eine Klasse. Klassen werden zum Erstellen von Objekten verwendet. In Docker können Bilder mit Klassen verglichen werden, und Container können mit Instanzen von Bildern verglichen werden, dh mit Objekten. Betrachten Sie den Prozess des Generierens einer Docker-Datei, um dies herauszufinden.
Erstellen Sie eine leere Docker-Datei:
touch Dockerfile
Da wir einen Container für die Anwendung Node.js erstellen, müssen wir zunächst das Basisknoten-Image in den Container einfügen, das sich auf dem
Docker Hub befindet . Wir werden die LTS-Version von Node.js verwenden. Infolgedessen lautet die erste Anweisung unserer Docker-Datei wie folgt:
FROM node:8
Erstellen Sie danach ein Verzeichnis für unseren Code. Gleichzeitig können wir dank der hier verwendeten
ARG
Anweisung bei Bedarf den Namen des anderen Anwendungsverzeichnisses als
/app
während der Montage des Containers angeben. Details zu diesem Handbuch finden Sie
hier .
Da wir das Node-Image verwenden, sind die Plattformen Node.js und npm bereits darin installiert. Mit dem, was bereits im Image enthalten ist, können Sie die Installation von Projektabhängigkeiten organisieren. Wenn Sie das Flag
--production
verwenden (oder wenn die Umgebungsvariable
NODE_ENV
auf
production
), installiert npm die im Abschnitt
devDependencies
Datei
devDependencies
aufgeführten Module nicht.
Hier kopieren wir die
package*.json
Datei in das Image, anstatt beispielsweise alle Projektdateien zu kopieren. Wir tun genau das, weil die Dockerfile-Anweisungen
RUN
,
COPY
und
ADD
zusätzliche Bildebenen erstellen, sodass Sie die Caching-Funktionen der Docker-Plattformebenen verwenden können. Mit diesem Ansatz wird Docker beim nächsten Sammeln eines ähnlichen Bilds herausfinden, ob es möglich ist, Bildebenen, die sich bereits im Cache befinden, wiederzuverwenden. In diesem Fall wird das bereits vorhandene Bild ausgenutzt, anstatt neue zu erstellen Schichten. Auf diese Weise können Sie beim Zusammenstellen von Ebenen bei der Arbeit an großen Projekten, die viele npm-Module enthalten, erheblich Zeit sparen.
Kopieren Sie nun die Projektdateien in das aktuelle Arbeitsverzeichnis. Hier verwenden wir nicht die Anweisung
ADD , sondern die Anweisung
COPY . In den meisten Fällen wird empfohlen, die
COPY
Anweisung zu bevorzugen.
Der
ADD
Befehl weist im Vergleich zu
COPY
einige Funktionen auf, die jedoch nicht immer benötigt werden. Zum Beispiel sprechen wir über Optionen zum Entpacken von .tar-Archiven und zum Herunterladen von Dateien per URL.
Docker-Container sind isolierte Umgebungen. Dies bedeutet, dass wir beim Starten der Anwendung im Container nicht direkt mit ihr interagieren können, ohne den Port zu öffnen, den diese Anwendung überwacht. Um Docker darüber zu informieren, dass sich in einem bestimmten Container eine Anwendung befindet, die einen bestimmten Port
überwacht , können Sie die Anweisung
EXPOSE verwenden .
Bisher haben wir mithilfe der Docker-Datei das Image beschrieben, das die Anwendung enthalten wird, sowie alles, was zum erfolgreichen Start erforderlich ist. Fügen Sie nun der Datei die Anweisung hinzu, mit der Sie die Anwendung starten können. Dies ist eine
CMD- Anweisung. Hier können Sie einen bestimmten Befehl mit Parametern angeben, die beim Start des Containers ausgeführt werden und bei Bedarf von der Befehlszeile überschrieben werden können.
So sieht das fertige Dockerfile aus:
FROM node:8
Bildassemblierung
Wir haben eine Dockerfile-Datei vorbereitet, die Anweisungen zum Erstellen des Images enthält, auf deren Grundlage ein Container mit einer laufenden Anwendung erstellt wird. Stellen Sie das Bild zusammen, indem Sie einen Befehl der folgenden Form ausführen:
docker build --build-arg <build arguments> -t <user-name>/<image-name>:<tag-name> /path/to/Dockerfile
In unserem Fall sieht es so aus:
docker build --build-arg APP_DIR=var/app -t ankitjain28may/node-app:V1 .
Dockerfile verfügt über eine
ARG
Anweisung, die das Argument
APP_DIR
. Hier setzen wir seine Bedeutung. Wenn dies nicht getan wird, nimmt es den Wert an, der ihm in der Datei zugewiesen ist,
app
-
app
.
Überprüfen Sie nach dem Zusammenstellen des Bildes, ob Docker es sieht. Führen Sie dazu den folgenden Befehl aus:
docker images
Als Antwort auf diesen Befehl sollte ungefähr Folgendes ausgegeben werden.
Docker-BilderBildstart
Nachdem wir das Docker-Image zusammengestellt haben, können wir es ausführen, dh eine Instanz davon erstellen, die durch einen Arbeitscontainer dargestellt wird. Verwenden Sie dazu einen Befehl dieser Art:
docker run -p <External-port:exposed-port> -d --name <name of the container> <user-name>/<image-name>:<tag-name>
In unserem Fall sieht es so aus:
docker run -p 8000:3000 -d --name node-app ankitjain28may/node-app:V1
Mit diesem Befehl werden wir das System um Informationen zu Arbeitscontainern bitten:
docker ps
Als Reaktion darauf sollte das System Folgendes ausgeben:
Docker-ContainerBisher läuft alles wie erwartet, obwohl wir noch nicht versucht haben, auf die im Container ausgeführte Anwendung zuzugreifen. Unser Container mit dem Namen
node-app
überwacht nämlich Port
8000
. Um zu versuchen, darauf zuzugreifen, können Sie einen Browser öffnen und unter
localhost:8000
darauf zugreifen. Um den Zustand des Containers zu überprüfen, können Sie außerdem den folgenden Befehl verwenden:
curl -i localhost:8000
Wenn der Container wirklich funktioniert, wird als Antwort auf diesen Befehl etwas wie das in der folgenden Abbildung gezeigte zurückgegeben.
Ergebnis der Container-IntegritätsprüfungAuf der Grundlage des gleichen Bildes, beispielsweise auf der Grundlage der gerade erstellten, können viele Container erstellt werden. Darüber hinaus können Sie unser Image an die Docker Hub-Registrierung senden, damit andere Entwickler unser Image hochladen und die entsprechenden Container zu Hause starten können. Dieser Ansatz vereinfacht die Arbeit mit Projekten.
Empfehlungen
Hier sind einige Vorschläge, die Sie berücksichtigen sollten, um die Leistung von Docker zu nutzen und so kompakte Bilder wie möglich zu erstellen.
▍1. Erstellen Sie immer eine .dockerignore-Datei
In dem Projektordner, den Sie in den Container
.dockerignore
, müssen Sie immer eine
.dockerignore
Datei erstellen. Sie können Dateien und Ordner ignorieren, die beim Erstellen des Bildes nicht benötigt werden. Mit diesem Ansatz können wir den sogenannten Build-Kontext reduzieren, wodurch wir das Image schnell zusammenstellen und seine Größe reduzieren können. Diese Datei unterstützt Dateinamenvorlagen. In dieser Datei ähnelt sie einer
.gitignore
Datei. Es wird empfohlen, einen Befehl zu
.dockerignore
hinzuzufügen, aufgrund dessen Docker den Ordner
/.git
ignoriert, da dieser Ordner normalerweise große Materialien enthält (insbesondere während der Entwicklung eines Projekts) und das Hinzufügen zum Bild zu einer Vergrößerung führt. Darüber hinaus ist das Kopieren dieses Ordners in ein Bild wenig sinnvoll.
▍2. Verwenden Sie den mehrstufigen Bildassemblierungsprozess
Betrachten Sie das Beispiel, wenn wir ein Projekt für eine bestimmte Organisation sammeln. Dieses Projekt verwendet viele npm-Pakete, und jedes dieser Pakete kann zusätzliche Pakete installieren, von denen es abhängt. Das Ausführen all dieser Vorgänge führt zu zusätzlichem Zeitaufwand für das Zusammenstellen des Images (obwohl dies dank der Caching-Funktionen von Docker keine so große Sache ist). Schlimmer noch, das resultierende Bild, das die Abhängigkeiten eines bestimmten Projekts enthält, ist ziemlich groß. Wenn wir hier über Front-End-Projekte sprechen, können wir uns daran erinnern, dass solche Projekte normalerweise mit Bundlern wie Webpack verarbeitet werden, die es ermöglichen, alles, was eine Anwendung benötigt, bequem in ein Verkaufspaket zu packen. Daher sind npm-Paketdateien für ein solches Projekt nicht erforderlich. Dies bedeutet, dass wir solche Dateien entfernen können, nachdem wir das Projekt mit demselben Webpack erstellt haben.
Versuchen Sie mit dieser Idee Folgendes zu tun:
Ein solcher Ansatz wird uns jedoch nicht passen. Wie bereits erwähnt, erstellen die Anweisungen
RUN
,
ADD
und
COPY
von Docker zwischengespeicherte Ebenen. Daher müssen wir einen Weg finden, um die Installation von Abhängigkeiten zu handhaben, das Projekt zu erstellen und dann unnötige Dateien mit einem einzigen Befehl zu löschen. Zum Beispiel könnte es so aussehen:
In diesem Beispiel gibt es nur eine
RUN
Anweisung, die die Abhängigkeiten installiert,
node_modules
Projekt erstellt und den Ordner
node_modules
löscht. Dies führt dazu, dass die Größe des Bildes nicht so groß ist wie die Größe des Bildes, das den Ordner
node_modules
. Wir verwenden die Dateien aus diesem Ordner nur während des Erstellungsprozesses des Projekts und löschen sie dann. Dieser Ansatz ist insofern schlecht, als die Installation von npm-Abhängigkeiten viel Zeit in Anspruch nimmt. Sie können diesen Nachteil mithilfe der Technologie der mehrstufigen Montage von Bildern beseitigen.
Stellen Sie sich vor, wir arbeiten an einem Frontend-Projekt mit vielen Abhängigkeiten und verwenden Webpack, um dieses Projekt zu erstellen. Mit diesem Ansatz können wir zur Reduzierung der Bildgröße die Funktionen von Docker für die
mehrstufige Montage von Bildern nutzen .
FROM node:8 As build
Bei diesem Ansatz ist das resultierende Bild viel kleiner als das vorherige Bild, und wir verwenden auch das
node:alpine
Bild, das selbst sehr klein ist. Und hier ist ein Vergleich eines Bildpaares, bei dem zu sehen ist, dass das Bild von
node:alpine
viel kleiner ist als das Bild von
node:8
.
Vergleichen von Bildern aus dem Node-Repository▍3. Verwenden Sie den Docker-Cache
Versuchen Sie, die Caching-Funktionen von Docker zum Erstellen Ihrer Bilder zu verwenden. Wir haben diese Funktion bereits bei der Arbeit mit einer Datei beachtet, auf die über das Namenspaket
package*.json
. Dies reduziert die Erstellungszeit des Bildes. Diese Gelegenheit sollte jedoch nicht vorschnell genutzt werden.
Angenommen, wir beschreiben in Dockerfile die Installation von Paketen in einem Image, das aus dem Basis-
Ubuntu:16.04
Image erstellt wurde
Ubuntu:16.04
:
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y \ curl \ package-1 \ . .
Wenn das System diese Datei verarbeitet und viele Pakete installiert sind, nehmen die Aktualisierungs- und Installationsvorgänge viel Zeit in Anspruch. Um die Situation zu verbessern, haben wir uns entschlossen, die Layer-Caching-Funktionen von Docker zu nutzen und die Docker-Datei wie folgt neu zu schreiben:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ . .
Wenn Sie das Bild jetzt zum ersten Mal zusammenstellen, läuft alles so, wie es sollte, da der Cache noch nicht gebildet wurde. Stellen Sie sich jetzt vor, wir müssen ein anderes Paket installieren,
package-2
. Dazu schreiben wir die Datei neu:
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y \ curl \ package-1 \ package-2 \ . .
Aufgrund eines solchen Befehls wird
package-2
nicht installiert oder aktualisiert. Warum? Tatsache ist, dass Docker beim Ausführen der
RUN apt-get update
Anweisung
RUN apt-get update
keinen Unterschied zwischen dieser Anweisung und der zuvor ausgeführten Anweisung sieht, sodass Daten aus dem Cache entnommen werden. Und diese Daten sind bereits veraltet. Bei der Verarbeitung der
RUN apt-get install
Anweisung
RUN apt-get install
System sie aus, da sie nicht wie eine ähnliche Anweisung in der vorherigen Docker-Datei aussieht. Während der Installation können jedoch Fehler auftreten oder die alte Version von Paketen wird installiert. Infolgedessen stellt sich heraus, dass die
update
und
install
innerhalb derselben
RUN
Anweisung ausgeführt werden müssen, wie dies im ersten Beispiel der Fall ist. Caching ist eine großartige Funktion, aber die rücksichtslose Verwendung dieser Funktion kann zu Problemen führen.
▍4. Minimieren Sie die Anzahl der Bildebenen
Es wird empfohlen, nach Möglichkeit zu versuchen, die Anzahl der Bildebenen zu minimieren, da jede Ebene das Dateisystem des Docker-Bildes ist. Je kleiner das Ebenenbild, desto kompakter wird es. Bei Verwendung des mehrstufigen Prozesses zum Zusammensetzen von Bildern wird eine Verringerung der Anzahl von Schichten im Bild und eine Verringerung der Größe des Bildes erreicht.
Zusammenfassung
In diesem Artikel haben wir uns mit dem Verpacken von Node.js-Anwendungen in Docker-Containern und dem Arbeiten mit solchen Containern befasst. Darüber hinaus haben wir einige Empfehlungen abgegeben, die übrigens nicht nur beim Erstellen von Containern für Node.js-Projekte verwendet werden können.
Liebe Leser! Wenn Sie Docker bei der Arbeit mit Node.js-Projekten professionell verwenden, teilen Sie Anfängern Empfehlungen zur effektiven Verwendung dieses Systems mit.
