Offizielles Tutorial zum systematischen Erlernen der japanischen Übersetzung von Docker

Über diesen Artikel

** Übersetzt von ** getting-started : https://github.com/docker/getting-started/tree/6190776cb618b1eb3cfb21e207eefde511d13449

Lizenz: Apache License 2.0

Docker-Desktop

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_01.png

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.

Lass uns beginnen mit

Über den Befehl, den Sie gerade ausgeführt haben

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.

** 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

Docker-Dashboard

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.

tutorial-in-dashboard.png

Was ist ein Container?

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.

Was ist ein Containerbild?

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".

Einführung von Apps zur Verwendung

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.

todo-list-sample.png

Hol dir die App

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.

  1. Öffnen Sie nach [ZIP-Datei herunterladen](http: //localhost/assets/app.zip) die ZIP-Datei und entpacken Sie sie.

  2. Ö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.

ide-screenshot.png

Erstellen Sie ein Container-Image für Ihre App

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.

  1. Erstellen Sie eine Docker-Datei mit den folgenden Inhalten in dem Verzeichnis, das "package.json" enthält.
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.

  1. Wenn nicht, öffnen Sie ein Terminal und wechseln Sie in das Verzeichnis "app", in dem sich die "Dockerfile" befindet. Lassen Sie uns das Container-Image mit dem Befehl 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.

Starten Sie den App-Container

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?)

  1. Starten Sie den Container mit dem Befehl 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.

  1. Öffnen Sie nach einigen Sekunden http: // localhost: 3000 in Ihrem Webbrowser. Sie sollten die App sehen.

todo-list-empty.png

  1. Fügen Sie ein oder zwei Elemente hinzu und prüfen Sie, ob sie wie erwartet funktionieren. Sie können die Fertigstellung des Artikels überprüfen oder den Artikel löschen. Das Frontend hat den Artikel im Backend gespeichert. Es ist sehr einfach, oder?

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.)

dashboard-two-containers.png

einpacken

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.

Aktualisiere die App

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.

Aktualisieren Sie den Quellcode

  1. Schreiben Sie die Zeile 56 von 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>
  1. Erstellen Sie das aktualisierte Image mit demselben Befehl, den Sie zuvor verwendet haben.
docker build -t getting-started .
  1. Starten Sie einen neuen Container mit dem aktualisierten Code.
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.

Ersetzen Sie den alten Behälter

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.

Löschen Sie den Container mit der CLI

  1. Verwenden Sie den Befehl docker ps, um die ID des Containers abzurufen.
docker ps
  1. Verwenden Sie den Befehl "Docker Stop", um den Container zu stoppen.
# <the-container-id>Ersetzen Sie durch die ID, die Sie mit dem Befehl docker ps erhalten haben.
docker stop <the-container-id>
  1. Nachdem Sie den Container gestoppt haben, löschen Sie ihn mit dem Befehl 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>

Löschen Sie den Container über das Docker-Dashboard

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.

  1. Öffnen Sie das Dashboard und bewegen Sie den Mauszeiger über den Container der App, um die Liste der Aktionen auf der rechten Seite anzuzeigen.

  2. Klicken Sie auf die Schaltfläche Papierkorb, um den Container zu löschen.

  3. Bestätigen Sie den Löschvorgang und Sie sind fertig.

dashboard-removing-container.png

Starten Sie die aktualisierte App

  1. Starten Sie die aktualisierte App.
docker run -dp 3000:3000 getting-started
  1. Laden Sie den Browser unter [http: // localhost: 3000](http: // localhost: 3000) neu und Sie sehen den aktualisierten Text.

todo-list-updated-empty-text.png

einpacken

Während ich die App aktualisieren konnte, gab es zwei Dinge zu beachten.

Bevor wir über Beständigkeit sprechen, lernen wir, wie man ein Bild mit anderen teilt.

Teile die App

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.

Repository erstellen

Um ein Image zu pushen, müssen Sie zuerst ein Repository auf Docker Hub erstellen.

  1. Gehen Sie zu Docker Hub (https://hub.docker.com/) und melden Sie sich bei Bedarf an.

  2. Klicken Sie auf die Schaltfläche ** Repository erstellen **.

  3. Geben Sie als Repository-Namen "Erste Schritte" an. Stellen Sie sicher, dass die Veröffentlichungsstufe "Öffentlich" ist.

  4. 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.

push-command.png

Schieben Sie das Bild

  1. Versuchen Sie, den Push-Befehl von Docker Hub in der Befehlszeile auszuführen. Beachten Sie, dass der Befehlsnamespace Ihr eigener sein sollte, nicht "Docker".
$ 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

  1. Melden Sie sich mit dem Befehl docker login -u YOUR-USER-NAME bei Docker Hub an.

  2. 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
  1. Versuchen Sie erneut, den Push-Befehl auszuführen. Ich habe dem Bildnamen keine Tags hinzugefügt. Wenn Sie ihn also aus Docker Hub kopiert und eingefügt haben, entfernen Sie den Teil "Tagname". Wenn Sie kein Tag angeben, verwendet Docker das Tag "latest".
docker push YOUR-USER-NAME/getting-started

Führen Sie das Image auf einer neuen Instanz aus

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.

  1. Öffnen Sie Play with Docker (http://play-with-docker.com/) in Ihrem Browser.

  2. Melden Sie sich mit Ihrem Docker Hub-Konto an.

  3. 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.

pwd-add-new-instance.png

  1. Starten Sie die Push-App auf dem Terminal.
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.

einpacken

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.

Behalten Sie die Datenbank bei

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.

Container-Dateisystem

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.

Schau mal

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.

  1. Gehen wir mit 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.

dashboard-open-cli-ubuntu.png

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.

  1. Starten Sie einen anderen Ubuntu-Container und überprüfen Sie, ob dieselbe Datei vorhanden ist.

docker run -it ubuntu ls /

Es gibt keine data.txt. Es wurde in den Arbeitsbereich für den ersten Container geschrieben.

  1. Löschen Sie den ersten Container mit dem Befehl docker rm -f.

Behältervolumen

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.

Todo-Daten beibehalten

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.

  1. Erstellen Sie ein Volume mit dem Befehl docker volume create.
docker volume create todo-db
  1. 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.

  2. 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
  1. Öffnen Sie nach dem Starten des Containers die App und versuchen Sie, einige Elemente zu Ihrer Aufgabenliste hinzuzufügen.

items-added.png

  1. 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 ", um sie zu löschen.

  2. Starten Sie einen neuen Container mit demselben Befehl wie oben.

  3. 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.

Erfahren Sie mehr über die Lautstärke

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.

einpacken

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.

Verwenden Sie Bind Mount

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.

Volumentyp-Vergleichstabelle

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( -vverwenden) 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

Starten Sie einen Container im Entwicklermodus

Beginnen wir mit einem Container, der in der Entwicklungsphase verwendet werden kann. Mach Folgendes:

Also lasst uns anfangen.

  1. Stellen Sie sicher, dass der bisher verwendete Container "Erste Schritte" nicht gestartet wurde.

  2. 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"
  1. Sie können die Protokolle mit dem Befehl 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.

  1. Nehmen wir nun einige Änderungen an der App vor. Lassen Sie uns die Schaltfläche "Element hinzufügen" in der Datei "src / static / js / app.js" in "Hinzufügen" ändern. Es ist in der Linie 109.
-                         {submitting ? 'Adding...' : 'Add Item'}
+                         {submitting ? 'Adding...' : 'Add'}
  1. Aktualisieren Sie einfach die Seite (oder öffnen Sie sie), und die Änderungen werden fast sofort in Ihrem Browser angezeigt. Der Neustart des Knotenservers dauert einige Sekunden. Wenn Sie also eine Fehlermeldung erhalten, versuchen Sie, nach einigen Sekunden eine Aktualisierung durchzuführen.

updated-add-button.png

  1. Versuchen Sie, andere Änderungen vorzunehmen. Sobald dies erledigt ist, stoppen Sie den Container und verwenden Sie "Docker Build -t Getting-Start", um ein neues Image zu erstellen.

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.

einpacken

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.

App mit mehreren Containern

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 gibt auch andere Gründe. Also werde ich die App so aktualisieren, dass sie so funktioniert.

multi-app-architecture.png

Netzwerk von Containern

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.

Starten Sie MySQL

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.

  1. Erstellen Sie ein Netzwerk.
docker network create todo-app
  1. Starten Sie den MySQL-Container und stellen Sie eine Verbindung zum Netzwerk her. Außerdem werden einige Umgebungsvariablen definiert, die zum Initialisieren der Datenbank verwendet werden. (Siehe das Kapitel "Umgebungsvariablen" in MySQL Docker Hub-Liste)
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.

  1. Um zu überprüfen, ob die Datenbank ausgeführt wird, stellen Sie eine Verbindung zur Datenbank her und stellen Sie sicher, dass sie verbunden ist.
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.

Stellen Sie eine Verbindung zu MySQL her

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.

  1. Starten Sie einen neuen Container mit dem Bild nicolaka / netshoot. Stellen Sie sicher, dass Sie mit demselben Netzwerk verbunden sind.
docker run -it --network todo-app nicolaka/netshoot
  1. Verwenden Sie den Befehl 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.

Führen Sie Apps aus, die MySQL verwenden

Mit der ToDo-App können Sie einige Umgebungsvariablen festlegen, die die MySQL-Verbindungseinstellungen angeben. Die Einzelheiten sind wie folgt.

** 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.

  1. Geben Sie jede der oben genannten Umgebungsvariablen an, damit der Container eine Verbindung zum Netzwerk Ihrer App herstellen kann.
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"
  1. Wenn Sie sich die Containerprotokolle ansehen (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
  1. Öffnen Sie die App in Ihrem Browser und versuchen Sie, einige Apps zu Ihrer Aufgabenliste hinzuzufügen.

  2. 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.

dashboard-multi-container-app.png

einpacken

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.

Verwenden Sie Docker Compose

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.

Installieren Sie Docker Compose

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 Compose-Datei

  1. Erstellen Sie eine Datei mit dem Namen "docker-compose.yml" im Stammverzeichnis des Projekts Ihrer App.

  2. 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
  1. Definieren Sie als Nächstes eine Liste der Dienste (oder Container), die Sie als Teil Ihrer App ausführen möchten.
version: "3.7"

services:

Als nächstes verschieben wir den Dienst in eine Compose-Datei.

Definieren Sie den Dienst der App

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"
  1. Definieren Sie zunächst den Serviceeintrag und das Image für den Container. Sie können einen beliebigen Dienstnamen auswählen. Der Name wird automatisch als Netzwerkalias verwendet, um die Definition von MySQL-Diensten zu vereinfachen.
version: "3.7"

services:
  app:
    image: node:12-alpine
  1. Im Allgemeinen werden Befehle in der Nähe der Definition von "Bild" geschrieben, jedoch in beliebiger Reihenfolge. Nun schreiben wir in die Datei.
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
  1. Verschieben wir den Teil "-p 3000: 3000" des Befehls nach "ports". Hier wird Kurzes Schreiben verwendet, es ist jedoch redundant und [Langes Schreiben](https: // docs. Sie können auch docker.com/compose/compose-file/#long-syntax-1) verwenden.
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
  1. Migrieren Sie als Nächstes das Arbeitsverzeichnis (-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
  1. Migrieren Sie abschließend die Umgebungsvariablen mit dem Schlüssel "Umgebungs".
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 Sie einen MySQL-Dienst

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
  1. Definieren Sie zunächst einen neuen Dienst, nennen Sie ihn "mysql", und der Netzwerkalias wird automatisch abgerufen. Geben Sie das zu verwendende Bild an.
version: "3.7"

services:
  app:
    # The app service definition
  mysql:
    image: mysql:5.7
  1. Geben Sie als Nächstes die Datenträgerzuordnung an. Ein benanntes Volume wurde automatisch erstellt, als Sie den Container mit "Docker Run" starteten. Es wird jedoch nicht erstellt, wenn es mit Compose gestartet wird. Definieren Sie das Volume mit 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:
  1. Geben Sie abschließend die Umgebungsvariablen an.
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:

Starten Sie den Anwendungsstapel

Nachdem Sie "docker-compose.yml" haben, müssen Sie es nur noch starten.

  1. Stellen Sie zunächst sicher, dass keine andere Kopie von app / db ausgeführt wird. (Verwenden Sie "Docker ps" und "Docker rm -f ".)

  2. 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 in mysql: latest geschrieben wurde.

docker volume rm app_todo-mysql-data
  1. Sehen Sie sich die Protokolle mit dem Befehl 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.

  1. Öffnen Sie die App und Sie sollten sehen, dass sie ausgeführt wird. Und Sie können es mit einem Befehl stoppen.

Überprüfen Sie den Anwendungsstapel im Docker-Dashboard

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.

dashboard-app-project-collapsed.png

Wenn Sie die App-Dropdown-Liste öffnen, werden die beiden in der Erstellungsdatei definierten Container angezeigt. Der Name lautet " _ _ ". Dank dessen ist es leicht zu verstehen, welcher Container welche App und welcher Container die MySQL-Datenbank ist.

dashboard-app-project-expanded.png

Stoppen Sie alle

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?

einpacken

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.

Best Practices für die Imagebildung

Bildebene

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.

  1. Sehen Sie sich die Ebenen des Bilds "Erste Schritte" an, das Sie zuvor in diesem Lernprogramm mit dem Befehl "Docker-Bildverlauf" erstellt haben.
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.

  1. Haben Sie bemerkt, dass einige Zeilen weggelassen wurden? Sie können die vollständige Ausgabe erhalten, indem Sie das Flag "--no-trunc" hinzufügen. (Es ist interessant, eine nicht abgekürzte Ausgabe mit ausgelassenen Flags zu erhalten, nicht wahr?)
docker image history --no-trunc getting-started

Ebenen-Cache

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?

  1. Aktualisieren Sie die Docker-Datei so, dass zuerst die Datei "package.json" kopiert wird, die Abhängigkeiten installiert werden und dann die anderen Dateien kopiert werden.
FROM node:12-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
  1. Erstellen Sie eine Datei mit dem Namen ".dockerignore" im selben Ordner wie die Docker-Datei und schreiben Sie den folgenden Inhalt.
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 /).

  1. Erstellen Sie ein neues Image mit "Docker Build".
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.

  1. Bearbeiten Sie die Datei "src / static / index.html" (ändern Sie den Inhalt von "" in "The Awesome Todo App").</p> </li> <li> <p>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:</p> </li> </ol> <pre><code>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 </code></pre> <p>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.</p> <h4>Mehrstufiger Aufbau</h4> <p>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:</p> <ul> <li> <p>Sie können Laufzeitabhängigkeiten trennen und Zeitabhängigkeiten erstellen.</p> </li> <li> <p>Reduzieren Sie die Gesamtgröße des Bildes, indem Sie nur das arrangieren, was für den Start der App erforderlich ist.</p> </li> </ul> <h5>Beispiele für Maven und Tomcat</h5> <p>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.</p> <pre><code class="language-dockerfile">FROM maven AS build WORKDIR /app COPY . . RUN mvn package FROM tomcat COPY --from=build /app/target/file.war /usr/local/tomcat/webapps </code></pre> <p>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").</p> <h5>Beispiel reagieren</h5> <p>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.</p> <pre><code class="language-dockerfile">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 </code></pre> <p>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?</p> <h4>einpacken</h4> <p>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.</p> <h3>Was macht man als nächstes</h3> <p>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.</p> <h4>Container-Orchestrierung</h4> <p>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.</p> <p>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.</p> <h4>Cloud Native Computing-Infrastrukturprojekt</h4> <p>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 <a href="https://www.cncf.io/projects/">erstellte Projekt hier</a> und das gesamte <a href="https://landscape.cncf.io/">CNCF-Diagramm</a> hier sehen. Ich werde. Viele dieser Projekte helfen Ihnen bei der Lösung von Problemen wie Überwachung, Protokollierung, Sicherheit, Image-Registrierung und Messaging.</p> <p>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.</p> <!-- ENDDDDDDDDDDDDDDDDDDDDDDDDDDDDD --> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- ng_ads_new_ui --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-6575041992772322" data-ad-slot="8191531813" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <div style="margin-top: 30px;"> <div class="link-top" style="margin-top: 1px;"></div> <p> <font size="4">Recommended Posts</font> <!-- BEGIN LINK ************************* --> <div style="margin-top: 10px;"> <a href="/de/5778e0d9e9c04038903c">Offizielles Tutorial zum systematischen Erlernen der japanischen Übersetzung von Docker</a> </div> <div style="margin-top: 10px;"> <a href="/de/f7b8ffe43a3904a52946">[Einführung in Docker] Offizielles Tutorial (japanische Übersetzung)</a> </div> <div style="margin-top: 10px;"> <a href="/de/6ec3d9f7c9422e279b9a">Docker Gradle Quick Reference Japanische Übersetzung</a> </div> <div style="margin-top: 10px;"> <a href="/de/d53cbe018233c3c1430a">Docker Desktop WSL 2 Backend Japanische Übersetzung</a> </div> <div style="margin-top: 10px;"> <a href="/de/03b605bc998f684c9905">Docker-Tutorial (Memo)</a> </div> <div style="margin-top: 10px;"> <a href="/de/5aeefc6b68ff07748e4b">settings.gradle Japanische Übersetzung</a> </div> <div style="margin-top: 10px;"> <a href="/de/5afd2ead3a2bd744ae26">Gradle japanische Übersetzung</a> </div> <div style="margin-top: 10px;"> <a href="/de/8c470f21c8ff8770396e">build.gradle Japanische Übersetzung</a> </div> <div style="margin-top: 10px;"> <a href="/de/4dccb102f4e0688e0922">Führen Sie auf, wie Sie in AWS von Docker zu AKS lernen können</a> </div> <!-- END LINK ************************* --> </p> </div> </div> </div> <div class="footer text-center" style="margin-top: 40px;"> <!-- <p> Licensed under cc by-sa 3.0 with attribution required. </p> --> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/highlight.min.js"></script> <!-- ads --> <script data-ad-client="ca-pub-6575041992772322" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- end ads --> </body> </html><script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>