Einführung
Docker ist eine Container-Plattform, die eine leichtgewichtige, virtualisierte, portable, softwaredefinierte standardisierte Umgebung darstellt. Sie ermöglicht es der Software, isoliert von anderer Software zu laufen, die auf dem physischen Host-Rechner ausgeführt wird. Docker ist eine entscheidende Komponente des Continuous Development and Integration-Aspekts der Softwareentwicklung. Sie bietet eine leichtgewichtige Alternative zu virtuellen Maschinen und ermöglicht es Entwicklern, verteilte Anwendungsarchitekturen zu nutzen. Für einen gründlichen Überblick über das Docker-Ökosystem, lesen Sie diesen Artikel.
Der Prozess des Erstellens einer Anwendung mit Docker beginnt damit, dass ein Entwickler ein Image für seine Anwendung erstellt. Anschließend wird das Image in einem Container bereitgestellt. Das Image enthält definierende Komponenten einer Anwendung wie den Anwendungscode, Bibliotheken, Konfigurationsdateien, Umgebungsvariablen und die Laufzeitumgebung. Das Image standardisiert die Umgebung innerhalb eines Containers, was der Containerisierung die Portabilitätseigenschaften verleiht. Node.js ist eine Open-Source, plattformübergreifende Backend-JavaScript-Laufzeitumgebung, die JavaScript-Code außerhalb eines Webbrowsers ausführen kann. Sie basiert auf Chromes V8 JavaScript Engine. Express.js ist ein minimalistisches Backend-JavaScript-Framework, das auf Node.js läuft.
In diesem Tutorial werden wir ein Image für eine Website erstellen, die auf dem Express-Framework läuft. Wir werden Bootstrap, eine Frontend-Bibliothek, verwenden, um das Frontend ansprechender zu gestalten. Sobald wir das Image erstellt haben, werden wir einen Container bauen und ihn auf Docker Hub hochladen. Docker Hub ermöglicht es Entwicklern, containerisierte Anwendungen für eine einfache Bereitstellung in jeder Docker-Umgebung zu hosten. Sobald Ihr Container auf Docker Hub gehostet ist, werden wir ihn herunterladen (pullen) und ein weiteres Image erstellen, das tatsächlich unsere Website bereitstellt.
Voraussetzungen
Dies wird ein praktisches Tutorial sein. Sie sollten eine Umgebung erstellen, die es Ihnen ermöglicht, den Schritten zu folgen.
- Sie sollten eine Installation von Ubuntu 20.04 als Ihre anfängliche Betriebsumgebung haben und einen Nicht-Root-Benutzer mit sudo-Rechten erstellen. Melden Sie sich mit dem Nicht-Root-Benutzer an und fahren Sie mit den folgenden Schritten fort.
- Sie müssen Docker installieren. Folgen Sie den Schritten 1, 2, 3 und 4 unseres Tutorials über die Installation und den Betrieb von Docker auf Ubuntu. Dies sollte für jede Ubuntu-Distribution funktionieren.
- Erstellen Sie ein Docker Hub-Konto, falls Sie noch keines haben. Sie können diesem Link folgen für die Docker Hub-Schnellstartanleitung.
- Installieren Sie Node.js und NPM. NPM ist ein JavaScript-Paketmanager. Sie können diesen Anweisungen zur Installation von Node und npm folgen.
Schritt 1: Anwendungsabhängigkeiten konfigurieren
Sie müssen Ihren Anwendungsquellcode erstellen, bevor Sie das Image erstellen können. Der Anwendungsquellcode umfasst Code, statische Inhalte und Abhängigkeiten, die in den Container kopiert werden. Beginnen Sie mit dem Erstellen eines Verzeichnisses für Ihr Projekt im Home-Verzeichnis des Nicht-Root-Benutzers. Wir nennen es node_express, aber es steht Ihnen frei, einen Verzeichnisnamen Ihrer Wahl zu verwenden:
|
1 |
mkdir node_express |
Wechseln Sie als Nächstes in dieses Verzeichnis:
|
1 |
cd node_express |
Dies wird Ihr Anwendungs-Root-Verzeichnis sein. Eine node.js-Anwendung erwartet eine package.json-Datei im Root-Ordner. Npm verwendet diese Datei, um zu bestimmen, welche Abhängigkeiten Ihre Anwendung benötigt. Geben Sie den folgenden Befehl ein, um diese Datei zu erstellen:
|
1 |
nano package.json |
Fügen Sie danach das folgende Code-Snippet in die Datei ein. Sie können den Namen, den Autor, die Beschreibung und die Einstiegspunkt-Datei nach Belieben anpassen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "name": "node-express-docker-image", "version": "1.0.0", "description": "Nodejs Express Docker Image Example", "author": "hackins", "main": "index.js", "license": "ISC", "keywords": [ "nodejs", "express", "bootstrap" ], "dependencies": { "express": "^4.17.1" } } |
Wie Sie sehen können, gibt diese Datei den Projektnamen, die Version, den Autor und die Lizenz an, unter der der Anwendungscode geteilt wird. Es wird empfohlen, einen kurzen und beschreibenden Namen für Ihr Projekt zu verwenden, um Duplikate in der npm-Registry zu vermeiden. Wir haben die ISC-Lizenz für das Projekt angegeben, die das freie Kopieren, Ändern oder Verteilen des Anwendungscodes erlaubt.
Am wichtigsten ist, dass Sie die folgenden Direktiven in der Datei beachten sollten:
- “
main“: Diese Direktive gibt den Einstiegspunkt der Anwendung an, den wir als index.js festgelegt haben. Wir werden diese Datei in Kürze erstellen. - “
dependencies“: Diese Direktive gibt die Anwendungsabhängigkeiten an, die aus der npm-Registry abgerufen werden, wenn wir den Befehlnpmausführen, in unserem Fall wollen wir Express-Version 4.17.1 und höher.
Sie können die Datei nun speichern, indem Sie Strg + O drücken. Schließen Sie die Datei anschließend, indem Sie Strg + X drücken. Als Nächstes installieren wir die Abhängigkeiten, indem wir den folgenden Befehl ausführen:
|
1 |
npm install |
Der Befehl installiert die in der Datei package.json im Verzeichnis node_modules angegebenen Anwendungsabhängigkeiten. Diese wurden automatisch erstellt, als Sie den Befehl zum ersten Mal ausgeführt haben. Da unsere Anwendungsabhängigkeiten nun installiert sind, können Sie mit dem Hinzufügen des Anwendungscodes beginnen.
Schritt 2: Hinzufügen Ihrer Anwendungscode-Dateien
Wir werden eine einfache Rezept-Website erstellen, mit freundlicher Genehmigung von allrecipes. Der Haupteinstiegspunkt für die Anwendung ist die Datei index.js file. Wir werden ein Verzeichnis views hinzufügen, das die verschiedenen Seiten und statischen Assets des Projekts enthält. Die Website wird eine Landingpage haben, die einführende Informationen und Links zu einigen Rezepten enthält.
Der Code für unsere Landingpage wird in der Datei home.html abgelegt. Erstellen Sie zuerst die Datei index.js, indem Sie den folgenden Befehl eingeben:
|
1 |
nano index.js |
Fügen Sie den folgenden Code hinzu, der eine Express-Anwendung importiert und erstellt. Er gibt auch das Router-Objekt, das Basisverzeichnis und den Port an, auf dem diese App bereitgestellt wird:
|
1 2 3 4 5 6 |
const express = require('express'); const app = express(); const router = express.Router(); const path = __dirname + '/views/'; const port = 8090; |
require ist eine JavaScript-Funktion, die ein Modul lädt. In diesem Fall laden wir das express-Modul. Anschließend verwenden wir das importierte Modul, um die express- und router-Objekte zu erstellen. Das router-Objekt führt die Routing-Funktionen der App aus, indem es auf HTTP-Methodenaufrufe reagiert, die wir im Laufe des Tutorials zu diesem Objekt hinzufügen werden.
Wir haben auch path und port festgelegt. Die path-Konstante definiert das Basisverzeichnis für den Code. In unserem Fall ist es das Unterverzeichnis views innerhalb des Projekt-Stammverzeichnisses. Der port gibt den Port an, auf dem die Express-App lauschen soll, in unserem Beispiel haben wir ihn auf 8090.
Sobald wir die Konstanten haben, können wir mit dem router-Objekt einige Routen für die Anwendung festlegen. Fügen Sie der Datei index.js den folgenden Code hinzu, um die Routen anzugeben:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
router.use(function (req,res,next) { console.log('/' + req.method); next(); }); router.get('/', function(req,res){ res.sendFile(path + 'home.html'); }); router.get('/lasagna', function(req,res){ res.sendFile(path + 'lasagna.html'); }); router.get('/guacamole', function(req,res){ res.sendFile(path + 'guacamole.html'); }); router.get('/banana-bread', function(req,res){ res.sendFile(path + 'banana_bread.html'); }); |
Sie können Middleware zu Routen hinzufügen, indem Sie die router.use-Funktion verwenden. In diesem Fall fügen wir eine Funktion hinzu, die die Anfragen des Routers protokolliert, bevor sie an die Anwendungsrouten weitergegeben werden. Eine GET-Anfrage an die Basis der Anwendung liefert eine home.html-Seite. Danach haben wir Seiten für drei Rezepte hinzugefügt, die ebenfalls über die GET-Anfrage für die spezifische Rezeptseite abgerufen werden.
Fügen Sie schließlich den folgenden Code hinzu, um die router-Middleware und die statischen Assets der Anwendung zu mounten. Sagen Sie der Express-Anwendung außerdem, dass sie auf dem Port 8090:
|
1 2 3 4 5 6 |
app.use(express.static(path)); app.use('/', router); app.listen(port, function () { console.log('Nodejs Express Beispiel-App läuft auf Port ' + port) }) |
Ihre vollständige index.js-Datei sollte wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
const express = require('express'); const app = express(); const router = express.Router(); const path = __dirname + '/views/'; const port = 8090; router.use(function (req,res,next) { console.log('/' + req.method); next(); }); router.get('/', function(req,res){ res.sendFile(path + 'home.html'); }); router.get('/lasagna', function(req,res){ res.sendFile(path + 'lasagna.html'); }); router.get('/guacamole', function(req,res){ res.sendFile(path + 'guacamole.html'); }); router.get('/banana-bread', function(req,res){ res.sendFile(path + 'banana_bread.html'); }); app.use(express.static(path)); app.use('/', router); app.listen(port, function () { console.log('Nodejs Express Beispiel-App läuft auf Port ' + port) }) |
Sie können die Datei nun speichern und schließen. Der nächste Schritt besteht darin, die statischen Webseiten zum Verzeichnis views hinzuzufügen. Geben Sie zunächst den folgenden Befehl ein, um das Verzeichnis zu erstellen:
|
1 |
mkdir views |
Geben Sie den folgenden Befehl ein, um die home.html-Landingpage-Datei zu öffnen:
|
1 |
nano views/home.html |
Fügen Sie den folgenden Code in die Datei ein. Der Code importiert Bootstrap und bietet Website-Besuchern einige Informationen darüber, worum es auf der Website geht:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton und Bootstrap-Mitwirkende"> <meta name="generator" content="Hugo 0.80.0"> <title>Tolle Rezepte</title> <!-- Bootstrap-Core-CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Navigation umschalten</span> </button> <a class="navbar-brand" href="#">Tolle Rezepte</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Startseite</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Bananenbrot</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">Tolles Rezept</h1> <p class="lead text-muted"> Finden und teilen Sie alltägliche Kochinspirationen aus diesen tollen Rezepten. Entdecken Sie Rezepte, Köche, Videos und Anleitungen basierend auf dem Essen, das Sie lieben, und den Freunden, denen Sie folgen. <br /> <em>(Nichts Ernstes, dies ist nur für unsere Demo-node-express-docker-Image-App)</em> </p> </div> </div> </section> </main> </body> </html> |
Neben dem Importieren von Bootstrap fügt die Seite auch ein grundlegendes Navigationsmenü hinzu, das uns hilft, durch die Seiten und zurück zur Startseite zu navigieren. Wir haben auch eine Zeile hinzugefügt, um unsere benutzerdefinierte CSS-Datei zu importieren:
|
1 |
<link href="css/custom.css" rel="stylesheet"> |
Wir werden diese Datei später verwenden, um der Anwendung ein benutzerdefiniertes Styling hinzuzufügen. Lassen Sie uns nun die drei Seiten für die Rezepte erstellen. Wir beginnen mit der Erstellung der Lasagne-Seite. Öffnen Sie die Datei mit dem Nano-Editor mit dem folgenden Befehl:
|
1 |
nano views/lasagna.html |
Fügen Sie in der geöffneten Datei den folgenden Code hinzu. Diese Datei importiert Bootstrap, die custom.css-Datei, definiert ein Navigationsmenü und bietet einige Informationen zum Lasagne-Rezept:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton und Bootstrap-Mitwirkende"> <meta name="generator" content="Hugo 0.80.0"> <title>Lasagne-Rezept</title> <!-- Bootstrap-Core-CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Navigation umschalten</span> </button> <a class="navbar-brand" href="#">Tolle Rezepte</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Startseite</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Bananenbrot</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">Das beste Lasagne-Rezept</h1> <p class="lead text-muted"> Dies ist die beste Lasagne, die Sie je zubereiten werden. <br /> <em>(Nichts Ernstes, dies ist nur für unsere Demo-App mit dem node-express-docker-Image)</em> </p> <h3>Zutaten</h3> <ul class="list-group"> <li class="list-group-item">1 Pfund süße italienische Bratwurst</li> <li class="list-group-item">¾ Pfund mageres Rinderhackfleisch</li> <li class="list-group-item">½ Tasse fein gehackte Zwiebel</li> <li class="list-group-item">2 Knoblauchzehen, zerdrückt</li> <li class="list-group-item">1 Dose (28 Unzen) gestückelte Tomaten</li> <li class="list-group-item">2 Dosen (je 6 Unzen) Tomatenmark</li> <li class="list-group-item">2 Dosen (je 6,5 Unzen) Tomatensauce</li> <li class="list-group-item">½ Tasse Wasser</li> <li class="list-group-item">2 Esslöffel weißer Zucker</li> <li class="list-group-item">1 ½ Teelöffel getrocknete Basilikumblätter</li> <li class="list-group-item">½ Teelöffel Fenchelsamen</li> <li class="list-group-item">1 Teelöffel italienische Kräutermischung</li> <li class="list-group-item">1 ½ Teelöffel Salz, aufgeteilt, oder nach Geschmack</li> <li class="list-group-item">¼ Teelöffel gemahlener schwarzer Pfeffer</li> <li class="list-group-item">4 Esslöffel gehackte frische Petersilie</li> <li class="list-group-item">12 Lasagneplatten</li> <li class="list-group-item">16 Unzen Ricotta</li> <li class="list-group-item">1 Ei</li> <li class="list-group-item">¾ Pfund Mozzarella, in Scheiben</li> <li class="list-group-item">¾ Tasse geriebener Parmesankäse</li> </ul> </div> </div> </section> </main> </body> </html> |
Gehen wir genauso vor, um eine Datei für die Guacamole-Rezeptseite zu erstellen. Öffnen Sie die Datei mit nano, indem Sie folgenden Befehl ausführen:
|
1 |
nano views/guacamole.html |
Fügen Sie dann diesen Code zur Datei hinzu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.80.0"> <title>Guacamole-Rezept</title> <!-- Bootstrap-Core-CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Navigation umschalten</span> </button> <a class="navbar-brand" href="#">Tolle Rezepte</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Startseite</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Bananenbrot</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">Das beste Guacamole-Rezept</h1> <p class="lead text-muted"> Sie können diesen Avocadosalat je nach Geschmack cremig oder stückig zubereiten. <br /> <em>(Nichts Ernstes, dies dient nur für unsere Demo-Node-Express-Docker-Image-App)</em> </p> <h3>Zutaten</h3> <ul class="list-group"> <li class="list-group-item">3 Avocados – geschält, entkernt und zerdrückt</li> <li class="list-group-item">1 Limette, ausgepresst</li> <li class="list-group-item">1 Teelöffel Salz</li> <li class="list-group-item">½ Tasse gewürfelte Zwiebel</li> <li class="list-group-item">3 Esslöffel gehackter frischer Koriander</li> <li class="list-group-item">2 Roma-Tomaten (Eiertomaten), gewürfelt</li> <li class="list-group-item">1 Teelöffel fein gehackter Knoblauch</li> <li class="list-group-item">1 Prise gemahlener Cayennepfeffer (optional)</li> </ul> </div> </div> </section> </main> </body> </html> |
Erstellen wir schließlich die Datei banana_bread.html, indem wir folgenden Befehl eingeben:
|
1 |
nano views/banana_bread.html |
Fügen Sie dann den folgenden HTML-Code in die Datei ein:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.80.0"> <title>Bananenbrot-Rezept</title> <!-- Bootstrap-Basis-CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md"> <div class="container"> <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Navigation umschalten</span> </button> <a class="navbar-brand" href="#">Tolle Rezepte</a> <div class="collapse navbar-collapse justify-content-center" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav justify-content-center"> <li class="active nav-item"> <a href="/" class="nav-link">Startseite</a> </li> <li class="nav-item"> <a href="/lasagna" class="nav-link">Lasagne</a> </li> <li class="nav-item"> <a href="/guacamole" class="nav-link">Guacamole</a> </li> <li class="nav-item"> <a href="/banana-bread" class="nav-link">Bananenbrot</a> </li> </ul> </div> </div> </nav> <main> <section class="py-5 text-center container bg-light"> <div class="row py-lg-5"> <div class="col-lg-6 col-md-8 mx-auto"> <h1 class="fw-light">Das beste Bananen-Bananenbrot-Rezept</h1> <p class="lead text-muted"> Warum Kompromisse beim Bananengeschmack eingehen? Dieses Bananenbrot ist saftig und köstlich mit intensivem Bananengeschmack! Freunde und Familie lieben mein Rezept und sagen, es sei bei weitem das beste! Es schmeckt herrlich getoastet!! Guten Appetit! <br /> <em>(Nichts Ernstes, dies ist nur für unsere Demo-Node-Express-Docker-Image-App)</em> </p> <h3>Zutaten</h3> <ul class="list-group"> <li class="list-group-item">2 Tassen Allzweckmehl</li> <li class="list-group-item">1 Teelöffel Natron</li> <li class="list-group-item">¼ Teelöffel Salz</li> <li class="list-group-item">½ Tasse Butter</li> <li class="list-group-item">¾ Tasse brauner Zucker</li> <li class="list-group-item">2 Eier, verquirlt</li> <li class="list-group-item">2⅓ Tassen zerdrückte, überreife Bananen</li> </ul> </div> </div> </section> </main> </body> </html> |
Nun haben wir alle Seiten erstellt. Wenn Sie sich erinnern, müssen wir noch die Datei css/custom.css hinzufügen. Geben Sie den folgenden Befehl ein, um das Verzeichnis zu erstellen:
|
1 |
mkdir views/css |
Erstellen und öffnen Sie die Datei dann im Nano-Editor mit dem Befehl:
|
1 |
nano views/css/custom.css |
Sie können weitere CSS-Codes hinzufügen, um Ihre Website nach Belieben zu gestalten. Der Kürze halber fügen wir der Datei folgendes Code-Snippet hinzu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.bd-placeholder-img { font-size: 1.125rem; text-anchor: middle; -webkit-user-select: none; -moz-user-select: none; user-select: none; } @media (min-width: 768px) { .bd-placeholder-img-lg { font-size: 3.5rem; } } |
Speichern und schließen Sie die Datei, wenn Sie fertig sind.
Sie können die Anwendung starten, da wir nun den Quellcode der Anwendung und die Projektabhängigkeiten installiert haben.
Wir haben die App so eingestellt, dass sie auf dem Port 8090 lauscht. Führen Sie den folgenden Befehl aus, um die Firewall anzuweisen, Datenverkehr über diesen Port zuzulassen. Wenn Sie einen anderen Port angegeben haben, ersetzen Sie die Portnummer im Befehl:
|
1 |
sudo ufw allow 8090 |
Jetzt können Sie die Anwendung starten. Stellen Sie jedoch zuerst sicher, dass Sie sich im Stammverzeichnis des Projekts befinden, indem Sie den folgenden Befehl ausführen:
|
1 |
cd ~/node_express |
Starten Sie die Anwendung mit node index.js. Wenn Sie einen anderen Einstiegspunkt angegeben haben, ersetzen Sie diesen durch Ihren Einstiegspunkt:
|
1 |
node index.js |
Wenn Sie in Ihrem Browser zu http://your_public_server_ip:8090 navigieren, sehen Sie die Landingpage für Rezepte wie definiert:
Sie können die Links zu den verschiedenen Rezepten in der Navigation sehen. Klicken wir auf einige. Unten sehen wir die Lasagne-Rezeptseite:
Und hier haben wir die Guacamole-Rezeptseite:
Bis zu diesem Punkt haben Sie Ihre Anwendung erstellt und getestet, ob sie wie erwartet funktioniert. Sie können den Server durch Drücken von Strg + C beenden und mit der Erstellung der Dockerfile fortfahren. Dockerfiles helfen bei der Skalierbarkeit, indem sie es ermöglichen, eine Instanz einer Anwendung bei Bedarf neu zu erstellen.
Schritt 3: Erstellen der Dockerfile
Docker liest beim Erstellen von Images die in einem Dockerfile angegebenen Anweisungen. Es spezifiziert die Laufzeitumgebung einer Anwendung. Daher hilft es Entwicklern, Unstimmigkeiten bei Abhängigkeiten oder sich ändernden Laufzeitversionen zu vermeiden. Geben Sie den folgenden Befehl ein, um das Dockerfile zu erstellen:
|
1 |
nano Dockerfile |
Ein Docker-Image wird aus mehreren Image-Ebenen erstellt, die aufeinander aufbauen. Sie beginnen mit dem Hinzufügen eines Basis-Images, das den Ausgangspunkt für die App bildet.
Da die Anwendung in einer node.js-Umgebung ausgeführt werden soll, beginnen wir mit dem Hinzufügen des node:10-alpine-Images für node.js. Zum Zeitpunkt der Erstellung dieses Tutorials ist dies die empfohlene LTS-Version von Node.js. Wir haben dieses spezifische Image gewählt, da es vom Alpine Linux-Projekt abgeleitet ist. Daher hilft es, unsere Image-Größe minimal zu halten. Es gibt verschiedene Image-Varianten auf der Docker Hub Node-Images-Seite, aus denen Sie je nach Ihren Anforderungen wählen können.
Fügen Sie den folgenden Code hinzu, um das Basis-Image der Anwendung mithilfe der FROM-Anweisung festzulegen:
|
1 |
FROM node:10-alpine |
Dieses Image enthält Node.js und npm. Jedes Dockerfile muss mit einer FROM-Anweisung beginnen. Das Docker-node-Image enthält standardmäßig einen Nicht-Root-Benutzer „node“, den Sie verwenden können, um Ihren Anwendungscontainer als Root auszuführen. Docker-Sicherheit empfiehlt, Container nicht als Root auszuführen und die Berechtigungen auf diejenigen zu beschränken, die für die Ausführung der Ressourcen erforderlich sind.
In diesem Fall verwenden wir das Home-Verzeichnis des node-Benutzers als Arbeitsverzeichnis für die Anwendung sowie den Benutzer innerhalb des Containers. Sie können diesen Best Practices für Docker-Node-Images-Leitfaden für weitere Informationen lesen.
Wir werden das Unterverzeichnis node_modules innerhalb von /home/node zusammen mit dem App-Verzeichnis erstellen, um die Berechtigungen für den Anwendungscode zu optimieren. Das Erstellen dieser Verzeichnisse stellt sicher, dass sie die richtigen Berechtigungen haben, wenn wir den Befehl npm install lokal in den Containern ausführen. Sobald Sie die Verzeichnisse erstellt haben, müssen Sie deren Eigentümerschaft auf den Benutzer node übertragen. Wir tun dies im Dockerfile, indem wir die folgende Zeile hinzufügen:
|
1 |
mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app |
Dann legen Sie das Arbeitsverzeichnis fest, indem Sie die folgende Zeile hinzufügen:
|
1 |
WORKDIR /home/node/app |
Es ist eine gute Idee, immer das WORKDIR festzulegen, damit Docker nicht standardmäßig eines erstellen muss.
Fügen Sie die folgende Zeile hinzu, um die Dateien package.json und package-lock.json zu kopieren:
|
1 |
COPY package*.json ./ |
Es wird empfohlen, die Anweisung COPY vor dem Ausführen von npm install oder dem Kopieren des Anwendungsquellcodes hinzuzufügen. Dadurch können Sie den Caching-Mechanismus von Docker nutzen. Während des Build-Prozesses prüft Docker, ob für jede Anweisung eine Ebene im Cache gespeichert ist. Das bedeutet, wenn Sie die Datei package.json nicht geändert haben, verwendet Docker die vorhandene Image-Ebene und vermeidet die Neuinstallation von node modules, was zu schnelleren Build-Prozessen führt.
Vor dem Ausführen von npm install, fügen Sie die folgende Zeile hinzu, um den Benutzer zu node zu wechseln, um sicherzustellen, dass alle Anwendungsdateien und das Verzeichnis node_modules dem Nicht-Root-Benutzer „node“ gehören:
|
1 |
USER node |
Unser Container ist nun bereit, den Befehl „npm install“ auszuführen. Fügen Sie die folgende Zeile zum Dockerfile hinzu:
|
1 |
RUN npm install |
Sobald node_modules installiert wurden, fügen Sie die folgende Zeile hinzu, die Docker anweist, den Anwendungscode mit den richtigen Berechtigungen und der richtigen Eigentümerschaft, d. h. dem Nicht-Root-Benutzer „node“, in das Anwendungsverzeichnis auf dem Container zu kopieren:
|
1 |
COPY --chown=node:node . . |
Der letzte Schritt besteht darin, den Port 8090 auf dem Container freizugeben, wie wir es in unserer Einstiegsdatei index.js definiert hatten:
|
1 2 |
EXPOSE 8090 CMD [ "node", "index.js" ] |
EXPOSE legt fest, welche Ports auf dem Container zur Laufzeit geöffnet sein werden. CMD führt den Befehl zum Starten der Anwendung aus, in diesem Fall „node index.js“.
Sie sollten nur einen CMD-Befehl im Dockerfile haben, da nur der letzte wirksam ist. Bitte lesen Sie die Dockerfile-Referenzdokumentation für eine Liste von Dingen, die Sie mit Dockerfile tun können.
Ihr vollständiges Dockerfile sollte wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 |
FROM node:10-alpine RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app COPY package*.json ./ USER node RUN npm install COPY --chown=node:node . . EXPOSE 8090 CMD [ "node", "index.js" ] |
Sie können die Datei nun speichern und schließen.
Als Nächstes fügen Sie die .dockerignore-Datei hinzu. Genau wie die .gitignore-Datei gibt die .dockerignore an, welche Dateien und Verzeichnisse im Projektverzeichnis nicht in den Container kopiert werden sollen.
Öffnen Sie die Datei mit dem Nano-Editor:
|
1 |
nano .dockerignore |
Fügen Sie die folgenden Zeilen in die Datei ein:
|
1 2 3 4 |
node_modules npm-debug.log Dockerfile .dockerignore |
Wenn Sie mit einem git-Repository arbeiten, sollten Sie auch das .git-Verzeichnis und die .gitignore-Datei hinzufügen. Speichern und schließen Sie die Datei.
Wenn alles gut gegangen ist, ist es an der Zeit, das Anwendungs-Image mit dem Befehl docker build zu erstellen. Sie können das Flag –t zum Befehl docker build hinzufügen, um das Image mit einem einprägsamen Namen zu versehen, anstatt der zufälligen Zeichenfolge, die Docker standardmäßig festlegt. Wir werden das Image auch auf Docker Hub hochladen, daher ist es am besten, Ihren Docker Hub-Benutzernamen in das Tag aufzunehmen.
Wir werden nodejs-express-image als Tag-Namen verwenden. Es steht Ihnen frei, einen Tag-Namen zu wählen, der Ihnen gefällt. Hier ist der Befehl zum Erstellen des Images:
|
1 |
sudo docker build -t your_dockerhub_username/nodejs-express-image . |
Denken Sie daran, your_dockerhub_username durch Ihren tatsächlichen Docker Hub-Benutzernamen zu ersetzen. Der . (Punkt) am Ende gibt an, dass der Build-Kontext das aktuelle Verzeichnis ist.
Der Build-Prozess dauert ein oder zwei Minuten. Sobald er abgeschlossen ist, geben Sie den Befehl ein, um Ihre Images zu überprüfen:
|
1 |
sudo docker images |
Sie sollten etwas Ähnliches wie das hier sehen:
Denken Sie daran, dass wir your_dockerhub_username durch einen tatsächlichen Benutzernamen ersetzt haben.
Nachdem Sie sich vergewissert haben, dass Ihr Image erstellt wurde, können Sie nun mit docker run einen Container mit dem Image erstellen. Die folgenden Flags werden enthalten sein:
-p: veröffentlicht den Port auf dem Container und leitet ihn an einen Port auf dem Host-System weiter. Wir werden zu Demonstrationszwecken Port 80 auf dem Host-System verwenden. Wenn Sie jedoch einen anderen Prozess auf diesem Port ausführen haben, können Sie dies nach Bedarf anpassen. Erfahren Sie mehr über Port-Bindung in der Docker-Dokumentation.-d: für den Detached-Modus. Ermöglicht es dem Container, im Hintergrund weiterzulaufen.--name: Sie können dies verwenden, um einen einprägsamen Namen festzulegen, anstatt Docker eine zufällige Zeichenfolge zuweisen zu lassen.
Der Befehl zum Erstellen des Containers lautet wie folgt. Ersetzen Sie Ihren Docker Hub-Benutzernamen entsprechend:
|
1 |
sudo docker run --name nodejs-express-image -p 80:8090 -d your_dockerhub_username/nodejs-express-image |
Warten Sie, bis der Container erstellt wurde und läuft. Sie können diesen Befehl verwenden, um alle laufenden Container zu überprüfen:
|
1 |
sudo docker ps |
Sie sollten eine Ausgabe ähnlich der folgenden sehen:
Wie in der Ausgabe zu sehen ist, läuft der Container nun. Sie können ihn im Browser anzeigen, indem Sie die öffentliche IP-Adresse Ihres Servers ohne den Port im Browser aufrufen. Ihre Startseite wird geladen:
Sie haben erfolgreich eine statische Node Express-Website mit Docker bereitgestellt. Sehen wir uns an, wie wir dieses Image für die zukünftige Verwendung und Skalierung auf Docker Hub hochladen können.
Schritt 4: Arbeiten mit Docker-Image-Repositories
Sie können Ihre Images in Image-Registries wie Docker Hub übertragen und für die zukünftige Verwendung speichern, sie mit anderen Entwicklern teilen oder die Skalierung Ihrer Container ermöglichen. Wir können das von uns erstellte Image auf Docker Hub übertragen und verwenden, um einen Container neu zu erstellen.
Verwenden Sie den folgenden Befehl, um sich bei Ihrem Docker Hub-Konto anzumelden. Ersetzen Sie ihn durch Ihren tatsächlichen Docker Hub-Benutzernamen:
|
1 |
sudo docker login -u your_dockerhub_username |
Geben Sie Ihr Passwort ein, wenn Sie dazu aufgefordert werden. Sobald Sie angemeldet sind, wird eine ~/.docker/config.json-Datei im Home-Verzeichnis Ihres Benutzers erstellt, die Ihre Docker Hub-Anmeldedaten enthält.
Geben Sie anschließend den folgenden Befehl ein, um das Image auf Docker Hub zu übertragen, und geben Sie dabei den Tag an, den Sie zuvor beim Erstellen des Images festgelegt haben:
|
1 |
sudo docker push your_dockerhub_username/nodejs-express-image |
Dieser Befehl überträgt das Docker-Image auf Ihr Docker Hub-Konto. Wenn Sie Ihr Konto besuchen, können Sie Ihr kürzlich übertragenes Image sehen:
Wir können die Nützlichkeit des Image-Repositorys testen, indem wir den aktuellen Anwendungscontainer zerstören und ihn mithilfe des Images im Repository neu erstellen.
Listen Sie Ihre aktuellen Container auf, indem Sie folgenden Befehl eingeben:
|
1 |
sudo docker ps |
Sie sollten eine Ausgabe ähnlich wie diese sehen:
Notieren Sie sich die CONTAINER ID, die in Ihrer Ausgabe aufgeführt ist, kopieren Sie sie und verwenden Sie sie, um Ihren Container mit dem Befehl zu stoppen, wobei Sie die ID durch Ihre eigene ersetzen:
|
1 |
sudo docker stop 1bb2d65279bb |
Geben Sie den folgenden Befehl ein, um alle in Ihrem System verfügbaren Docker-Images aufzulisten:
|
1 |
sudo docker images –a |
Die Ausgabe zeigt den Namen Ihres Images, das node.js-Image und andere Images aus dem Build-Prozess.
Geben Sie den folgenden Befehl ein, um die Images zu entfernen, einschließlich ungenutzter oder verwaister Images:
|
1 |
sudo docker system prune |
Geben Sie y ein, um zu bestätigen. Dies entfernt die gestoppten Container und Images. Wenn Sie sie auflisten, sehen Sie eine leere Liste in der Ausgabe:
Nun haben Sie sowohl den Container, in dem die Anwendung ausgeführt wird, als auch das Image selbst entfernt. Erfahren Sie mehr über das Entfernen von Docker-Containern, -Images und -Volumes, indem Sie unserem Tutorial folgen.
Wir können nun den gesamten Prozess neu erstellen, indem wir zuerst das Image mit dem folgenden Befehl von Docker Hub abrufen. Ersetzen Sie Ihren Docker Hub-Benutzernamen entsprechend:
|
1 |
sudo docker pull your_dockerhub_username/nodejs-express-image |
Listen Sie Ihre Docker-Images erneut mit dem Befehl auf:
|
1 |
sudo docker images |
Sie sollten das Image in der Ausgabe sehen:
Sie können Ihren Container nun mit dem Befehl aus Schritt 3 neu erstellen. Ersetzen Sie natürlich Ihren Docker Hub-Benutzernamen an den entsprechenden Stellen:
|
1 |
sudo docker run --name nodejs-express-image -p 80:8090 -d your_dockerhub_username/nodejs-express-image |
Listen Sie Ihre Container auf, um zu bestätigen, dass sie neu erstellt wurden:
|
1 |
sudo docker ps |
Sie sollten eine ähnliche Ausgabe sehen:
Navigieren Sie in Ihrem Browser zur öffentlichen IP-Adresse Ihres Servers, und Sie sollten Ihre App laufen sehen.
Fazit
Wenn Sie dem Tutorial bis zu diesem Punkt gefolgt sind, haben Sie nun eine statische Website, die mit Express und Bootstrap erstellt und mit Docker bereitgestellt wurde. Sie haben die statischen Website-Dateien verwendet, um ein Docker-Image zu erstellen, und das Image verwendet, um einen Container zu erstellen. Anschließend haben Sie das Image in eine Docker-Image-Registry übertragen, Docker Hub, wodurch es für die zukünftige Verwendung oder Skalierung verfügbar wird. Um die Verwendung der Image-Registry zu testen, haben Sie die Images und Container zerstört, die Images aus der Registry abgerufen und die Container neu erstellt.
In diesem Tutorial wurde erklärt, wie man eine Node.js-App bereitstellt. Wenn Sie erfahren möchten, wie Sie einen anderen Webentwicklungs-Stack verwenden, haben wir ein Tutorial zum Thema Bereitstellen einer Laravel-App mit Docker Compose auf Nginx.
Weitere Ressourcen zur Nutzung von Docker finden Sie in den folgenden Tutorials:
- So installieren und konfigurieren Sie Docker Compose auf Ubuntu 20.04
- So teilen Sie Daten zwischen einem Docker-Container und einem Host
- Installieren und Einrichten von Docker auf CentOS 7
Fröhliches Computing!











Kommentare
Noch keine Kommentare. Schreiben Sie den ersten.