So richten Sie die CI / CD-Pipeline für eine node.js-App mit Jenkins ein

Was ist CI / CD?

Continuous Integration und Continuous Deployment sind zwei moderne Methoden der Softwareentwicklung. Continuous Integration (CI) ist der Prozess der Automatisierung des Erstellens und Testens von Code jedes Mal, wenn ein Teammitglied Änderungen an der Versionskontrolle festlegt. Die kontinuierliche Bereitstellung (Continuous Deployment, CD) kann als Erweiterung der kontinuierlichen Integration betrachtet werden und ist der Prozess der automatischen Bereitstellung einer Anwendung nach erfolgreichem CI. Ziel ist es, die Vorlaufzeit zu minimieren. Die Zeit, die zwischen dem Schreiben einer neuen Codezeile und der Verwendung dieses neuen Codes durch Live-Benutzer in der Produktion vergangen ist.

Warum CI / CD?

Es gibt viele Vorteile für CI / CD-Praktiken. Ich werde nicht auf jeden Vorteil im Detail eingehen, aber ich möchte hier einige hervorheben:

Vorteile der kontinuierlichen Integration:

  • Weniger Bugs
  • Weniger Kontextwechsel, da Entwickler benachrichtigt werden, sobald sie den Build abbrechen
  • Testkosten werden reduziert
  • Ihr QA-Team verbringt weniger Zeit mit Testen

Vorteile der kontinuierlichen Bereitstellung:

  • Releases sind weniger riskant
  • Einfache Freigabe
  • Kunden sehen einen kontinuierlichen Strom von Verbesserungen
  • Beschleunigen Sie die Entwicklung, da die Entwicklung für Releases nicht unterbrochen werden muss

Was werden wir bauen?

Wir werden eine einfache Node-Anwendung erstellen und auf der DigitalOcean-Instanz hosten. Außerdem werden wir einen Automatisierungsserver konfigurieren und Jenkins auf einer separaten DigitalOcean-Instanz hosten. Jenkins wird uns helfen, den CI / CD-Prozess zu automatisieren. Bei jeder Codeänderung aus unserem Node-App-Repository wird Jenkins benachrichtigt, und die Änderungen werden auf unseren Jenkins-Server übertragen (Schritt 1), Abhängigkeiten installiert (Schritt 2) und der Integrationstest ausgeführt (Schritt 3). Wenn alle Tests bestanden wurden, stellt Jenkins die App auf dem Knotenserver bereit (Schritt 4). Wenn dies fehlschlägt, wird ein Entwickler benachrichtigt.

Merkmal 1

Erstellen einer Node-App

Bevor wir eine CI / CD-Pipeline schreiben, benötigen wir eine Anwendung zum Testen und Bereitstellen. Wir werden eine einfache node.js-Anwendung erstellen, die mit "Hallo Welt" -Text antwortet. Richten wir zunächst unser GitHub-Repository für dieses Projekt ein.

Setze GitHub Repository

Erstellen Sie ein neues Repository unter Ihrem GitHub-Konto und nennen Sie es "Node-App".

  • Sie können zwischen öffentlichem und privatem Repo wählen
  • Aktivieren Sie das Kontrollkästchen Dieses Repository mit einer README-Datei initialisieren
  • Wählen Sie im Dropdown-Menü .gitignore den Knoten aus
  • Klicken Sie auf die Schaltfläche Repository erstellen
Figur 2

Nun klonen wir unser Node-App-Repo auf unseren lokalen Computer und navigieren zu diesem:

git clone git@github.com:  /node-app.git
CD Node-App

Erstellen Sie die Node.js-App

Der erste Schritt beim Erstellen einer Node-App ist das Erstellen der Datei package.json. In dieser Datei werden die Anwendungsabhängigkeiten aufgelistet. Erstellen Sie in Ihrem Projektstamm eine neue Datei mit dem Namen package.json und fügen Sie den folgenden Inhalt ein:

{
 "Name": "node-app",
 "Beschreibung": "Hallo Jenkins Test App",
 "Version": "0.0.1",
 "Privat": wahr,
 "Abhängigkeiten": {
    "Express": "3.12.0"
 },
 "DevDependencies": {
    "Mokka": "1.20.1",
    "Supertest": "0.13.0"
 }
}
  • Express: Node Framework
  • Mokka: Test-Framework für Node (Sie können ein anderes Test-Framework auswählen, wenn Sie Jasmin, Jest, Tape usw. möchten.)
  • supertest: Stellen Sie eine allgemeine Abstraktion zum Testen von HTTP bereit

Nachdem wir unsere Abhängigkeiten in package.json definiert haben, können wir sie installieren:

npm install

Genial! Bereit, Code zu schreiben? Erstellen Sie eine neue Datei im Projektstamm mit dem Namen index.js und fügen Sie den folgenden Code ein:

// Node Framework importieren
var express = require ("express");
 
var app = express ();
// Antworte mit "Hallo Welt" auf Anfragen, die unsere Wurzel treffen "/"
app.get (‘/’, function (req, res) {
 res.send ("Hallo Welt");
});
// Standardmäßig Port 3000 abhören
app.listen (process.env.PORT || 3000);
 
module.exports = app;

Unsere App antwortet mit "Hallo Welt", wenn Anfragen an unsere Stamm-URL ("/") gesendet werden.

Und das ist unsere App!

Hier ist die endgültige Ordnerstruktur:

Figur 3

Jetzt können wir unsere App ausführen:

Knoten index.js

Sie können Ihre App in Ihrem Browser anzeigen, wenn Sie zu http: // localhost: 3000 navigieren

Tests schreiben

Wir sind bereit, unseren ersten Integrationstest zu schreiben. Unser Test navigiert zum Site-Stammverzeichnis ("/") und überprüft, ob die Seite mit dem Text "Hallo Welt" antwortet.

Unter einem neuen Verzeichnis / test / create test.js. Kopieren Sie den folgenden Code und fügen Sie ihn ein:

var request = require (‘supertest’);
var app = require (‘../ index.js’);
describe ('GET /', function () {
 es ("Antwort mit Hallo Welt", Funktion (erledigt) {
 // gehe zu root und überprüfe, ob die Antwort "Hallo Welt" ist
 request (app) .get (‘/’). expect (‘Hallo Welt’, erledigt);
 });
});

Wir werden Mokka verwenden, um unseren Test durchzuführen. Wir haben Mocha als Teil unserer devDependencies in package.json installiert. Um den Test auszuführen, müssen wir Mocha unsere Datei /test/test.js als Argument übergeben.

./node_modules/.bin/mocha ./test/test.js

Wenn Sie diesen Befehl von Ihrem Projektstamm ausführen, sehen Sie unseren Testlauf und bestehen ihn.

Figur 4

In Abbildung 1, Schritt 3, möchten wir, dass Jenkins unseren Integrationstest ausführt, nachdem er erstellt wurde. Um dies zu erreichen, müssen wir in unserem Projekt ein Shell-Skript erstellen, das unseren Test auslöst.

Erstellen Sie einen neuen / script / -Ordner und einen Dateinamentest ohne die Dateierweiterung. Kopieren Sie den folgenden Code und fügen Sie ihn in die Testdatei ein:

#! / bin / sh
./node_modules/.bin/mocha ./test/test.js

Ausführbare Berechtigungen erteilen:

chmod + x script / test

Und testen Sie es, indem Sie das Shell-Skript aus dem Projektstamm ausführen:

./script/test

Boom! Der Integrationstest ist fertig und jetzt können wir unseren Code an GitHub senden:

Git hinzufügen.
git commit -m "einfache Node-App mit Test"
Git Push Origin Master

Serve Node App

Wir werden unsere Node-App auf einem Server hosten, damit die ganze Welt unser Meisterstück sehen kann. Wir werden DigitalOcean als Hosting-Provider verwenden. DigitalOcean bietet eine einfache Möglichkeit, Server zu konfigurieren und neue Instanzen zu starten.

Knotentropfen erstellen

Melden Sie sich an und melden Sie sich bei Ihrem DigitalOcean-Konto an.

  • Klicken Sie auf die Schaltfläche Neues Droplet erstellen.
  • Wählen Sie ein Bild aus: Klicken Sie auf die Registerkarte App mit einem Klick und wählen Sie den Knoten JS aus der Liste aus
  • Wähle eine Größe: 1GB (Die günstigste)
  • Wählen Sie eine Datencenter-Region: Wählen Sie die Ihnen am nächsten gelegene. Ich wähle New York Zone 3
  • Hinzufügen Ihrer SSH-Schlüssel: Fügen Sie den SSH-Schlüssel Ihres lokalen Computers hinzu. Wenn Sie keinen SSH-Schlüssel haben, folgen Sie diesen Anweisungen, um einen zu erstellen. Dieser Befehl kopiert Ihren öffentlichen SSH-Schlüssel und fügt ihn in das Textfeld ein
pbcopy <~ / .ssh / id_rsa.pub
  • Wähle einen Hostnamen: Nenne ihn "nodejs-app"
  • Klicken Sie auf die Schaltfläche Erstellen

Das Tröpfchen ist in wenigen Sekunden fertig.

Abbildung 5

Nodejs-App-Serverkonfiguration

Setzen wir den DevOps-Hut auf und richten Sie unseren Knotenserver ein

Öffnen Sie Ihr Terminal auf Ihrem lokalen Computer und melden Sie sich als Root-Benutzer bei Ihrem nodejs-app-Server an:

ssh root@NODE.SERVER.IP

Jetzt haben Sie sich als Root-Benutzer angemeldet, der ein Super-Power-Benutzer ist. Und „mit großer Kraft geht große Verantwortung einher“.

Da wir keine Verantwortung übernehmen möchten, erstellen wir einen neuen Benutzer, der die Serverkonfiguration durchführt, und benennen ihn nach Ihrem Nachnamen:

adduser 

Wählen Sie das Benutzerpasswort und folgen Sie den Anweisungen. Bevor wir zu unserem neuen Benutzer wechseln, müssen wir ihm sudo-Berechtigungen geben:

usermod -a -G sudo 

Jetzt können Sie zu Ihrem neuen Benutzer wechseln.

su - Benutzername

Stellen Sie die Node-App bereit

Unser DigitalOcean Server wird mit Node aber nicht mit Git ausgeliefert. Lässt git mit app-get installieren:

sudo apt-get install git

Klonen Sie unser Node App Repo:

Git-Klon https://github.com//node-app.git

Navigieren Sie in den Projektordner und installieren Sie die App-Abhängigkeiten:

CD Node-App
npm install - produktion

Bevor wir über den Browser auf unsere App zugreifen können, müssen wir einen weiteren Schritt ausführen. Wie Sie sich erinnern, wird unsere App standardmäßig auf Port 3000 ausgeführt. Die DigitalOcean-Firewall blockiert Clients, die auf einen Port außer 80 zugreifen. Zum Glück enthält Ubuntu ein UFW-Firewall-Konfigurationstool, das Firewall-Regeln hinzufügt, um bestimmte Ports freizugeben.

Lassen Sie uns Port 3000 entsperren und unsere App ausführen:

sudo ufw erlauben 3000
Knoten index.js

Jetzt können Sie auf Ihre Node-App zugreifen, indem Sie den PORT an Ihre IP-Adresse anhängen:

http: //NODE.SERVER.IP: 3000

Node App für immer ausführen

Das Starten der Node-App wie oben ist gut für Entwicklungszwecke, aber nicht für die Produktion. Für den Fall, dass unsere Knoteninstanz abstürzt, benötigen wir einen Prozess, der den automatischen Neustart durchführt. Wir werden das PM2-Modul verwenden, um uns bei dieser Aufgabe zu unterstützen. PM2 ist ein universeller Prozessmanager und eine Produktionslaufzeit für Node.js-Apps mit integriertem Load Balancer. Lassen Sie uns PM2 installieren und unsere Knoteninstanz starten:

sudo npm installiere pm2 @ latest -g
pm2 start index.js

Jetzt ist unser Knotenserver konfiguriert und läuft.

Richten Sie den Jenkins-Server ein

Jenkins Droplet erstellen

Beginnen wir mit der Erstellung eines zweiten DigitalOcean-Droplets für unsere Jenkins-App. Befolgen Sie die Anweisungen im obigen Abschnitt Erstellen eines Knotentröpfchens und wählen Sie "jenkins-app" als Ihren Hostnamen. Sie werden mit 2 Tropfen enden:

Abbildung 6

Neuen Benutzer erstellen

SSH in das neue Droplet als Root-Benutzer, erstelle einen neuen Benutzer, gib ihm Sudo-Rechte und wechsle zum neu hinzugefügten Benutzer:

ssh root@JENKINS.SERVER.IP
adduser 
usermod -a -G sudo 
su - 

Jenkins müssen in der Lage sein, Änderungen aus dem Node App Repo zu übernehmen. Deshalb müssen wir git auf der Instanz installieren:

sudo apt-get install git

Installieren Sie Jenkins

Holen Sie sich Jenkins:

// Den Repository-Schlüssel zum System hinzufügen
wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
// Hänge die Debian-Paket-Repository-Adresse an das Echo deb des Servers an: https://pkg.jenkins.io/debian-stable binary / | sudo tee /etc/apt/sources.list.d/jenkins.list
//aktualisieren
sudo apt-get update

Installieren Sie Jenkins:

sudo apt-get install jenkins

Starten Sie Jenkins:

sudo systemctl status jenkins

Jenkins laufen auf Port 8080. Erinnerst du dich an die Firewall? Öffnen wir den Hafen:

sudo ufw 8080 erlauben

Und jetzt können wir über den Browser auf Jenkins zugreifen, indem wir navigieren zu:

http: //JENKINS.SERVER.IP: 8080

Konfigurieren Sie Jenkins

Beim Navigieren zur Jenkins-Homepage ist Ihnen wahrscheinlich ein zusätzlicher Schritt aufgefallen, den Sie ausführen müssen. Du musst Jenkins freischalten

Abbildung 7

Kopieren Sie das auf Ihrem Jenkins-Server gehostete Jenkins-Passwort

sudo vim / var / lib / jenkins / secrets / initialAdminPassword

Fügen Sie das Passwort in das Textfeld ein. Sie können Jenkins jetzt einrichten. Zunächst möchten wir das GitHub-Plugin hinzufügen. Wählen Sie im linken Menü die Option "Jenkins verwalten" und gehen Sie zu "Plugins verwalten". Wählen Sie auf der Plugins-Seite die verfügbare Registerkarte und suchen Sie nach dem GitHub-Plugin, aktivieren Sie das entsprechende Kontrollkästchen und klicken Sie auf die Schaltfläche Jetzt herunterladen und nach dem Neustart installieren.

Abbildung 8

Scrollen Sie nach Abschluss der Installation nach unten und wählen Sie die Option Jenkins neu starten, wenn die Installation abgeschlossen ist. Dadurch wird Jenkins neu gestartet und die Installation abgeschlossen.

Ändern Sie Ihr Jenkins-Administratorkennwort

Ich schlage an dieser Stelle vor, Ihr Benutzerpasswort für den Jenkins-Administrator zu ändern. Wählen Sie im linken Menü die Option "Jenkins verwalten" und klicken Sie auf "Benutzer verwalten". Wählen Sie den Administrator aus und wählen Sie ein neues Passwort. Sie werden das neue Passwort verwenden, wenn Sie sich in Zukunft bei Jenkins anmelden.

Jenkins Job erstellen

Wir werden unseren Jenkins-Job erstellen, der für das Abrufen von Codeänderungen aus dem Node-App-Git-Repo, das Installieren von Abhängigkeiten, das Ausführen von Integrationstests und das Bereitstellen der Anwendung jedes Mal verantwortlich ist, wenn ein Entwickler Änderungen an der NodeJS-App-Repo-Master-Verzweigung vornimmt.

Klicken Sie auf die Schaltfläche Neues Element, benennen Sie das Element node-app, wählen Sie die Option Frei gestaltete Softwareprojekte erstellen und klicken Sie auf die Schaltfläche OK.

Jenkins Job konfigurieren

Quellcodeverwaltung: Aktivieren Sie das Optionsfeld "Git" und geben Sie den https-Link von github zum Node-App-Repository ein:

https://github.com//node-app.git

Trigger erstellen: Wählen Sie die Option GitHub-Hook-Trigger für GITScm-Polling. Dies startet unseren Jenkins-Job bei jedem Git-Push in der Master-Filiale

Build-Schritt hinzufügen: Klicken Sie auf die Schaltfläche Build-Schritt hinzufügen und wählen Sie die Option Shell ausführen. Geben Sie die folgenden Befehle in den Textbereich ein:

npm install
./script/test

In diesem Build-Schritt installieren wir Abhängigkeiten und führen dann unser Test-Shell-Skript aus.

Abbildung 9

Fügen Sie Git Webhook hinzu

Wir werden Git Webhook hinzufügen, um Jenkins jedes Mal zu informieren, wenn ein Entwickler neuen Code in den Master-Zweig schiebt.

Gehen Sie zu Node-App GitHub, klicken Sie auf die Registerkarte "Einstellungen", wählen Sie "Webhooks" aus dem linken Menü aus und klicken Sie auf die Schaltfläche "Webhooks hinzufügen". Geben Sie Ihre Jenkins-Webhook-URL unter Payload-URL ein:

http: //JENKINS.SERVER.IP: 8080 / github-webhook /

und wählen Sie die Option Nur Push-Ereignis. Klicken Sie auf die Schaltfläche Webhook hinzufügen.

Abbildung 10

Testen wir, was wir bisher haben. Gehen Sie zu Ihrem Node-App-Projekt auf Ihrem Computer und ändern Sie die Version in package.json in 0.0.2. Übernehmen Sie diese Änderung und übertragen Sie sie auf GitHub. Rufen Sie nach dem Pushen im Browser Ihren Jenkins-Job auf und stellen Sie fest, dass der Jenkins-Job erfolgreich gestartet und abgeschlossen wurde.

Einsatz

Das letzte Puzzleteil ist die Bereitstellung unserer Knotenanwendung auf dem Node-App-Server, wenn unser Test bestanden wird.

SSH-Authentifizierung

Dazu muss Jenkins Server in den Node-App-Server ssh, das Repo klonen, Abhängigkeiten installieren und den Server neu starten. Lasst uns zuerst den SSH-Zugang zu Jenkins einrichten.

Bei der Installation von Jenkins wurde automatisch ein Jenkins-Benutzer erstellt. SSH in unseren Jenkins-Server als Root-Benutzer:

ssh root@JENKINS.SERVER.IP

Wechseln Sie zu Jenkins Benutzer:

su - jenkins

SSH-Schlüssel generieren:

ssh-keygen -t rsa

Speichern Sie den generierten Schlüssel in /var/lib/jenkins/.ssh/id_rsa

Drucken Sie den soeben erstellten SSH-Schlüssel aus:

cat ~ / .ssh / id_rsa.pub

Und Kopieren Sie die Ausgabe in Ihre Zwischenablage. Jetzt können Sie den öffentlichen Schlüssel auf dem nodejs-app-Server ablegen, um die Authentifizierung zwischen dem Jenkins-Server und dem nodejs-app-Server abzuschließen.

SSH in den NodeJS-App-Server als root und wechseln Sie zu Ihrem Benutzer:

ssh root@NODE.SERVER.IP
su - 

Öffnen Sie die Datei, in der autorisierte Schlüssel gespeichert sind:

vim ~ / .ssh / authorized_keys

Kopieren Sie den soeben erstellten öffentlichen Jenkins-Schlüssel und fügen Sie ihn in diese Datei ein. Speichern Sie durch Drücken der Esc-Taste auf Ihrer Tastatur, geben Sie: x ein und drücken Sie die Eingabetaste.

Legen Sie die richtige Berechtigung für den Ordner ".ssh" fest:

chmod 700 ~ / .ssh
chmod 600 ~ / .ssh / *

Bevor wir weitermachen, testen wir unser SSH-Setup. Wenn die Einrichtung korrekt ist, können wir SSH von JENKINS.SERVER.IP als jenkins-Benutzer zu @ NODE.SERVER.IP ausführen, ohne ein Kennwort einzugeben

ssh root@JENKINS.SERVER.IP
su - jenkins
ssh  @ NODE.SERVER.IP

Erfolg!

Automatische Bereitstellung

Wir werden ein weiteres Shell-Skript erstellen, das für die Bereitstellung verantwortlich ist. Erstellen Sie eine Datei unter dem Skript "deploy" und fügen Sie das folgende Skript hinzu:

#! / bin / sh
ssh ezderman@NODE.SERVER.IP << EOF
 cd ~ / node-app
 Git ziehen
 npm install - produktion
 pm2 alle neu starten
 Ausfahrt
EOF

Mit diesem Skript wird eine SSH-Verbindung zum Knotenserver hergestellt, Änderungen von GitHub übernommen, Abhängigkeiten installiert und der Server neu gestartet.

Machen Sie unsere neue Skriptdatei ausführbar:

chmod + x script / deploy

Bevor wir unsere Änderungen festschreiben, fügen wir den Bereitstellungsschritt zu unserem Jenkins-Job hinzu:

Abbildung 11

Und speichern.

Der Moment der Wahrheit

Wir sind bereit, alles zu testen, was wir gebaut haben. Gehen Sie zu Ihrem nodejs-app-Projekt und bearbeiten Sie die Datei index.js, um mit "Hey World" zu antworten. Vergessen Sie nicht, Ihre test / test.js zu ändern, um auch auf diese Zeichenfolge zu testen.

Commit und Push:

Git hinzufügen.
git commit -m 'Bereitstellungsskript hinzufügen'
Git Push Origin Master

Nachdem Sie gedrückt haben, sollte Jenkins Job gestartet werden. Wenn Sie fertig sind, sollten Sie Ihre Änderungen auf http: //NODE.SERVER.IP: 3000 sehen

Abbildung 12

Und wir sind fertig!