Einrichten einer Node.js-Anwendung für die Produktion unter Ubuntu 20.04

Einführung

Node.js ist eine Open-Source-basierte JavaScript-Laufzeitumgebung für das Einrichten von Server- und Netzwerkanwendungen. Die Plattform läuft unter Linux, MacOS, FreeBSD und Windows. Sie können Node.js-Anwendungen zwar in der Befehlszeile ausführen können, doch werden Sie sie in diesem Tutorial als Dienst ausführen. Das bedeutet, dass sie bei erneutem Booten oder einem Absturz neu gestartet werden und zur Verwendung in einer Produktionsumgebung sicher sind.

In diesem Tutorial werden Sie eine produktionsfähige Node.js-Umgebung auf einem einzelnen Ubuntu 20.04-Server einrichten. Dieser Server wird eine von PM2 verwaltete Node.js-Anwendung ausführen und Benutzern sicheren Zugriff auf die Anwendung über einen Nginx-Reverseproxy bereitstellen. Der Nginx-Server bietet HTTPS mit einem kostenlosen Zertifikat, das von Let’s Encrypt bereitgestellt wird.

Voraussetzungen

Dieser Leitfaden geht davon aus, dass Sie Folgendes haben:

  • Eine Ubuntu 20.04-Server-Einrichtung, wie im Leitfaden zur Ersteinrichtung des Servers für Ubuntu 20.04 beschrieben. Sie sollten einen non-root user mit sudo-Berechtigungen und eine aktive Firewall haben.
  • Einen Domänennamen, der auf die öffentliche IP-Adresse Ihres Servers verweist. In diesem Tutorial wird durchgängig der Domänenname example.com verwendet.
  • Nginx installiert, wie in Installieren von Nginx unter Ubuntu 20.04 beschrieben.
  • Nginx, konfiguriert mit SSL unter Verwendung von Let’s Encrypt-Zertifikaten. Sichern von Nginx mit Let’s Encrypt unter Ubuntu 20.04 wird Sie durch den Prozess führen.

Wenn Sie die Voraussetzungen abgeschlossen haben, verfügen Sie über einen Server, der die Standardplatzhalterseite Ihrer Domäne unter https://example.com/ bereitstellt.

Schritt 1 — Installieren von Node.js

Beginnen wir zunächst mit der Installation der neuesten LTS-Version von Node.js unter Verwendung der NodeSource-Paketarchive.

Installieren Sie zunächst das NodeSource-PPA, um Zugriff auf dessen Inhalt zu erhalten. Stellen Sie sicher, dass Sie sich in Ihrem Stammverzeichnis befinden, und verwenden Sie curl, um das Installationskript für die aktuellste LTS-Version von Node.js aus den Archiven abzurufen.

  • cd ~
  • curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh

Sie können den Inhalt dieses Skripts mit nano oder Ihrem bevorzugten Texteditor prüfen:

  • nano nodesource_setup.sh

Wenn Sie das Skript fertig geprüft haben, führen Sie es unter sudo aus:

  • sudo bash nodesource_setup.sh

Das PPA wird Ihrer Konfiguration hinzugefügt und Ihr lokaler Paket-Cache automatisch aktualisiert. Nach Ausführung des Einrichtungsskripts aus Nodesource können Sie nun das Node.js-Paket installieren:

  • sudo apt install nodejs

Um zu prüfen, welche Version von Node.js Sie nach diesen ersten Schritten installiert haben, geben Sie Folgendes ein:

  • nodejs -v
Outputv14.4.0 

Anmerkung: Bei der Installation aus dem NodeSource-PPA wird die ausführbare Node.js-Datei nodejs und nicht node genannt.

Das nodejs-Paket enthält das binäre nodejs sowie npm, einen Paketmanager für Node-Module. Sie müssen npm also nicht separat installieren.

npm verwendet eine Konfigurationsdatei in Ihrem Home Verzeichnis, um Aktualisierungen zu verfolgen. Sie wird erstellt, wenn Sie npm das erste Mal ausführen. Führen Sie diesen Befehl aus, um zu verifizieren, dass npm installiert ist, und um die Konfigurationsdatei zu erstellen:

  • npm -v
Output6.14.5 

Damit bestimmte npm Pakete funktionieren (z. B. jene, deren Code aus Source erstellt werden muss), müssen Sie das build-essential Paket installieren:

  • sudo apt install build-essential

Jetzt haben Sie die notwendigen Tools, um mit npm Paketen zu arbeiten, deren Code aus Source erstellt werden muss.

Mit installierter Node.js-Laufzeitumgebung können wir jetzt mit dem Schreiben einer Node.js-Anwendung fortfahren.

Schritt 2 — Erstellen einer Node.js-Anwendung

Lassen Sie uns eine Hello World-Anwendung schreiben, die in beliebigen HTTP-Anfragen „Hello World“ zurückgibt. Diese Beispielanwendung hilft Ihnen dabei, Node.js einzurichten. Sie können sie durch eine eigene Anwendung ersetzen – stellen Sie sicher, dass Sie Ihre Anwendung so ändern, dass an den richtigen IP-Adressen und Ports gelauscht wird.

Erstellen wir zunächst eine Beispielanwendung namens hello.js:

  • cd ~
  • nano hello.js

Fügen Sie in der Datei den folgenden Code hinzu:

~/hello.js

const http = require('http');  const hostname = 'localhost'; const port = 3000;  const server = http.createServer((req, res) => {   res.statusCode = 200;   res.setHeader('Content-Type', 'text/plain');   res.end('Hello World!n'); });  server.listen(port, hostname, () => {   console.log(`Server running at http://${hostname}:${port}/`); }); 

Speichern Sie die Datei und beenden Sie den Editor.

Diese Node.js-Anwendung lauscht an der angegebenen Adresse (localhost) und Port (3000) und gibt “Hello World!” mit dem HTTP-Erfolgscode 200 zurück. Da wir an localhost lauschen, können sich Remoteclients nicht mit unserer Anwendung verbinden.

Geben Sie zum Testen Ihrer Anwendung Folgendes ein:

  • node hello.js

Sie erhalten die folgende Ausgabe:

OutputServer running at http://localhost:3000/ 

Anmerkung: Durch Ausführung einer Node.js-Anwendung auf diese Weise werden weitere Befehle blockiert, bis der Abbruch der Anwendung durch Drücken von Strg+C erzwungen wird.

Öffnen Sie zum Testen der Anwendung auf Ihrem Server eine weitere Terminalsitzung und stellen Sie unter Verwendung von curl mit localhost eine Verbindung her:

  • curl http://localhost:3000

Wenn Sie die folgende Ausgabe erhalten, funktioniert die Anwendung ordnungsgemäß und lauscht an der richtigen Adresse und am richtigen Port:

OutputHello World! 

Wenn Sie nicht die erwartete Ausgabe erhalten, stellen Sie sicher, dass Ihre Node.js-Anwendung ausgeführt wird und so konfiguriert ist, dass sie an der richtigen Adresse und am richtigen Port lauscht.

Sobald Sie sicher sind, dass es funktioniert, erzwingen Sie den Abbruch der Anwendung (wenn Sie es nicht bereits getan haben), indem Sie Strg+C drücken.

Schritt 3 – Installieren von PM2

Als Nächstes installieren wir PM2, einen Prozessmanager für Node.js-Anwendungen. PM2 ermöglicht es, Anwendungen zu daemonisieren, damit sie im Hintergrund als Dienst ausgeführt werden.

Verwenden Sie npm zum Installieren der neuesten Version von PM2 auf Ihrem Server:

Die Option -g weist npm an, das Modul global zu installieren, damit es systemweit verfügbar ist.

Verwenden wir zunächst den Befehl pm2 start zum Ausführen Ihrer Anwendung hello.js im Hintergrund:

  • pm2 start hello.js

Dadurch wird Ihre Anwendung auch der Prozessliste von PM2 hinzugefügt, die bei jeder Ausführung einer Anwendung ausgegeben wird:

Output... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0  │ hello              │ fork     │ 0    │ online    │ 0%       │ 25.2mb   │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘ 

Wie oben angegeben, weist PM2 automatisch einen App-Namen (basierend auf dem Dateinamen ohne die Erweiterung .js) und eine PM2-ID zu. Außerdem pflegt PM2 weitere Informationen, wie z. B. die PID des Prozesses, den aktuellen Status und die Speicherauslastung.

Anwendungen, die unter PM2 ausgeführt werden, werden automatisch neu gestartet, wenn eine Anwendung abstürzt oder ihr Abbruch erzwungen wird. Wir können jedoch mit dem Unterbefehl startup einen zusätzlichen Schritt hinzufügen, damit die Anwendung beim Systemstart gestartet wird. Dieser Unterbefehl generiert und konfiguriert ein Startskript zum Starten von PM2 und den verwalteten Prozessen beim Booten von Servern:

  • pm2 startup systemd

Die letzte Zeile der resultierenden Ausgabe enthält einen Befehl zum Ausführen mit Superuser-Berechtigungen, damit PM2 beim Booten gestartet wird:

Output[PM2] Init System found: systemd sammy [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy 

Führen Sie den Befehl aus der Ausgabe aus, wobei Sie anstelle von sammy Ihren Benutzernamen verwenden:

  • sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Als weiteren Schritt können wir die PM2-Prozessliste und entsprechende Umgebungen speichern:

  • pm2 save

Sie haben nun eine systemd-Einheit erstellt, die beim Booten pm2 für Ihren Benutzer ausführt. Diese pm2-Instanz gibt wiederum hello.js zurück.

Starten Sie den Dienst mit systemctl:

  • sudo systemctl start pm2-sammy

Wenn an diesem Punkt ein Fehler auftritt, müssen Sie möglicherweise neu starten, was Sie mit sudo reboot erreichen können.

Überprüfen Sie den Status der systemd-Einheit:

  • systemctl status pm2-sammy

Für eine ausführliche Übersicht zu systemd lesen Sie bitte Systemd Essentials: Arbeiten mit Diensten, Einheiten und dem Journal.

Neben den von uns abgedeckten Befehlen bietet PM2 viele Unterbefehle, mit denen Sie Daten über Ihre Anwendung verwalten oder suchen können.

Stoppen Sie eine Anwendung mit diesem Befehl (geben Sie den App-Namen oder die ID von PM2 an):

  • pm2 stop app_name_or_id

Starten Sie eine Anwendung neu:

  • pm2 restart app_name_or_id

Listen Sie die aktuell von PM2 verwalteten Anwendungen auf:

  • pm2 list

Erhalten Sie Informationen zu einer bestimmten Anwendung mithilfe des App-Namens:

  • pm2 info app_name

Der PM2-Prozessmonitor kann mit dem Unterbefehl monit aufgerufen werden. Dadurch werden der Anwendungsstatus sowie die CPU-und Speicherauslastung angezeigt:

  • pm2 monit

Beachten Sie, dass beim Ausführen von pm2 ohne Argumente auch eine Hilfeseite mit Beispielnutzung angezeigt wird.

Nachdem Ihre Node.js-Anwendung ausgeführt und von PM2 verwaltet wird, können wir nun den Reverseproxy einrichten.

Schritt 4 — Einrichten von Nginx als Reverseproxy-Server

Ihre Anwendung wird ausgeführt und lauscht an localhost. Sie müssen jedoch einen Weg finden, damit Ihre Benutzer darauf zugreifen können. Dazu werden wir den Nginx-Webserver als Reverseproxy einrichten.

Im Tutorial zu den Voraussetzungen richten Sie Ihre Nginx-Konfiguration in der Datei /etc/nginx/sites-available/example.com ein. Öffnen Sie diese Datei zur Bearbeitung:

  • sudo nano /etc/nginx/sites-available/example.com

Innerhalb des server-Blocks sollten Sie einen vorhandenen location /-Block haben. Ersetzen Sie den Inhalt dieses Blocks durch die folgende Konfiguration. Wenn Ihre Anwendung so konfiguriert ist, dass sie an einem anderen Port lauscht, aktualisieren Sie den markierten Teil mit der richtigen Portnummer:

/etc/nginx/sites-available/example.com

server { ...     location / {         proxy_pass http://localhost:3000;         proxy_http_version 1.1;         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection 'upgrade';         proxy_set_header Host $host;         proxy_cache_bypass $http_upgrade;     } ... } 

Dadurch wird der Server so konfiguriert, dass er auf Anfragen an sein Stammverzeichnis antwortet. Angenommen, unser Server ist unter example.com verfügbar. Durch Aufrufen von https://example.com/ über einen Webbrowser würde die Anfrage an hello.js gesendet werden, wobei an Port 3000 bei localhost gelauscht wird.

Sie können dem gleichen Serverblock zusätzliche location-Blöcke hinzufügen, um Zugriff auf andere Anwendungen auf dem gleichen Server zu gewähren. Wenn Sie beispielsweise eine andere Node.js-Anwendung an Port 3001 ausführen würden, könnten Sie diesen location-Block hinzufügen, um Zugriff darauf über https://example.com/app2 zu gewähren:

/etc/nginx/sites-available/example.com — Optional

server { ...     location /app2 {         proxy_pass http://localhost:3001;         proxy_http_version 1.1;         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection 'upgrade';         proxy_set_header Host $host;         proxy_cache_bypass $http_upgrade;     } ... } 

Sobald Sie die location-Blöcke für Ihre Anwendungen hinzugefügt haben, speichern Sie die Datei und verlassen Sie den Editor.

Stellen Sie sicher, dass Sie keine Syntaxfehler gemacht haben, indem Sie Folgendes eingeben:

  • sudo nginx -t

Starten Sie Nginx neu:

  • sudo systemctl restart nginx

Wenn Ihre Node.js-Anwendung ausgeführt wird und Ihre Anwendungs- und Nginx-Konfigurationen korrekt sind, sollten Sie nun über den Nginx-Reverseproxy auf Ihre Anwendung zugreifen können. Probieren Sie es aus, indem Sie die URL Ihres Servers (seine öffentliche IP-Adresse oder seinen Domänennamen) aufrufen.

Zusammenfassung

Herzlichen Glückwunsch! Ihre Node.js-Anwendung wird nun hinter einem Nginx-Reverseproxy auf einem Ubuntu 20.04-Server ausgeführt. Diese Reverseproxy-Einrichtung ist flexibel genug, um Ihren Benutzern Zugriff auf andere Anwendungen oder statische Webinhalte zu bieten, die Sie freigeben möchten.