Dieser Artikel ist eine japanische Übersetzung des Docker Desktop-Tutorials.
Dies ist ein offizielles Tutorial, damit Sie sicher und effizient lernen können.
Es deckt alles ab, von Docker Desktop über Docker Hub bis hin zu Docker Compose. Daher ist es ideal für Anfänger, um mit Docker zu beginnen, und für Fortgeschrittene, um auf die Grundlagen zurückzublicken.
Das ursprüngliche Tutorial ist ab dem ** 2020/11/19 ** aktuell. Bitte beachten Sie, dass die Informationen möglicherweise veraltet sind, wenn eine lange Zeit vergangen ist.
Teile, die den Leser nicht irreführen, werden entsprechend übersetzt, wobei der Schwerpunkt auf der Lesbarkeit liegt.
Wir haben mit DeepL usw. gearbeitet, aber wenn es Fehler oder bessere Ausdrücke gibt, stellen Sie bitte eine Bearbeitungsanfrage.
** Übersetzt von ** getting-started : https://github.com/docker/getting-started/tree/6190776cb618b1eb3cfb21e207eefde511d13449
Lizenz: Apache License 2.0
Docker Desktop ist ein Tool zum Erstellen und Freigeben von containerisierten Anwendungen und Microservices. Funktioniert unter Mac OS und Windows.
** Memo für japanische Übersetzer **
Um den Docker-Desktop zu installieren, gehen Sie zu hier und laden Sie ihn herunter, oder führen Sie den folgenden Befehl aus, um ihn von Homebrew Cask zu installieren. ..
$ brew cask install docker
Öffnen Sie den Docker-Desktop, um das Lernprogramm zu starten. Jeder Befehl usw. wird in der zweiten Hälfte ausführlich erläutert. Erfahren Sie daher, wie der Container hier erstellt wird.
Clone
Klonen Sie zunächst das Repository.
Das Getting Started-Projekt ist ein einfaches Github-Repository, das alles enthält, was Sie zum Erstellen und Ausführen eines Images als Container benötigen.
$ git clone https://github.com/docker/getting-started.git
Build
Erstellen Sie als Nächstes ein Bild.
Ein Docker-Image ist ein privates Dateisystem für Container. Es enthält alle Dateien und den Code, die der Container benötigt.
$ cd getting-started
$ docker build -t docker101tutorial .
Run
Lassen Sie uns den Container laufen.
Starten Sie einen Container basierend auf dem im vorherigen Schritt erstellten Image. Wenn Sie den Container starten, können Sie die Anwendung mit Ressourcen starten, die sicher vom Rest Ihres PCs isoliert sind.
$ docker run -d -p 80:80 --name docker-tutorial docker101tutorial
Share
Speichern und teilen Sie Ihr Bild.
Durch das Speichern und Freigeben eines Images in Docker Hub können andere Benutzer das Image problemlos auf einen beliebigen Computer herunterladen und starten.
Um Docker Hub verwenden zu können, müssen Sie ein Docker-Konto erstellen.
$ docker tag docker101tutorial michinosuke/docker101tutorial
$ docker push michinosuke/docker101tutorial
Docker Tutorial
Wenn Sie auf den im Docker-Desktop-Lernprogramm erstellten Container zugreifen, wird ein detaillierteres Docker-Lernprogramm gestartet.
Greifen wir auf [http: // localhost](http: // localhost) zu.
Ich konnte einen Container für dieses Tutorial einrichten.
Schauen wir uns zunächst den gerade ausgeführten Befehl an. Ich habe es vielleicht vergessen, also werde ich es wieder schreiben.
docker run -d -p 80:80 docker/getting-started
Möglicherweise haben Sie bemerkt, dass einige Flags verwendet werden. Jedes Flag hat die folgenden Bedeutungen.
-d
: Führen Sie den Container im Trennmodus (Hintergrund) aus.
-p
: Ordnet Port 80 des Hosts Port 80 des Containers zu.
Docker / Erste Schritte
: Zu verwendendes Bild
** Bewerbung **
Sie können den gesamten Befehl verkürzen, indem Sie Einzelbuchstaben-Flags kombinieren. Der obige Befehl kann beispielsweise auch wie folgt geschrieben werden:
docker run -dp 80:80 docker/getting-started
Bevor ich mit dem Tutorial fortfahre, werde ich ein Docker-Dashboard vorstellen, das eine Liste der auf dem PC ausgeführten Container anzeigen kann. Mit dem Docker-Dashboard können Sie schnell auf die Protokolle des Containers zugreifen, die Shell in den Container einbinden und den Lebenszyklus des Containers einfach verwalten (Stopps und Löschvorgänge).
Um auf das Dashboard zuzugreifen, rufen Sie Mac (https://docs.docker.com/docker-for-mac/dashboard/) oder Windows (https://docs.docker.com/docker-for-) auf. Befolgen Sie die Schritte in Windows / Dashboard /). Wenn Sie es jetzt öffnen, sollte dieses Tutorial ausgeführt werden. Der Name des Containers (der unten "jolly_bouman" lautet) ist ein zufällig generierter Name. Ich denke, es wird mit einem anderen Namen angezeigt.
Ich habe den Container gestartet, aber was genau ist der Container? Einfach ausgedrückt ist ein Container ein einfacher separater Prozess, der von allen anderen Prozessen auf dem Hostcomputer isoliert ist. Isolation verwendet den Kernel-Namespace und Cgroups, eine Funktion, die unter Linux seit langem verwendet wird. Docker hat daran gearbeitet, diese Funktionen vertraut und benutzerfreundlich zu machen.
Verwenden Sie beim Ausführen des Containers ein isoliertes Dateisystem. Dieses Dateisystem stammt aus dem Container-Image. Das Image enthält das Dateisystem des Containers. Daher müssen alle Abhängigkeiten, Einstellungen, Skripte, Binärdateien usw., die zum Ausführen der Anwendung erforderlich sind, im Image enthalten sein. Das Bild enthält auch Containereinstellungen wie Umgebungsvariablen, Standardbefehle für den Start und andere Metadaten.
Wir werden später mehr über Bildebenen, Best Practices und mehr sprechen.
** Informationen **
Wenn Sie "chroot" kennen, stellen Sie sich den Container als Erweiterung von "chroot" vor. Das Dateisystem wird nur aus dem Image gebracht. Der Behälter hat jedoch eine stärkere Isolationsfunktion als "chroot".
Von hier aus werden wir eine einfache Listenverwaltungs-App verwenden, die auf Node.js ausgeführt wird. Es spielt keine Rolle, ob Sie Node.js nicht kennen. JavaScript-Kenntnisse sind nicht erforderlich.
Nehmen wir an, dass das Entwicklungsteam sehr klein ist und eine einfache App erstellt, um MVP (Minimum Practical Product) anzuzeigen. Sie müssen nicht darüber nachdenken, wie es für große Teams oder mehrere Entwickler funktioniert. Erstellen Sie einfach eine App, um zu zeigen, wie es funktioniert und was Sie tun können.
Bevor Sie die Anwendung ausführen können, müssen Sie den Quellcode der Anwendung auf Ihrem PC speichern. In einem echten Projekt ist es meiner Meinung nach üblich, aus einem Repository zu klonen. In diesem Tutorial haben wir jedoch eine ZIP-Datei erstellt, die die Anwendung enthält. Daher werden wir diese verwenden.
Öffnen Sie nach [ZIP-Datei herunterladen](http: //localhost/assets/app.zip) die ZIP-Datei und entpacken Sie sie.
Öffnen Sie das Projekt nach dem Entpacken in einem beliebigen Editor. Wenn Sie den Editor nicht installiert haben, verwenden Sie den Visual Studio-Code (https://code.visualstudio.com/). Sie sollten package.json
und zwei Unterverzeichnisse ( src
und spec
) sehen.
Verwenden Sie "Dockerfile", um Ihre Anwendung zu erstellen. Dockerfile ist ein textbasiertes Anweisungsskript, mit dem Containerbilder erstellt werden. Wenn Sie jemals eine Docker-Datei erstellt haben, stellen Sie möglicherweise fest, dass die unten stehende Docker-Datei fehlerhaft ist. Wir werden später darüber sprechen.
FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
Überprüfen Sie, ob die Docker-Datei eine Erweiterung wie ".txt" hat. Einige Editoren fügen automatisch eine Erweiterung hinzu, was im nächsten Schritt zu einem Fehler führen kann.
docker build
erstellen.docker build -t getting-started .
Dieser Befehl verwendet eine Docker-Datei, um ein neues Container-Image zu erstellen. Möglicherweise haben Sie bemerkt, dass viele "Ebenen" installiert wurden. Der Grund ist, dass ich den Builder angewiesen habe, mit dem Bild node: 12-alpine
zu beginnen. Das Bild befand sich jedoch nicht auf meinem PC, sodass ich es herunterladen musste.
Nachdem das Bild heruntergeladen wurde, habe ich die Anwendung kopiert und mit "Garn" die Anwendungsabhängigkeiten installiert. Die Anweisung CMD
gibt den Standardbefehl an, der ausgeführt werden soll, wenn der Container von diesem Image aus gestartet wird.
Schließlich markiert das Flag "-t" das Bild. Stellen Sie sich vor, Sie geben dem Bild einen menschenfreundlichen Namen. Wir haben das Bild "Erste Schritte" genannt, damit Sie beim Starten des Containers darauf verweisen können.
Das .
am Ende des Befehls docker build
gibt an, dass Docker im aktuellen Verzeichnis nach dem Dockerfile
sucht.
Nachdem wir das Image haben, führen wir die Anwendung aus. Verwenden Sie dazu den Befehl docker run
. (Erinnerst du dich daran, es einmal benutzt zu haben?)
docker run
und geben Sie den Namen des gerade erstellten Images an.docker run -dp 3000:3000 getting-started
Erinnerst du dich an die -d
und -p
Flags? Ich habe den neuen Container im getrennten Modus (Hintergrundlauf) gestartet und Port 3000 auf dem Host Port 3000 auf dem Container zugeordnet. Wenn Sie keine Portzuordnung durchführen, können Sie nicht auf die Anwendung zugreifen.
Zu diesem Zeitpunkt haben Sie eine Todo-Listenverwaltungs-App mit einigen Elementen. Lassen Sie uns nun lernen, wie Sie Container mit ein paar Änderungen verwalten.
Wenn Sie sich das Docker-Dashboard ansehen, sehen Sie, dass zwei Container ausgeführt werden. (Dieses Tutorial selbst und der gerade gestartete App-Container.)
In diesem Kapitel haben Sie die Grundlagen zum Erstellen eines Container-Images gelernt und eine Docker-Datei dafür erstellt. Nachdem ich das Image erstellt hatte, startete ich den Container und berührte die laufende App.
Als Nächstes lernen wir, wie Sie die App ändern und die laufende App mit einem neuen Image aktualisieren. Unterwegs lernen Sie auch einige nützliche Befehle.
Als kleine Funktionsanforderung bat mich das Produktteam, den "leeren Text" zu ändern, der angezeigt wird, wenn ein Element in der Aufgabenliste nicht vorhanden ist. Ich möchte es wie folgt ändern.
You have no todo items yet! Add one above!
Es ist einfach? Wir werden diese Änderung vornehmen.
src / static / js / app.js
neu, um den neuen Text zu verwenden.- <p className="text-center">No items yet! Add one above!</p>
+ <p className="text-center">You have no todo items yet! Add one above!</p>
docker build -t getting-started .
docker run -dp 3000:3000 getting-started
Ah! Ich glaube, ich habe diesen Fehler bekommen. (ID ist anders)
docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
(bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 0.0.0.0:3000 failed: port is already allocated.
Was ist passiert? Der alte Container lief, daher konnte ich den neuen nicht starten. Der Grund für dieses Problem ist, dass ein bestimmter Port nur von einem Prozess (einschließlich des Containers) auf dem PC abgehört werden kann, auf dem sich der Container befindet, der Container jedoch bereits Port 3000 verwendet hat. Sie müssen den alten Container löschen, um diesen Fehler zu beheben.
Um den Container zu löschen, müssen Sie ihn zuerst stoppen. Einmal gestoppt, können Sie es löschen. Es gibt zwei Möglichkeiten, einen alten Container zu löschen. Bitte wählen Sie die Methode, die Sie mögen.
docker ps
, um die ID des Containers abzurufen.docker ps
# <the-container-id>Ersetzen Sie durch die ID, die Sie mit dem Befehl docker ps erhalten haben.
docker stop <the-container-id>
docker rm
.docker rm <the-container-id>
** Bewerbung **
Sie können einen Container mit einem einzigen Befehl stoppen und löschen, indem Sie dem Befehl
docker rm
das Flag" force "hinzufügen.Beispiel)
docker rm -f <the-container-id>
Sie können einen Container mit nur zwei Klicks löschen, indem Sie das Docker-Dashboard öffnen. Es ist viel einfacher als die Container-ID zu finden und zu löschen.
Öffnen Sie das Dashboard und bewegen Sie den Mauszeiger über den Container der App, um die Liste der Aktionen auf der rechten Seite anzuzeigen.
Klicken Sie auf die Schaltfläche Papierkorb, um den Container zu löschen.
Bestätigen Sie den Löschvorgang und Sie sind fertig.
docker run -dp 3000:3000 getting-started
Während ich die App aktualisieren konnte, gab es zwei Dinge zu beachten.
Alle vorhandenen ToDo-Listen sind verschwunden. Dies ist keine gute App. Ich werde in naher Zukunft darüber sprechen.
Trotz der kleinen Änderungen mussten viele Schritte unternommen werden. Im nächsten Kapitel erfahren Sie, wie Sie Ihren Code aktualisieren können, ohne bei jeder Änderung einen neuen Container neu erstellen und starten zu müssen.
Bevor wir über Beständigkeit sprechen, lernen wir, wie man ein Bild mit anderen teilt.
Nachdem Sie das Bild erstellt haben, können Sie es freigeben. Um ein Docker-Image freizugeben, müssen Sie die Docker-Registrierung verwenden. Die Standardregistrierung ist Docker Hub, und die Bilder, die ich bisher verwendet habe, wurden auch von dort aufgenommen.
Um ein Image zu pushen, müssen Sie zuerst ein Repository auf Docker Hub erstellen.
Gehen Sie zu Docker Hub (https://hub.docker.com/) und melden Sie sich bei Bedarf an.
Klicken Sie auf die Schaltfläche ** Repository erstellen **.
Geben Sie als Repository-Namen "Erste Schritte" an. Stellen Sie sicher, dass die Veröffentlichungsstufe "Öffentlich" ist.
Klicken Sie auf die Schaltfläche ** Erstellen **.
Wenn Sie sich die rechte Seite der Seite ansehen, sehen Sie den Docker-Befehl. Hier ist ein Beispiel für den Befehl, den Sie ausführen müssen, um in dieses Repository zu pushen.
$ docker push docker/getting-started
The push refers to repository [docker.io/docker/getting-started]
An image does not exist locally with the tag: docker/getting-started
Warum ist es gescheitert? Dieser Push-Befehl suchte nach einem Bild mit dem Namen Docker / Erste Schritte, konnte es jedoch nicht finden. Ich kann das Bild nicht finden, indem ich "docker image ls" ausführe. Um dieses Problem zu beheben, müssen die bisher erstellten Bilder mit Tags versehen werden, um ihnen einen anderen Namen zu geben.
** Memo für japanische Übersetzer **
Der Befehl enthält Docker-Images, die genauso funktionieren wie Docker-Image ls. Dies ist auf die Neuorganisation des Docker-Befehls zurückzuführen, und "Docker-Image ls" ist neuer und wird empfohlen. In diesem Tutorial werden wir andere Befehle sehen, die in Zukunft dasselbe Verhalten haben.
Referenz: https://qiita.com/zembutsu/items/6e1ad18f0d548ce6c266
Melden Sie sich mit dem Befehl docker login -u YOUR-USER-NAME
bei Docker Hub an.
Verwenden Sie den Befehl "Docker-Tag", um dem Bild "Erste Schritte" einen neuen Namen zu geben. Ersetzen Sie "IHR BENUTZERNAME" durch Ihre Docker-ID.
docker tag getting-started YOUR-USER-NAME/getting-started
docker push YOUR-USER-NAME/getting-started
Nachdem wir das Image erstellt und in die Registrierung verschoben haben, führen wir dieses Container-Image auf einer neuen Instanz aus. Verwenden Sie dazu Play with Docker.
Öffnen Sie Play with Docker (http://play-with-docker.com/) in Ihrem Browser.
Melden Sie sich mit Ihrem Docker Hub-Konto an.
Klicken Sie nach dem Anmelden in der linken Leiste auf den Link "\ + NEUE INSTANZ HINZUFÜGEN" (wenn Sie ihn nicht sehen, spreizen Sie Ihren Browser ein wenig zur Seite). Nach einigen Sekunden wird in Ihrem Browser ein Terminalfenster angezeigt.
docker run -dp 3000:3000 YOUR-USER-NAME/getting-started
Nachdem das Bild aufgenommen wurde, wird es gestartet.
Sie sehen ein Abzeichen mit der Aufschrift 5.3000 und klicken darauf, um die von Ihnen geänderte App anzuzeigen. Du hast es getan, nicht wahr? Wenn Sie das Abzeichen mit der Aufschrift 3000 nicht sehen, klicken Sie auf die Schaltfläche Port öffnen und geben Sie 3000 ein.
In diesem Kapitel haben Sie gelernt, wie Sie Bilder an die Registrierung senden und freigeben. Dann ging ich in eine neue Instanz und startete das Push-Image. Dies ist in CI-Pipelines üblich. Sobald die Pipeline ein Image erstellt und in die Registrierung überträgt, ist die neueste Version des Images in der Produktion verfügbar.
Nachdem Sie es verstanden haben, kehren wir zum letzten Thema im vorherigen Kapitel zurück. Es gab ein Problem, dass beim Neustart der App alle Elemente in der Aufgabenliste gelöscht wurden. Das ist natürlich keine gute UX (User Experience). Lassen Sie uns also lernen, wie Sie die Daten nach einem Neustart beibehalten.
Wie Sie vielleicht bemerkt haben, wird die ToDo-Liste jedes Mal initialisiert, wenn Sie den Container starten. Warum. Lassen Sie uns etwas tiefer in die Funktionsweise des Containers eintauchen.
Wenn der Container gestartet wird, werden verschiedene Bildebenen für das Dateisystem verwendet. Zusätzlich reserviert jeder Container einen "Arbeitsbereich" zum Erstellen / Aktualisieren / Löschen. Änderungen wirken sich nicht auf einen anderen Container aus, selbst wenn dasselbe Bild verwendet wird.
Um es in Aktion zu sehen, starten wir zwei Container und erstellen für jeden eine Datei. Wenn Sie eine Datei in einem Container erstellen, werden Sie feststellen, dass die Datei im anderen Container nicht gültig ist.
Starten Sie einen "Ubuntu" -Container, der eine "/ data.txt" mit Zufallszahlen von 1.1 bis 10000 erstellt.
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Wenn Sie mit Befehlen vertraut sind, werden Sie feststellen, dass Sie die Bash-Shell starten und zwei Befehle aufrufen (verwenden Sie dazu "&&"). Im ersten Teil schreibe ich eine Zufallszahl in / data.txt
. Der zweite Befehl überwacht lediglich die Datei, um den Container am Laufen zu halten.
exec
in den Container, um zu sehen, was ausgegeben wird. Sie können dies tun, indem Sie das Dashboard öffnen und auf die erste Aktion des laufenden Ubuntu-Bildes klicken.Sie können sehen, dass die Shell im Ubuntu-Container ausgeführt wird. Führen Sie den folgenden Befehl aus, um den Inhalt von / data.txt
anzuzeigen. Schließen Sie anschließend das Terminal erneut.
cat /data.txt
Wenn Sie dasselbe über die Befehlszeile tun möchten, verwenden Sie "docker exec". Nachdem Sie die Container-ID mit "Docker ps" erhalten haben, können Sie den Inhalt der Datei mit dem folgenden Befehl abrufen.
docker exec <container-id> cat /data.txt
Sie sollten eine Zufallszahl sehen.
docker run -it ubuntu ls /
Es gibt keine data.txt
. Es wurde in den Arbeitsbereich für den ersten Container geschrieben.
docker rm -f
.Inzwischen wissen wir, dass der Container zunächst das Image beim Start definiert. Ein Container kann Dateien erstellen, aktualisieren und löschen. Sie gehen jedoch verloren, wenn der Container gelöscht wird und alle Änderungen auf diesen Container beschränkt sind. Mit Volumes können Sie jedoch alle ändern.
Volumes (https://docs.docker.com/storage/volumes/) bieten die Möglichkeit, dass ein bestimmter Dateisystempfad in einem Container eine Verbindung zu einem Hostcomputer herstellt. Wenn ein Verzeichnis im Container bereitgestellt wird, wirkt sich das Ändern dieses Verzeichnisses auch auf den Hostcomputer aus. Wenn Sie dasselbe Verzeichnis auch nach dem Neustart des Containers bereitstellen, wird dieselbe Datei angezeigt.
Es gibt zwei Arten von Volumes. Ich benutze beide, aber lasst uns vorerst ** benanntes Volume ** verwenden.
Die ToDo-App speichert die Daten in der SQLite-Datenbank unter / etc / todos / todo.db
. Machen Sie sich keine Sorgen, wenn Sie SQLite nicht kennen. SQLite ist eine einfache relationale Datenbank, in der alle Ihre Daten in einer Datei gespeichert sind. Dies ist nicht der beste Weg, um mit großen Datenmengen zu arbeiten, aber es funktioniert für kleine Demo-Apps. Wie Sie zu einem anderen Datenbankmodul wechseln, wird später beschrieben.
Da es sich bei der Datenbank um eine einzelne Datei handelt, sollten Sie in der Lage sein, diese Datei auf dem Host beizubehalten, damit sie vom nächsten Container referenziert werden kann, damit Sie dort weitermachen können, wo Sie aufgehört haben. Sie können die Daten dauerhaft machen, indem Sie ein Volume erstellen und eine Verbindung zu dem Verzeichnis herstellen, in dem die Daten gespeichert sind (auch als Mount bezeichnet). Wenn der Container in die Datei "todo.db" schreibt, wird er auf dem Host im Volume gespeichert.
Zum kurzen Berühren verwende ich ** Named Volume **. Stellen Sie sich ein benanntes Volume als Bucket für Ihre Daten vor. Docker reserviert physischen Speicherplatz auf der Festplatte, sodass Sie sich nur den Namen des Volumes merken müssen. Wenn Sie ein Volume verwenden, überprüft Docker, ob Sie die richtigen Daten erhalten.
docker volume create
.docker volume create todo-db
Die ToDo-App, die Sie bereits gestartet haben, wird ohne Verwendung dauerhafter Volumes ausgeführt. Verwenden Sie daher das Dashboard oder den Befehl doker rm -f <id>
, um sie zu stoppen.
Ich starte einen ToDo-App-Container. Fügen Sie das Flag -v hinzu, um die Volume-Verbindung anzugeben. Stellen Sie mit einem benannten Volume eine Verbindung zu / etc / todos
her und erfassen Sie alle Dateien.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Löschen Sie den ToDo-App-Container. Verwenden Sie das Dashboard oder verwenden Sie "Docker ps", um die ID abzurufen, und verwenden Sie dann "Docker rm -f
Starten Sie einen neuen Container mit demselben Befehl wie oben.
Nachdem Sie bestätigt haben, dass die Liste angezeigt wird, löschen Sie den Container und fahren Sie fort.
Jetzt, da Sie verstehen, wie Sie Daten beibehalten können.
** Bewerbung **
Named Volumes und Bind Mounts (dazu später mehr) sind zwei Volumes, die seit der Installation von Docker unterstützt wurden. Es gibt jedoch auch viele Treiber-Plugins, die NFS, SFTP, NetApp usw. unterstützen. tun. Dies ist sehr wichtig, wenn Container auf mehreren Hosts in einer Clusterumgebung wie Swarm oder Kubernetes gestartet werden.
Viele Leute fragen oft: "Wo ist der tatsächliche Ort, an dem Docker Daten speichert, wenn benannte Volumes verwendet werden?" Wenn Sie wissen möchten, können Sie den Befehl "Docker Volume Inspect" verwenden.
docker volume inspect todo-db
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Der "Mountpoint" ist der tatsächliche Ort, an dem die Daten auf der Festplatte gespeichert werden. Beachten Sie, dass die meisten Computer Root-Berechtigungen benötigen, um vom Host aus auf dieses Verzeichnis zuzugreifen.
** Zugriff auf Volumendaten direkt auf dem Docker-Desktop **
Während der Ausführung auf dem Docker-Desktop werden die Docker-Befehle tatsächlich in einer kleinen virtuellen Maschine auf der Maschine ausgeführt. Wenn Sie den tatsächlichen Inhalt des Mountpoint-Verzeichnisses anzeigen möchten, müssen Sie zunächst die virtuelle Maschine aufrufen.
Zu diesem Zeitpunkt konnte ich eine funktionierende Anwendung erstellen, die lebend neu gestartet werden konnte. Wir hoffen, dass die Anleger unsere Vision zeigen und verstehen können.
Es dauert jedoch etwas zu lange, um das Image bei jeder Änderung neu zu erstellen. Es gibt einen besseren Weg, um Änderungen vorzunehmen. Das Bind-Mount (das, auf das ich zuvor hingewiesen habe) ist die Methode. Lass uns einen Blick darauf werfen.
Im vorherigen Kapitel haben wir benannte Volumes verwendet, um die Datenbank beizubehalten. Benannte Volumes sind nützlich, wenn Sie nur Ihre Daten speichern möchten, da Sie sich keine Gedanken darüber machen müssen, wo Sie Ihre Daten speichern.
Mit ** Bind Mount ** können Sie den genauen Mountpoint auf Ihrem Host steuern. Es kann auch für die Datenpersistenz verwendet werden, wird jedoch häufig verwendet, um dem Container zusätzliche Daten bereitzustellen. Bei der Entwicklung einer App können Sie den Quellcode mit einem Container mit einem Bind-Mount verbinden, um die Änderungen sofort zu ändern, darauf zu reagieren oder zu sehen.
Für mit Node erstellte Apps ist nodemon der beste Weg, um Dateiänderungen zu überwachen und die Anwendung neu zu starten. Ähnliche Tools gibt es in den meisten Sprachen und Frameworks.
Bindungs-Mounts und benannte Volumes sind die beiden Haupt-Volume-Typen der Docker-Engine. Andererseits sind zusätzliche Volume-Treiber in anderen Anwendungsfällen verfügbar (SFTP, Ceph / Erste Schritte mit dem Docker-rbd-Volume-Plugin /), NetApp, S3 (/ elementar / docker-s3-volume) usw.).
Named Volumes | Binden Sie die Halterung | |
---|---|---|
Host-Standort | Docker wählt | ich wähle |
Beispiel montieren( -v verwenden) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
Erstellen Sie ein neues Volume mit dem Inhalt des Containers | Yes | No |
Unterstützung für Volume-Treiber | Yes | No |
Beginnen wir mit einem Container, der in der Entwicklungsphase verwendet werden kann. Mach Folgendes:
Also lasst uns anfangen.
Stellen Sie sicher, dass der bisher verwendete Container "Erste Schritte" nicht gestartet wurde.
Führen Sie den folgenden Befehl aus. Ich werde auch erklären, was Sie tun.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "yarn install && yarn run dev"
Wenn Sie PowerShell verwenden, verwenden Sie den folgenden Befehl.
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
node:12-alpine `
sh -c "yarn install && yarn run dev"
-dp 3000: 3000
: Wie zuvor. Starten Sie im getrennten (Hintergrund-) Modus und erstellen Sie eine Portzuordnung.
-w / app
: Geben Sie das" Arbeitsverzeichnis "oder das aktuelle Verzeichnis an, in dem der Befehl ausgeführt wird.
-v" $ (pwd): / app "
: Binden Sie vom Container-Host aus das aktuelle Verzeichnis an das Verzeichnis / app
.
node: 12-alpine
: Das zu verwendende Bild. Bitte beachten Sie, dass dieses Image das Basis-Image der App ist, wie in der Docker-Datei angegeben.
sh -c" Garn installieren && Garn ausführen dev "
: Befehl. Ich benutze sh
(alpine hat bash
nicht), um die Shell zu starten, installiere alle Abhängigkeiten mit yarn install
und starte dann yarn run dev
. Wenn Sie sich "package.json" ansehen, können Sie sehen, dass das "dev" -Skript "nodemon" startet.
docker logs -f <container-id>
anzeigen. Wenn Sie sich das ansehen, wissen Sie, dass Sie bereit sind.docker logs -f <container-id>
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000
Wenn Sie das Protokoll angezeigt haben, können Sie mit "Strg" + "C" beenden.
- {submitting ? 'Adding...' : 'Add Item'}
+ {submitting ? 'Adding...' : 'Add'}
Die Verwendung von Bind-Mounts ist in der lokalen Entwicklung sehr verbreitet. Der Vorteil ist, dass auf der Entwicklungsmaschine keine Build-Tools oder Umgebungen installiert sein müssen. Mit nur dem Befehl "Docker Run" wird die Entwicklungsumgebung abgerufen und ist bereit. Wir werden in einem späteren Kapitel über Docker Compose sprechen, das Befehle mit vielen Flags vereinfachen kann.
Wir haben die Datenbank persistent gemacht, damit wir schnell auf die Anforderungen und Wünsche von Investoren und Gründern reagieren können. aber bitte warte einen Moment. Tolle Neuigkeiten sind da!
** Ihr Projekt wird in Zukunft entwickelt. ** ** **
Zur Vorbereitung der Kommerzialisierung muss die Datenbank auf etwas Erweiterbareres als SQLite migriert werden. Einfach ausgedrückt, sollten Sie MySQL mit intakter relationaler Datenbank verwenden. Aber wie bringt man MySQL zum Laufen? Wie erlaube ich die Kommunikation zwischen Containern? Ich werde im nächsten Kapitel darüber sprechen.
Bisher haben wir mit einer Container-App gearbeitet. Aber ich möchte MySQL zu meiner Anwendung hinzufügen. Eine häufig gestellte Frage lautet: "Wo soll ich MySQL ausführen? Soll ich es im selben Container ausführen und separat starten?" Im Allgemeinen sollte jeder Container nur eines tun. Dafür gibt es mehrere Gründe.
Es ist wahrscheinlich, dass die API und das Front-End anders erweitert werden als die Datenbank.
Durch Trennen der Container können Sie die Version separat aktualisieren.
Sie können einen lokalen Datenbankcontainer verwenden, aber in einer Produktionsumgebung möchten Sie möglicherweise einen Dienst verwenden, der die Datenbank verwaltet. In diesem Fall ist es nicht erforderlich, das Datenbankmodul zusammen mit der App in das Produkt aufzunehmen.
Um mehrere Prozesse auszuführen, benötigen Sie einen Prozessmanager (der Container startet nur einen Prozess), was das Starten / Stoppen des Containers erschwert.
Es gibt auch andere Gründe. Also werde ich die App so aktualisieren, dass sie so funktioniert.
Denken Sie daran, dass Container standardmäßig unabhängig voneinander ausgeführt werden und nichts über andere Prozesse oder Container auf demselben Computer wissen. Wie kann ein Container mit anderen Containern kommunizieren? Die Antwort lautet ** Netzwerk **. Sie müssen kein Netzwerktechniker sein. Denken Sie einfach an diese Regel.
Wenn sich zwei Container im selben Netzwerk befinden, können sie miteinander kommunizieren. Die Kommunikation ist nur möglich, wenn Sie sich im selben Netzwerk befinden.
Es gibt zwei Möglichkeiten, einen Container im Netzwerk zu platzieren. Die erste ist die Zuweisungsmethode zu Beginn. Die zweite besteht darin, einen vorhandenen Container zu verbinden. Dieses Mal erstellen wir zuerst das Netzwerk und verbinden dann den gestarteten MySQL-Container.
docker network create todo-app
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
Wenn Sie PowerShell verwenden, verwenden Sie den folgenden Befehl.
docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7
Sie haben das Flag "--network-alias" angegeben. Dies wird später besprochen.
** Informationen für Profis **
Ich habe ein Volume mit dem Namen "todo-mysql-data" verwendet und es auf "/ var / lib / mysql" gemountet, wo die MySQL-Daten gespeichert sind. Ich verwende jedoch nicht den Befehl "Docker Volume Create". Docker erkannte, dass wir ein benanntes Volume verwenden würden, und erstellte das Volume automatisch.
docker exec -it <mysql-container-id> mysql -p
Wenn Sie nach einem Passwort gefragt werden, geben Sie ** secret ** ein. Zeigen Sie in der MySQL-Shell die Datenbankliste an und stellen Sie sicher, dass Sie über die Datenbank "todos" verfügen.
mysql> SHOW DATABASES;
Es sollte so aussehen.
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| todos |
+--------------------+
5 rows in set (0.00 sec)
Sie haben eine "todos" -Datenbank.
Nachdem wir bestätigt haben, dass MySQL gestartet wurde, verwenden wir es tatsächlich. Aber wenn Sie einen anderen Container im selben Netzwerk starten, wie finden Sie den Container? (Denken Sie daran, dass jeder Container eine andere IP-Adresse hat.)
Um dies zu verstehen, verwenden Sie den Container nicolaka / netshoot, der nützliche Tools zur Fehlerbehebung und zum Debuggen von Netzwerkproblemen enthält.
docker run -it --network todo-app nicolaka/netshoot
dig
, ein praktisches DNS-Tool im Container. Suchen Sie die IP-Adresse mit dem Hostnamen "mysql".dig mysql
Sie sollten so etwas sehen:
; <<>> DiG 9.14.1 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;mysql. IN A
;; ANSWER SECTION:
mysql. 600 IN A 172.23.0.2
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Tue Oct 01 23:47:24 UTC 2019
;; MSG SIZE rcvd: 44
Wenn Sie sich "ANTWORT ABSCHNITT" ansehen, können Sie sehen, dass der "A" -Datensatz von "mysql" "172.23.0.2" ist (Ihre IP-Adresse hat wahrscheinlich einen anderen Wert). mysql
ist normalerweise kein gültiger Hostname, aber Docker konnte die IP-Adresse eines Containers mit dem Netzwerkalias mysql
auflösen (denken Sie daran, das Flag --network-alias
zu verwenden). Hast du?).
Dies bedeutet, dass sogar ToDo-Apps mit der Datenbank kommunizieren können, indem sie einfach eine Verbindung zu einem Host namens "mysql" herstellen. Es war noch nie einfacher.
Mit der ToDo-App können Sie einige Umgebungsvariablen festlegen, die die MySQL-Verbindungseinstellungen angeben. Die Einzelheiten sind wie folgt.
MYSQL_HOST
: Der Hostname des laufenden MySQL-Servers.
MYSQL_USER
: Der Benutzername für die Verbindung.
MYSQL_PASSWORD
: Das Passwort für die Verbindung.
MYSQL_DB
: Die Datenbank, die nach dem Verbinden verwendet werden soll.
** Achtung **
Es ist in Ordnung, Umgebungsvariablen zum Konfigurieren von Verbindungen in einer Entwicklungsumgebung zu verwenden, aber die Verwendung in einer Anwendung, die in einer Produktionsumgebung ausgeführt wird, ist eine ** sehr veraltete ** Praxis. Diogo Monica, ehemals für Sicherheit bei Docker verantwortlich, erklärt, warum großartiger Artikel -secret-data /) wird geschrieben.
Ein sicherer Ansatz besteht darin, die geheime Unterstützung des Container-Orchestrierungs-Frameworks zu nutzen. In den meisten Fällen werden diese geheimen Dateien in einem laufenden Container bereitgestellt. Viele Apps (einschließlich MySQL-Images und ToDo-Apps) unterstützen auch Umgebungsvariablen mit dem Suffix "_FILE", die auf Dateien verweisen, die Dateien enthalten.
Wenn Sie beispielsweise die Variable "MYSQL_PASSWORD_FILE" festlegen, verwendet die App den Inhalt der Datei, auf die verwiesen wird, als Verbindungskennwort. Bitte beachten Sie, dass Docker keine dieser Umgebungsvariablen unterstützt. Die App muss wissen, wie man nach Umgebungsvariablen sucht und den Inhalt der Datei abruft.
Nachdem die Erklärung beendet ist, starten wir den Container.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
Wenn Sie PowerShell verwenden, verwenden Sie den folgenden Befehl.
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
--network todo-app `
-e MYSQL_HOST=mysql `
-e MYSQL_USER=root `
-e MYSQL_PASSWORD=secret `
-e MYSQL_DB=todos `
node:12-alpine `
sh -c "yarn install && yarn run dev"
Docker-Protokolle <Container-ID>
), wird eine Meldung angezeigt, dass Sie eine MySQL-Datenbank verwenden.# Previous log messages omitted
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Connected to mysql db at host mysql
Listening on port 3000
Öffnen Sie die App in Ihrem Browser und versuchen Sie, einige Apps zu Ihrer Aufgabenliste hinzuzufügen.
Stellen Sie eine Verbindung zur MySQL-Datenbank her und prüfen Sie, ob das Element geschrieben wurde. Das Passwort ist ** geheim **.
docker exec -ti <mysql-container-id> mysql -p todos
Führen Sie dann in der MySQL-Shell die folgenden Schritte aus:
mysql> select * from todo_items;
+--------------------------------------+--------------------+-----------+
| id | name | completed |
+--------------------------------------+--------------------+-----------+
| c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! | 0 |
| 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome! | 0 |
+--------------------------------------+--------------------+-----------+
Natürlich ist der Inhalt der Tabelle unterschiedlich, da sie Ihre Artikel enthält. Sie können jedoch sehen, dass der Artikel hier gespeichert ist.
Im Docker-Dashboard werden zwei Container ausgeführt. Es gibt jedoch keinen Hinweis darauf, dass sie in einer App zusammengefasst sind. Mal sehen, wie man das verbessert.
Ich konnte eine Anwendung erstellen, die Daten in einer externen Datenbank speichert, die in einem separaten Container ausgeführt wird. Sie haben ein wenig über Containernetzwerke und die Verwendung von DNS zum Erkennen von Diensten gelernt.
Möglicherweise sind Sie jedoch von allem überwältigt, was Sie zum Starten dieser App benötigen. Sie müssen ein Netzwerk erstellen, einen Container starten, alle Umgebungsvariablen angeben, Ports öffnen usw. Sicher ist es zu viel, um sich zu erinnern, und es ist schwierig, es jemandem zu sagen.
Im nächsten Kapitel werden wir über Docker Compose sprechen. Mit Docker Compose können Sie Ihren Anwendungsstapel einfacher freigeben und mit nur einem einfachen Befehl starten.
Docker Compose wurde entwickelt, um das Definieren und Freigeben von Multi-Container-Apps zu vereinfachen. Mit Compose können Sie einen Dienst definieren, indem Sie eine YAML-Datei erstellen und diese mit einem einzigen Befehl starten oder stoppen.
Der große Vorteil von Compose besteht darin, dass Sie einen Anwendungsstapel in einer Datei definieren und im Stammverzeichnis Ihres (versionierten) Projektrepositorys speichern können, sodass jeder problemlos zu Ihrem Projekt beitragen kann. Tatsächlich gibt es viele solcher Projekte auf GitHub und GitLab.
Lass uns zum ersten Mal gehen.
Wenn Sie Docker Desktop / Toolbox auf Ihrem Windows oder Mac installiert haben, ist Docker Compose bereits installiert. Docker Compose ist auch auf der Play-with-Docker-Instanz installiert. Wenn Sie einen Linux-Computer verwenden, müssen Sie Docker Compose gemäß dieser Seite (https://docs.docker.com/compose/install/) installieren.
Nach Abschluss der Installation sollten Sie in der Lage sein, die Versionsinformationen zu überprüfen, indem Sie den folgenden Befehl ausführen.
docker-compose version
Erstellen Sie eine Datei mit dem Namen "docker-compose.yml" im Stammverzeichnis des Projekts Ihrer App.
Definieren Sie in der Compose-Datei zunächst die Schemaversion. In den meisten Fällen ist es besser, die neueste Version zu verwenden. Die neueste Schemaversion und Kompatibilität finden Sie unter Referenz zum Erstellen von Dateien (https://docs.docker.com/compose/compose-file/).
version: 3.7
version: "3.7"
services:
Als nächstes verschieben wir den Dienst in eine Compose-Datei.
Denken Sie daran, hier sind die Befehle, mit denen ich den Container für meine App definiert habe.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
Wenn Sie PowerShell verwenden, habe ich einen Befehl wie den folgenden verwendet:
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
--network todo-app `
-e MYSQL_HOST=mysql `
-e MYSQL_USER=root `
-e MYSQL_PASSWORD=secret `
-e MYSQL_DB=todos `
node:12-alpine `
sh -c "yarn install && yarn run dev"
version: "3.7"
services:
app:
image: node:12-alpine
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
-w / app
) und die Volume-Zuordnung (-v "$ (pwd): / app"
) zu working_dir
und volume
. Volumes werden auch als kurz und lang geschrieben. Es gibt compose-file / # long-syntax-3).Einer der Vorteile von Docker Compose-Volume-Definitionen besteht darin, dass Sie einen Pfad relativ zum aktuellen Verzeichnis verwenden können.
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
Definieren wir nun den MySQL-Dienst. Die für den Container verwendeten Befehle sind:
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
Wenn Sie PowerShell verwenden, verwenden Sie den folgenden Befehl.
docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volume:
auf der obersten Ebene und geben Sie dann den Einhängepunkt für die Dienstkonfiguration an. Wenn Sie nur den Datenträgernamen angeben, werden die Standardoptionen verwendet. Es stehen jedoch viele andere Optionen zur Verfügung (https://docs.docker.com/compose/compose-file/#volume-configuration-reference).version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
volumes:
todo-mysql-data:
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
Die fertige docker-compose.yml
sieht folgendermaßen aus:
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
Nachdem Sie "docker-compose.yml" haben, müssen Sie es nur noch starten.
Stellen Sie zunächst sicher, dass keine andere Kopie von app / db ausgeführt wird. (Verwenden Sie "Docker ps" und "Docker rm -f
Starten Sie den Anwendungsstapel mit dem Befehl docker-compose up
. Fügen Sie das Flag -d
hinzu, um es im Hintergrund auszuführen.
docker-compose up -d
Wenn Sie es ausführen, sollten Sie ungefähr Folgendes sehen:
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1 ... done
Creating app_mysql_1 ... done
Sie können sowohl Volumes als auch Netzwerke erstellen. Standardmäßig erstellt Docker Compose automatisch ein Netzwerk von Anwendungsstapeln (weshalb wir es nicht in der Compose-Datei definiert haben).
** Memo für japanische Übersetzer ** - Wenn der folgende Fehler in "Docker-Compose Up" angezeigt wird
[ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file ./ibdata1 are 0x4800!
Es wurde behoben, indem das Volume mit dem folgenden Befehl gelöscht wurde. Möglicherweise wurde es dadurch verursacht, dass zu Beginn fälschlicherweise
docker-compose.yml
inmysql: latest
geschrieben wurde.docker volume rm app_todo-mysql-data
docker-compose logs -f
an. Sie können sehen, dass die Protokolle für jeden Dienst zu einem zusammengefasst sind. Dies ist sehr nützlich, wenn Sie Zeitprobleme sehen möchten. Das Flag -f folgt dem Protokoll, sodass das generierte Protokoll live ausgegeben wird.Die tatsächliche Ausgabe sieht folgendermaßen aus:
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1 | Version: '5.7.27' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
app_1 | Connected to mysql db at host mysql
app_1 | Listening on port 3000
Der (farbige) Dienstname in der ersten Zeile hilft bei der Identifizierung der Nachricht. Wenn Sie die Protokolle für einen bestimmten Dienst anzeigen möchten, fügen Sie den Dienstnamen am Ende des Protokollbefehls hinzu (z. B. "Docker-Compose-Protokolle -f App").
** Anwendung ** - Warten Sie auf die Datenbank, bevor Sie die App starten
Wenn Sie die Anwendung starten, wird versucht, eine Verbindung herzustellen, nachdem MySQL aktiv und bereit ist. Docker bietet keine integrierte Unterstützung für das Starten eines anderen Containers, nachdem der Container vollständig gestartet, ausgeführt und vorbereitet wurde. Für knotenbasierte Projekte können Sie wait-port verwenden. Ähnliche Projekte existieren in anderen Sprachen und Frameworks.
Im Docker-Dashboard gibt es eine Gruppe mit dem Namen ** app **. Dies ist der Projektname von Docker Compose und wird zum Gruppieren der Container verwendet. Standardmäßig ist der Projektname der Name des Verzeichnisses, in dem sich "docker-compose.yml" befindet.
Wenn Sie die App-Dropdown-Liste öffnen, werden die beiden in der Erstellungsdatei definierten Container angezeigt. Der Name lautet "
Alles, was Sie tun müssen, ist "Docker-Compose Down" auszuführen oder die gesamte App in den Papierkorb des Docker-Dashboards zu werfen. Der Container wird gestoppt und das Netzwerk gelöscht.
** Volume löschen **
Standardmäßig löscht das Ausführen von "Docker-Compose Down" nicht das benannte Volume in der Compose-Datei. Wenn Sie die Volumes löschen möchten, müssen Sie das Flag "--volumes" hinzufügen.
Wenn Sie im Docker-Dashboard den App-Stack löschen, wird das Volume nicht gelöscht.
Wechseln Sie nach dem Stoppen einfach zu einem anderen Projekt und führen Sie "docker-compose up" aus, um dieses Projekt zu entwickeln. Es ist sehr einfach, nicht wahr?
In diesem Kapitel haben Sie mehr über Docker Compose erfahren und erfahren, wie Sie Anwendungen für mehrere Dienste einfacher definieren und freigeben können. Ich habe den von mir verwendeten Befehl in das entsprechende Compose-Format migriert und eine Compose-Datei erstellt.
Das Tutorial ist auch in die Endphase eingetreten. Die Docker-Datei, die ich bisher verwendet habe, hat jedoch ein großes Problem. Daher möchte ich einige der Best Practices zum Erstellen von Bildern behandeln. Lass uns einen Blick darauf werfen.
Wussten Sie, dass Sie die Komponenten eines Bildes sehen können? Sie können den Befehl "Docker-Bildverlauf" verwenden, um den Befehl anzuzeigen, mit dem jede im Bild enthaltene Ebene erstellt wird.
docker image history getting-started
Sie sollten so etwas sehen (wahrscheinlich eine andere ID):
IMAGE CREATED CREATED BY SIZE COMMENT
a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "src/index.j… 0B
f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB
a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB
9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B
b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B
<missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB
<missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B
<missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB
<missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B
<missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
Jede Ebene repräsentiert eine Ebene des Bildes. Auf diesem Bildschirm wird die Basis des Bildes unten und die neueste Ebene oben angezeigt. Auf diese Weise können Sie jede Ebene schnell erkennen und große Bilder finden.
docker image history --no-trunc getting-started
Wir haben tatsächlich die Ebenen gesehen, was eine sehr wichtige Geschichte ist, wenn es darum geht, die Erstellungszeit von Containerbildern zu verkürzen.
Nach dem Schichtwechsel müssen alle nachgeschalteten Schichten regeneriert werden.
Werfen wir einen Blick auf die Docker-Datei, die wir wieder verwendet haben.
FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
Wenn wir zur Ausgabe des Bildverlaufs zurückkehren, können wir sehen, dass jeder Befehl in der Docker-Datei eine neue Bildebene ist. Möglicherweise erinnern Sie sich, dass die Garnabhängigkeiten neu installiert wurden, als Sie Änderungen am Bild vorgenommen haben. Gibt es eine Möglichkeit, dies zu beheben? Es ist lächerlich, bei jedem Erstellen dieselben Abhängigkeiten zu installieren.
Um dies zu beheben, müssen Sie die Docker-Datei neu erstellen, um die Abhängigkeiten zwischenzuspeichern. Für knotenbasierte Anwendungen werden Abhängigkeiten in der Datei "package.json" definiert. Dies bedeutet, dass, wenn Sie zuerst nur diese Datei kopieren, die anderen Dateien nach der Installation der Abhängigkeiten kopiert werden. Garnabhängigkeiten werden also nur neu erstellt, wenn Sie "package.json" ändern. Ist es nicht toll?
FROM node:12-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
node_modules
Mit der Datei ".dockerignore" können Sie nur die Dateien auswählen und kopieren, die Sie für Ihr Bild benötigen. Weitere Informationen finden Sie hier (https://docs.docker.com/engine/reference/builder/#dockerignore-file). In diesem Fall wird der Ordner "node_modules" im zweiten "COPY" ausgeschlossen. Andernfalls wird es mit der vom Befehl RUN
generierten Datei überschrieben. Weitere Informationen dazu, warum diese Methode für Node.js-Anwendungen und andere bewährte Methoden empfohlen wird, finden Sie unter Node Web Apps in Docker (https://nodejs.org/en/docs/guides/). Siehe nodejs-docker-webapp /).
docker build -t getting-started .
Sie sollten so etwas sehen:
Sending build context to Docker daemon 219.1kB
Step 1/6 : FROM node:12-alpine
---> b0dc3a5e5e9e
Step 2/6 : WORKDIR /app
---> Using cache
---> 9577ae713121
Step 3/6 : COPY package.json yarn.lock ./
---> bd5306f49fc8
Step 4/6 : RUN yarn install --production
---> Running in d53a06c9e4c2
yarn install v1.17.3
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 10.89s.
Removing intermediate container d53a06c9e4c2
---> 4e68fbc2d704
Step 5/6 : COPY . .
---> a239a11f68d8
Step 6/6 : CMD ["node", "src/index.js"]
---> Running in 49999f68df8f
Removing intermediate container 49999f68df8f
---> e709c03bc597
Successfully built e709c03bc597
Successfully tagged getting-started:latest
Sie können sehen, dass alle Ebenen neu erstellt wurden. Ich habe eine große Änderung an der Docker-Datei vorgenommen, sodass es kein Problem mehr gibt.
Bearbeiten Sie die Datei "src / static / index.html" (ändern Sie den Inhalt von "
Erstellen Sie das Docker-Image erneut mit "Docker-Build -t Erste Schritte". Dieses Mal sollte sich das, was Sie sehen, etwas ändern und so aussehen:
Sending build context to Docker daemon 219.1kB
Step 1/6 : FROM node:12-alpine
---> b0dc3a5e5e9e
Step 2/6 : WORKDIR /app
---> Using cache
---> 9577ae713121
Step 3/6 : COPY package.json yarn.lock ./
---> Using cache
---> bd5306f49fc8
Step 4/6 : RUN yarn install --production
---> Using cache
---> 4e68fbc2d704
Step 5/6 : COPY . .
---> cccde25a3d9a
Step 6/6 : CMD ["node", "src/index.js"]
---> Running in 2be75662c150
Removing intermediate container 2be75662c150
---> 458e5c6f080c
Successfully built 458e5c6f080c
Successfully tagged getting-started:latest
Sie haben festgestellt, dass der Build sehr schnell ist. Sie können auch sehen, dass die Schritte 1 bis 4 alle "Verwenden von Cashe" enthalten. Sie können jetzt den Build-Cache verwenden. Das Verschieben, Ziehen und Aktualisieren von Bildern ist sehr schnell.
Ich werde in diesem Tutorial nicht zu sehr ins Detail gehen, aber mehrstufige Builds sind ein lächerlich leistungsfähiges Werkzeug, mit dem Sie Bilder in mehreren Stufen erstellen können. Es hat folgende Vorteile:
Sie können Laufzeitabhängigkeiten trennen und Zeitabhängigkeiten erstellen.
Reduzieren Sie die Gesamtgröße des Bildes, indem Sie nur das arrangieren, was für den Start der App erforderlich ist.
Beim Erstellen einer Java-basierten Anwendung benötigen Sie ein JDK, um den Quellcode in Java-Bytecode zu kompilieren. Das JDK wird jedoch in einer Produktionsumgebung nicht benötigt. Sie können auch Tools wie Maven oder Gradle verwenden, um Ihre App zu erstellen. Diese werden auch für das endgültige Bild nicht benötigt. Hier bieten sich mehrstufige Builds an.
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
In diesem Beispiel erstellen wir Java mit Maven in der ersten Phase mit dem Namen "build". Die zweite Stufe, beginnend mit "FROM Tomcat", kopiert die Dateien aus der "Build" -Stufe. Das endgültige Bild ist nur die letzte Stufe, die erstellt wurde (überschrieben mit dem Flag "--target").
Zum Erstellen einer React-Anwendung benötigen Sie eine Knotenumgebung, die JS-Code (normalerweise JSX), SASS-Stylesheets usw. in statisches HTML, JS und CSS kompiliert. Wenn Sie kein serverseitiges Rendering benötigen, benötigen Sie keine Knotenumgebung, um Ihre Produktionsumgebung zu erstellen. Dann müssen Sie nur noch die statischen Ressourcen in einen statischen Nginx-Container legen.
FROM node:12 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
Hier erstellen wir (Maximieren des Ebenen-Cache) das Bild "node: 12" und kopieren dann die Ausgabe in den Nginx-Container. Das ist besser, nicht wahr?
Mit ein wenig Verständnis für die Struktur des Bildes wird das Bild schneller erstellt und Sie können weniger Änderungen vornehmen. Mehrstufige Builds tragen auch zur Verbesserung der Sicherheit des endgültigen Containers bei, indem sie die Gesamtgröße des Images verringern und die Abhängigkeiten von Build-Time und Laufzeit entkoppeln.
Das Tutorial ist beendet, aber es gibt noch mehr über Container zu lernen. Ich werde hier nicht ins Detail gehen, aber schauen wir uns das an.
Das Ausführen eines Containers in einer Produktionsumgebung kann schwierig sein. Ich möchte mich nicht bei der Maschine anmelden und "Docker Run" oder "Docker-Compose Up" ausführen. Warum? Was passiert also, wenn der Container stirbt? Wie skaliere ich über mehrere Maschinen? Die Container-Orchestrierung löst dieses Problem. Tools wie Kubernetes, Swarm, Nomad und ECS lösen dieses Problem auf leicht unterschiedliche Weise.
Die allgemeine Idee ist, einen "Manager" zu haben, der den ** erwarteten Zustand ** erhält. Dieser Status lautet "Ich möchte, dass Sie zwei Webanwendungsinstanzen starten und Port 80 öffnen". Der Manager überwacht alle Maschinen im Cluster und delegiert die Arbeit an die "Arbeiter". Der Manager überwacht Änderungen (z. B. wenn der Container gestoppt wird) und handelt dann so, dass der ** tatsächliche Status ** den erwarteten Status widerspiegelt.
CNCF (Cloud Native Infrastructure Project) ist eine Vielzahl von herstellerunabhängigen Open Source-Projekten, darunter Kubernetes, Prometheus, Envoy, Linkerd, NATS und mehr. Sie können das erstellte Projekt hier und das gesamte CNCF-Diagramm hier sehen. Ich werde. Viele dieser Projekte helfen Ihnen bei der Lösung von Problemen wie Überwachung, Protokollierung, Sicherheit, Image-Registrierung und Messaging.
Wenn Sie sich über den gesamten Container und die Entwicklung einer Cloud-nativen Anwendung nicht sicher sind, verwenden Sie ihn bitte. Treten Sie der Community bei, stellen Sie Fragen und lernen Sie. Wir freuen uns auf deine Beteiligung.
Recommended Posts