Grundlagen der Dokerisierung in.NET Core

Grundlagen der Dokerisierung in.NET Core

Blog post image

Also, wo soll ich anfangen? Die Erfahrung zeigt mir, dass die anfängliche Eintrittsschwelle ziemlich hoch ist, obwohl es sich bei dem jetzigen und dem ehemaligen Hafenarbeiter um völlig unterschiedliche Tiere handelt.

Ich wurde durch ein Gespräch, das in der Firma mitgehört wurde, zu diesem Artikel inspiriert. Es ging um die Erstellung von Docker-Images und wurde mit der Aussage „Das ist unglaublich schwierig!“ dargelegt. Ich stimme dieser Schlussfolgerung nicht ganz zu. Meiner Meinung nach reicht es aus, die absoluten Grundlagen der verwendeten Technologie zu kennen und mit einem bestimmten Betriebssystem zu arbeiten, und es wird keine unüberwindbaren Hindernisse auf unserem Weg geben. Aber das ist meine Meinung, und Sie haben keinen Grund, mir zu glauben, oder? Zu Beginn meines Abenteuers mit dem Docker habe ich auch die Tutorials im Internet gelesen, dabei große Augen gemacht und mich gefragt „Auf was lasse ich mich da ein?!“

Also lass uns ein bisschen herumspielen — du wirst sehen, dass der gezähmte Docker nicht (zu oft) beißt.

Was ist der Plan? Wir werden kurz auf die Grundlagen der Arbeit mit Docker eingehen, um einen einheitlichen Überblick über die auftretenden Begriffe zu erhalten. Dann platzieren wir unsere eigene Anwendung in einem Container, versorgen sie mit allem, was sie benötigt, und am Ende werden wir völlig wild werden, zuerst lächerlich komplizieren und dann unser gesamtes Testsystem containerisieren.

Hinweis: Unser Image wird eine Anwendung enthalten, die in der.NET Core-Technologie integriert ist. Wenn Sie jedoch nicht mit einem Onkel aus Redmond unterwegs sind, laufen Sie noch nicht weg! Die folgenden Anweisungen können problemlos an eine ganze Reihe anderer Technologien angepasst werden, sofern Sie Ihre Anwendung mit dem Terminal kompilieren können.

Noch ein kurzer Exkurs, bevor wir zu den Vorzügen kommen. Lassen Sie uns eine Frage beantworten — warum? Das ist meine App, ich habe eine tolle IDE dafür, die sogar Kaffee brüht. Warum sollte ich mich für Dockerisierung interessieren? Abgesehen von der Idee, Docker in der Produktion einzusetzen (ich werde hier nichts vorschlagen, Sie müssen selbst entscheiden, ob das in Ihrem Projekt eine gute Idee ist), sind Anwendungen selten einsame Inseln. Informationssysteme bestehen oft aus Dutzenden oder sogar Hunderten kleinerer Würfel, die ein (wackeliges) Ganzes bilden. Einige von ihnen werden in einer Sprache verfasst sein, die wir nicht kennen, und manchmal haben wir noch nicht einmal von ihr gehört. Was muss ich installieren und welche Befehle muss ich verwenden, um es auszuführen? Und wenn — zu meinem Entsetzen — etwas nicht funktioniert, wo kann man nach Hilfe suchen? Thread auf Stack Overflow? Rituelles Ziegenopfer aus Kastanien? Wer auch immer es gesehen hat, wer weiß...

Abb. 1. Beispiel Ziege für rituelle Opfer

Diese Programme wurden jedoch von einigen Programmierern entwickelt, die vielleicht immer noch mit uns zusammenarbeiten oder vielleicht nur in Erinnerungen und Legenden leben. Es kann sogar davon ausgegangen werden, dass diese Entwickler in der Lage waren, eine bestimmte Anwendung auszuführen und sie davon zu überzeugen, ihre Arbeit zu erledigen. Wenn sie nur klare Betriebsanweisungen hinterlassen würden... Oder wenn es die Möglichkeit gäbe, die Anwendung lokal so auszuführen, dass sie vollständig mit ihrem Betrieb in der Produktion kompatibel ist... Und nein, warte mal, dafür ist Docker nützlich!
Wiederholbarkeit, Standardisierung, Einfachheit. Und natürlich ein bisschen mehr Mühe, ja für die Balance ;-)

Sprechen Sie über den Docker

Im Titel steht das Wort „Dockerisierung“ — eine Ableitung des Namens Docker. Ein umfassenderes Äquivalent zu diesem Konzept ist Containerisierung, allerdings sind diese Wörter tatsächlich zu Synonymen geworden. Docker ist einfach die beliebteste Methode zur Containerisierung, obwohl es natürlich auch andere Anbieter dieser Art von Diensten gibt (zum Beispiel Tabletts).

Docker hilft beim Platzieren von Anwendungen in einem Container. Aber was genau ist dieser ganze Container? Docker selbst definiert einen Container als:

Ein Container ist eine Standardeinheit von Software, die Code und all seine Abhängigkeiten so verpackt, dass die Anwendung schnell und zuverlässig von einer Computerumgebung zur anderen ausgeführt wird.

Nun, das heißt, wir gewinnen an Geschwindigkeit und Zuverlässigkeit, wenn wir Anwendungen in verschiedenen Umgebungen ausführen. Hast du jemals jemanden mit den Worten „Es funktioniert für mich“ ausgelacht? Nun, leider wirst du es nicht mehr so vermasseln können.

Abbildung 2. Quelle: Reddit

Wir lesen weiter:

Ein Docker-Container-Image ist ein leichtes, eigenständiges, ausführbares Softwarepaket, das alles enthält, was zum Ausführen einer Anwendung benötigt wird: Code, Laufzeit, Systemtools, Systembibliotheken und Einstellungen.

Ich habe alle Spielzeuge mitgebracht, nicht nur die App, sondern auch die gesamte Laufzeit, sodass ich völlig unabhängig bin! Moment, es ist nicht dasselbe wie eine virtuelle Maschine? Nicht genau — eine virtuelle Maschine enthält ein Betriebssystem, das darauf ausgeführt wird. Container haben kein System — stattdessen verwenden sie den Kernel des Hostsystems. Deshalb sind sie leicht und schnell — sie enthalten nur das, was für eine bestimmte Anwendung benötigt wird.

Übrigens wurden hier zwei Begriffe reingeschmuggelt — Container und Image — also denke ich, es wäre gut herauszufinden, was sie bedeuten:

  • Ein Container ist ein lebender Organismus, den wir ausführen können und der einige Aufgaben erfüllt. Letztlich wird die Anwendung direkt im Container ausgeführt.
  • Ein Bild ist ein Datensatz, mit dem Sie einen Container erstellen können. Das Bild selbst kann nicht gestartet werden.

Die beste Analogie, die hier angewendet werden kann (geliehen, ich bin nicht der Autor und kann mich leider nicht an die Quelle erinnern), ist Klasse und Objekt. Das Bild ist wie eine Klasse — es beschreibt, was der Container tun wird, ohne in irgendeiner Weise ausführbar zu sein. Der Container ist wie eine Instanz einer bestimmten Klasse, die funktioniert und einsatzbereit ist.

Dies ist fast das Ende der trockenen Theorie, aber lassen Sie uns auch die Beziehung des Containers zum Betriebssystem erwähnen. Zusätzlich zu dem, was wir im Image mitgebracht haben, benötigt die Anwendung drei weitere Dinge, um glücklich zu sein: ein Dateisystem (weil es irgendwo leben muss), einen Prozessbaum (weil es irgendwo beginnen muss) und eine Netzwerkkonfiguration (weil es mit der Welt in Kontakt sein muss). Alle drei werden per Docker-Engine direkt vom Host-Betriebssystem geliefert. Jeder Container hat sein eigenes Dateisystem, seinen eigenen Prozessbaum und seine eigene Adressierung, die sowohl vom Host als auch von parallelen Containern vollständig isoliert sind.

Nun, da wir das alles wissen, machen wir uns an die Arbeit.

Aber wie? Lass uns containerisieren!

Zuallererst benötigen wir eine App. Da dies ein absolut zweitrangiges Thema ist, werden wir das einfach tun

λ > dotnet new webapp -o aspnetcoreapp

Wir werden eine einfache Anwendung namens aspnetcoreapp bekommen. Wir werden später darauf zurückkommen, aber das reicht uns jetzt.
Um Docker-Images zu erstellen, benötigen wir Docker (duh!) und eine spezielle Datei namens Docker-Datei (Aufzeichnungen). Es beschreibt, wie man ein Image erstellt, welches Betriebssystem verwendet werden muss, wo man unsere Anwendung bekommt usw. Es ist einfach ein Skript, das alles in eine Box packt, die als Image bezeichnet wird. Das erste, was wir brauchen, ist ein Quell-Image — ja, genauso wie Klassen voneinander erben, bauen Bilder auch auf anderen Images auf. Das machen wir mit dem Befehl VON

1 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build

Da wir in einer Dotnet-Umgebung arbeiten, verwenden wir Images, die das.NET Core 3.1-SDK enthalten. Dort finden wir alle Bibliotheken und Abhängigkeiten, die von.NET Core verwendet werden, sodass wir sie nicht selbst hinzufügen müssen. Diese Bilder werden von Microsoft verwaltet und sind daher im Allgemeinen auf dem neuesten Stand. Ein Wort der Warnung — Microsoft spielt manchmal ohne ersichtlichen Grund gerne bei der Benennung von Bildern herum. Wenn Sie dies lesen, ist die Benennung von Bildern möglicherweise veraltet. Die neuesten Bilder finden Sie immer auf Docker-Hub.

Hinweis: Wenn du überhaupt kein Dotnet bist, hast du dich hier gerade aus dem Internet verheddert — hab keine Angst! DockerHub enthält Bilder für wahrscheinlich jede mögliche Technologie, nur einen Moment Suche

2 | WORKDIR /app
3 |
4 | COPY aspnetcoreapp/aspnetcoreapp.csproj ./
5 | RUN dotnet restore

Wir arbeiten weiter! Mit dem Befehl ARBEITSVERZEICHNIS wir setzen das aktuelle Arbeitsverzeichnis (ARBEITSVERZEICHNIS erstellt ein Verzeichnis (falls es es nicht findet) innerhalb des zu erstellenden Images. Mit dem Befehl COPY kopieren wir unsere Projektdatei in das Image. Danach laden wir alle erforderlichen Abhängigkeiten herunter.
Noch ein Wort zum Kopieren — wir kopieren die Datei aus dem Build-Kontext (dazu später mehr) in das Innere des Images. Alle Pfade sind also relative Pfade, die ihren Ursprung entweder im Build-Kontext oder in ARBEITSVERZEICHNIS.

Sobald die Abhängigkeiten geklärt sind, müssen wir nur noch alle anderen Dateien herunterladen

7 | COPY . ./

und erstelle eine App

8 | RUN dotnet publish -c Release -p:PublishDir=./output
aspnetcoreapp/aspnetcoreapp.csproj

Damit könnten Sie den Bauprozess tatsächlich beenden. Neugierig, nicht wahr? Wir werden dies jedoch nicht tun, da dies einer der Annahmen der Containerisierung widersprechen würde — dem Mindestpaket, um die Anwendung auszuführen. Unser Image basiert auf dotnet/core/sdk und das muss auch so bleiben — das SDK enthält alle Tools, die zum Erstellen und Debuggen benötigt werden (ja, du kannst im Container debuggen!) Anwendungen. Letztlich werden wir es jedoch für nichts benötigen, schließlich wollen wir nur unser Programm ausführen und keinen Code kompilieren. Verwenden wir also ein minimalistischeres Bild, dotnet/core/aspnet, und ein Prozess namens mehrstufige Konstruktion.

10| FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
11| WORKDIR /app
12|
13| COPY --from=build /app/output .

Wir wechseln mit dem Befehl zu einem anderen Basis-Image VON und wir schaffen ein neues  ARBEITSVERZEICHNIS — diesmal in einem Bild, das auf dotnet/core/aspnet. Dann kopieren wir das Ergebnis des Befehls dotnet veröffentlichen, aber nicht aus dem Build-Kontext, sondern aus der vorherigen Build-Phase! Den Aufmerksameren ist sicherlich aufgefallen, dass wir unser Bild in der ersten Zeile als bezeichnet haben Gebäude „Wir haben es zu diesem Zweck gemacht. Die folgenden Stufen haben Zugriff auf die Daten, die in den vorherigen Stufen enthalten sind.
Jetzt müssen Sie nur noch mit dem Finger darauf zeigen, was der erstellte Container tun soll (PID 1). Der Befehl wird dafür verwendet EINSTIEGSPUNKT.

17| ENTRYPOINT ["dotnet", "aspnetcoreapp.dll"]

Zusätzlich können wir einen Befehl hinzufügen ENTLARVT, um die Benutzer über unser Image zu informieren, dass sie an einem bestimmten Port etwas erwarten können. Dies ist für den Betrieb in keiner Weise erforderlich, da es sich um eine solche Pseudodokumentation handelt.

15| EXPOSE 80

Und schon, nach den Schmerzen! In seiner ganzen Pracht sieht unser Dockerfile so aus:

1 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
2 | WORKDIR /app
3 |
4 | COPY aspnetcoreapp/aspnetcoreapp.csproj ./
5 | RUN dotnet restore
6 |
7 | COPY . ./
8 | RUN dotnet publish -c Release -p:PublishDir=./output aspnetcoreapp/aspnetcoreapp.csproj
9 |
10| FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
11| WORKDIR /app
12|
13| COPY --from=build /app/output .
14|
15| EXPOSE 80
16|
17| ENTRYPOINT ["dotnet", "aspnetcoreapp.dll"]

Mein erstes Bild

Das haben wir schon Docker-Datei mit der Definition unseres Bildes, cool, aber... was nun? Docker-Datei es ist noch kein Bild, um etwas daraus zu machen brauchen wir es noch bauen. Der Befehl wird dafür verwendet

λ > docker build -f Dockerfile -t aspnetcoreimage.

Der Parameter -f gibt den Speicherort der Datei an Docker-Datei und in diesem Fall könnten wir es ganz überspringen, weil das der Standardwert ist. Der Parameter -t gibt den Namen unseres Bildes an als mcr.microsoft.com/dotnet/core/aspnet im Fall unseres Basisimages. Der Punkt am Ende ist überhaupt kein Tippfehler, ha, diesmal nicht! Dieser Punkt ist unser Geheimnis. Kontext erstellen Die, vor denen ich dich schon einmal erschreckt habe.

Der Build-Kontext sind die Daten, die in der Phase der Erstellung an das Image (oder tatsächlich an den Docker-Daemon) übergeben werden. Wir können also nur von Dockerfile aus auf sie zugreifen und sie werden nicht Teil des Ausgabe-Images sein - sofern wir uns nicht anders entscheiden (leer beherrschen KOPIE). Da unser Build-Prozess von der Existenz von Anwendungsquellen ausgeht (stattdessen könnten wir sie beispielsweise von Git herunterladen), müssen wir sie durch den Build-Kontext leiten. Der Punkt hier bezeichnet das Verzeichnis, aus dem wir den Befehl ausgeführt haben Docker-Build — alle darin enthaltenen Dateien und Verzeichnisse können zum Erstellen unseres Images verwendet werden.

Nun, alle ausnahmslos. Ob wir sie brauchen oder nicht. Auch dies spricht für einen minimalistischen Ansatz, schließlich wird jedes unnötige Megabyte den Bauprozess verlangsamen und komplizieren. Zum Glück kann auch etwas dagegen unternommen werden! Was für ein glücklicher Zufall, nicht wahr?

An diesem Punkt betritt eine weitere Datei — .dockerignore — die Szene (alles in weiß...). Für Dockerfile ist es, was .gitignore für Git ist — sie zeigt, worauf man nicht achten sollte. So wie es keinen Sinn macht, alles im Repository zu behalten, wird nicht jede Datei benötigt, um ein Image zu erstellen. Klingt trivial — wie viel Speicherplatz kann man sparen, wenn man bin, out und.git loswird? Bei kleinen Projekten werden die Unterschiede tatsächlich gering sein, aber im Laufe der Zeit wird der Kontext anschwellen und anschwellen, bis sich schließlich herausstellt, dass wir bereits Hunderte von MB an Müll versenden, was alles erheblich verlangsamt. Glauben Sie mir beim Wort. War ich, ich habe es gesehen. Manchmal habe ich immer noch Albträume.

Einen Moment der Pause, ich schreibe dir aus der Zukunft. Buchstäblich ein paar Tage, nachdem ich diese Worte geschrieben hatte, sprach ich mit einem Kollegen, der an einem ernsthaften IT-Projekt arbeitete. Er beklagte, dass die Erstellung von Images seiner App unglaublich langsam geworden war. Schuld daran war der Build-Kontext. Schnallt eure Gürtel an, gleich authentische Logs vor und nach dem Hinzufügen einer einfachen.dockerignore-Datei:

Sending build context to Docker daemon 825MB
Sending build context to Docker daemon 2.676MB

Wir sind ein wenig vom Thema abgewichen — wir haben unser Image aufgebaut. Schauen wir uns an, was auch nach der Ausführung des Docker-Build-Befehls passiert ist:

λ > docker build -f Dockerfile -t aspnetcoreimage .
Sending build context to Docker daemon 4.393MB
Step 1/11 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
---> cf60f383a8d1

Step 2/11 : WORKDIR /app
---> Running in a0141eff2546
Removing intermediate container a0141eff2546
---> ad1a813fab27

Step 3/11 : COPY aspnetcoreapp/aspnetcoreapp.csproj ./
---> e7b454992e8a

Step 4/11 : RUN dotnet restore
---> Running in f27c6ff45ec6
Determining projects to restore…
Restored /app/aspnetcoreapp.csproj (in 157 ms).
Removing intermediate container f27c6ff45ec6
---> 805893f96f5c

Step 5/11 : COPY . ./
---> b70ad4b4d3cb

Step 6/11 : RUN dotnet publish -c Release -p:PublishDir=./output aspnetcoreapp/aspnetcoreapp.csproj
---> Running in 4a8a17424f5f
Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.Determining projects to restore…
Restored /app/aspnetcoreapp/aspnetcoreapp.csproj (in 150 ms).
aspnetcoreapp -> /app/aspnetcoreapp/bin/Release/netcoreapp3.1/aspnetcoreapp.dll
aspnetcoreapp -> /app/aspnetcoreapp/bin/Release/netcoreapp3.1/aspnetcoreapp.Views.dll
aspnetcoreapp -> /app/aspnetcoreapp/output/
Removing intermediate container 4a8a17424f5f
---> ad742806d55f

Step 7/11 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
---> 8aa5a7e8b51a

Step 8/11 : WORKDIR /app
---> Running in e8f6b81bd2b1
Removing intermediate container e8f6b81bd2b1
---> fc4cefd5b42a

Step 9/11 : COPY --from=build /app/aspnetcoreapp/output .
---> 0f8072747c1d

Step 10/11 : EXPOSE 80
---> Running in a72be83c219f
Removing intermediate container a72be83c219f
---> b06cb3bc5f75

Step 11/11 : ENTRYPOINT ["dotnet", "aspnetcoreapp.dll"]
---> Running in dd0286e426d0
Removing intermediate container dd0286e426d0
---> a5b89154c9a1

Successfully built a5b89154c9a1
Successfully tagged aspnetcoreimage:latest

Docker Deamon hat alle in der Datei enthaltenen Anweisungen gehorsam ausgeführt Docker-Datei, erstellte ein Bild mit dem Namen aspnetcore image und gab ihm ein Etikett letzte (über Tags ein anderes Mal, Working Tag == Version).

Großartig! Nichts als den Behälter laufen lassen und schon kann der Champagner geöffnet werden!

λ > docker run --name awesomeaspnetcontainer aspnetcoreimage:latest
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app

Ein bisschen mehr Details

Unsere App funktioniert (auch wenn wir dotnet sdk nicht auf dem Host installiert haben!) , aber es besteht kein Kontakt zur Außenwelt. Es ist also Zeit, Ihrer Fantasie freien Lauf zu lassen und alles ein wenig zu komplizieren.

Abb. 3. Unsere Bewerbung im Moment

Wir werden nichts umsetzen, weil das nicht der Zweck dieser Übung ist. Stattdessen werden wir so tun, als ob unsere kleine App mit anderen Diensten im System kommuniziert — und was! Lassen Sie uns für die Zwecke des Experiments Folgendes erkennen:

  • Wir verwenden eine andere API, um Anfragen zu verarbeiten, sei es ProductAPI
  • Die Anwendung verwendet eine Datenbank. Stellen wir fest, dass es sich um MySQL handelt
  • Die Anwendung verwendet einen Cache in Form von Redis, denn wer verbietet den Reichen

Das Einnähen ihrer Adressen in den Code funktioniert nicht. Lassen Sie uns also die Datei appsettings.json ein wenig ändern und dort etwas mehr Details hinzufügen

{
 "ProductApiAddress": null,
 "MySql": {
   "ConnectionString": null
 },
 "Redis": {
   "ConnectionString": null
 }
}

Wir könnten mehr als ein Dutzend Versionen dieser Datei erstellen (localhost, dev, qa, uat, prod,...) und die entsprechende verwenden, aber das klingt nicht sehr ermutigend — nicht nur, dass wir sie pflegen müssen, sondern dass die Bilder sensible Daten enthalten werden. Lassen Sie uns stattdessen Umgebungsvariablen für diesen Zweck verwenden.

Schnittstelle iConfiguration, das unter anderem für den Umgang mit Konfigurationsdateien verantwortlich ist, verfügt über mehrere interne Informationsquellen. Eine davon ist (Standard) Konfigurationsanbieter für Umgebungsvariablen, in der Lage, die im System (oder, wie in diesem Fall, im Container) gefundenen Umgebungsvariablen in in der Datei sichtbare Felder umzuwandeln App-Einstellungen. Damit ist eine bestimmte magische Syntax verbunden, über die es sich zu informieren lohnt. Zum Beispiel, wenn Sie zum Konfigurationsschlüssel gelangen möchten

Redis:ConnectionString

Sie müssen eine Umgebungsvariable mit dem Namen verwenden

Redis__ConnectionString

Banal, nicht wahr? Ich weiß nicht, warum Microsoft nicht mehr damit prahlt, einmal habe ich eine Weile gebraucht, um diese Abhängigkeit zu entdecken...
Die auf diese Weise bereitgestellte Konfiguration ist nicht im Image selbst enthalten, sodass das Risiko, sie zu verlieren, geringer ist. Es bleibt nur übrig, die entsprechenden Werte an das Innere des Containers zu übergeben. Wir werden das tun, wenn wir es ausführen:

λ > docker run --name awesomeaspnetcontainer –e ”ProductApiAddress=acme.com/api” –e ”MySql__ConnectionString=server=acme.com;database=ToyStoryCharacters;user=andy;password=WoodyPride” –e ”Redis__ConnectionString=acme.com:1337” aspnetcoreimage:latest

Psst, anstatt alles zu einem Befehl hinzuzufügen, kannst du verwenden Konfigurationsdatei

Wir haben uns um die Kommunikation mit anderen Diensten gekümmert, aber wenn wir versuchen, einige Informationen aus unserer Anwendung zu erhalten, die in einem Container läuft, wird sich herausstellen, dass die Abfragen ins Leere fliegen. Was ist los? Obwohl die Anwendung innerhalb des Containers auf Port 80 gestartet wurde, teilt sich die Docker-Laufzeit standardmäßig keine Ports vom Inneren des Containers zur Außenwelt. Wir müssen es selbst machen. Port 80 ist ziemlich stark belegt, aber wir sind immer noch im Container, also spielt es keine Rolle. Da die Netzwerkadressierung einzelner Container und des Hosts völlig separate Dinge sind, können Dutzende von Containern intern auf demselben Port laufen, ohne dass sie sich gegenseitig stören. Um jedoch irgendwie in unsere Anwendung zu kommen, müssen wir den bereits erwähnten Port 80 einem beliebigen (freien) Port der physischen Maschine zuordnen — sagen wir Port 5000. Das muss auch beim Starten des Containers gemacht werden

λ > docker run --name awesomeaspnetcontainer –e ”ProductApiAddress=acme.com/api” –e ”MySql__ConnectionString=server=acme.com;database=ToyStoryCharacters;user=andy;password=WoodyPride” –e ”Redis__ConnectionString=acme.com:1337” –p 5000:80 aspnetcoreimage:latest

Unser Programm weiß bereits, wo es alles findet, was es für die Arbeit benötigt, und hat gelernt, auf gesendete Anfragen zu antworten. Das ist großartig. Wir können ihn endlich in Ruhe lassen und ihn seine Aufgaben in Ruhe erledigen lassen. Aber lassen Sie uns zu einem anderen Thema übergehen.

Orchestrierung

Nein, es geht nicht darum Orchestermanagement, ich habe nur noch keinen guten Begriff dafür auf Polnisch gefunden. Es geht nur darum Verwaltung von Behältern. Alle vorherigen Schritte wurden entwickelt, um Ihnen die Arbeit zu erleichtern, indem sie den Anwendungsstartvorgang automatisieren. Wer, der bei klarem Verstand ist, möchte also dabei von Hand auf das Konsolenband schreiben, oder? Schließlich ist der oben abgebildete Befehl eine Art Drama! Nein, nein, nein, es ist nicht für uns. Natürlich gibt es einen einfacheren Weg, das zu tun, und zwar ganze Dutzende. Einer von ihnen ist Docker-Compose (Aufzeichnungen) — ein Tool, das unsere Arbeit wieder vereinfachen wird. Wir werden einmal schreiben und dann werden wir uns mit einem einfachen Befehl um alles kümmern. Im Ernst, ich verspreche, dass es diesmal so einfach sein wird!

Die Grundlage der Aktion Docker Compose es gibt eine Datei docker-compose.yml. Ja, du hast das richtig gelesen, diese Datei wird nur im YAML-Format sein. Ja, YAML lebt noch und es gibt immer noch Leute, die es benutzen. Und ja, es ist ziemlich umständlich, aber man kann sich daran gewöhnen. Ich möchte die glühenden Gegner von YAML trösten, dass stattdessen das JSON-Format verwendet werden kann.

Ohne weitere Umschweife — docker-compose.yml ist (unter anderem) eine andere Art zu schreiben, was wir bisher mit dem Befehl gemacht haben Docker-Lauf. In unserem Fall wird die ganze Datei so aussehen

1 | version: '2'
2 |
3 | services:
4 | awesomeaspnetcontainer:
5 | container_name: awesomeaspnetcontainer
6 | image: aspnetcoreimage:latest
7 | ports:
8 | - "5000:80"
9 | environment:
10| - ProductApiAddress=acme.com/api
11| - MySql__ConnectionString=server=acme.com;database=ToyStoryCharacters;user=andy;password=WoodyPride
12| - Redis__ConnectionString=acme.com:1337

Dies sind tatsächlich dieselben Informationen, die wir bisher verwendet haben, in einer anderen Form dargestellt. Indem wir alle Details in die YAML-Datei werfen, können wir sie tatsächlich vergessen. Das Starten unserer Anwendung läuft jetzt auf einen einfachen Befehl hinaus

λ > docker-compose up
Creating network "example_default" with the default driver
Creating awesomeaspnetcontainer ... done

Keine zusätzliche Hexerei, keine Komplikationen, die App funktioniert. Eigentlich müssen wir nicht einmal wissen, was genau wir gerade ausführen, denn der Computer merkt sich das für uns.

Ein weiteres Plus ist, dass Compose seine eigenen Behälter nach seinem Hund reinigt. Indem wir sie manuell starten, müssen wir sicherstellen, dass sie einen aussagekräftigen und eindeutigen Namen haben und dass sie keine verwaisten Behälter hinterlassen, die, wenn sie gestartet und beschädigt werden, zu einem vorzeitigen Ergrauen führen... Docker Compose ist ein weiterer Automatisierungsgrad, der all das für uns erledigen wird.

Lass uns verrückt werden — Orchestrierung eines größeren Systems

Jemand könnte mir jetzt vorwerfen, dass Docker Compose Bei einem Behälter ist dies übertrieben. Darin hat er recht, obwohl ich persönlich die Bequemlichkeit schätze, alles in einer Akte aufzubewahren .ymlVerfassen zeigt seine wahren Fähigkeiten in einer Situation, in der wir mehr Container haben. Viel mehr. Zu einer Zeit, als ich das System, mit dem ich zu der Zeit arbeitete, lokal einrichtete, benötigte ich mehr als vierzig davon. Ich kannte viele der Anwendungen, die dort liefen, nur dem Namen nach und hatte keine Ahnung, mit welcher Technologie sie erstellt wurden. Ein Pferd in der Reihe für jeden, der ein solches Monster ohne Containerisierung auf den Markt bringt!

Etwas zuvor haben wir uns davon überzeugt, dass unsere Anwendung funktionieren muss MySQLRedisa und geheimnisvoll Produkt-API. Lassen wir der Fantasie freien Lauf und fügen wir dort eine Handvoll Technologie hinzu. Vielleicht eine Anwendung in Node.js? Vielleicht ein NGINX? Konsul? Hase MQ? Elastische Suche?

Obwohl wir Technologien von der Decke nehmen, ist es nicht schwer vorstellbar, dass ein größeres IT-System sie alle nutzen könnte. All das können wir problemlos in einer einzigen Datei zusammenfassen Docker-Compose und automatisch mit einem einzigen Klick ausführen.
Unser übertriebenes und übertriebenes docker-compose.yml könnte so aussehen:

version: '2'
services:
 awesomeaspnetcontainer:
   container_name: awesomeaspnetcontainer
   image: aspnetcoreimage:latest
   # Konfiguration
 redis_asp:
   container_name: redisasp
   image: redis
   # Konfiguration
 mysql_asp:
   container_name: mysqlasp
   image: mysql
   # Konfiguration
   volumes:
     - mysql-data-volume:/var/lib/mysql
 product_api:
   container_name: productapi
   image: secretregistry.com/productapi:latest
   # Konfiguration
 nginx:
   container_name: nginx
   image: nginx
   # Konfiguration
 rabbitmq:
   container_name: rabbitmq
   image: rabbitmq
   # Konfiguration
 consul:
   container_name: consul
   image: consul
   # Konfiguration
 elastic:
   container_name: elastic
   image: elasticsearch
   # Konfiguration
   volumes:
     - elastic-data-volume:/usr/share/elasticsearch/data
 nodeapp:
   container_name: nodeapp
   image: secretregistry.com/nodeapp:latest
   # Konfiguration
 dotnetcoreapp:
   container_name: dotnetcoreapp
   image: secretregistry.com/dotnetcoreapp
   # Konfiguration
 javaapp:
   container_name: javaapp
   image: secretregistry.com/javaapp
   # Konfiguration
 mongo:
   container_name: mongo
   image: mongo
   # Konfiguration
   volumes:
     - mongo-data-volume:/data/db
volumes:
 mysql-data-volume:
 elastic-data-volume:
 mongo-data-volume:

Und nur gutes Weiß war die Nacht. Das ganze System zu starten ist ein Befehl, den ich dir übrigens schon einmal gegeben habe

λ > docker-compose up

As user (Developer/Tester) of one such systems must you not once know, what in within for you go — least during all so works, how it should. Der Himmel ist die Grenze!

Interpretation von Zusammenschlüssen

Ich hoffe, der obige Artikel hat ihre Neugier geweckt und sie vor allem unzufrieden gemacht. Wir haben gelernt, was Containerisierung ist, haben gelernt, wie man eine Anwendung in ein Image packt und was man später macht, um sie nützlich zu machen. If they have read this point, without absätze to jump — herzlichen Glückwunsch zu ihrem Durchhaltevermögen! Du bist auf dem besten Weg, den Docker näher zu treffen. Und das ist der Anfang - trotz der ausführlichen Beschreibung, mit denen Sie sich bereits vertraut haben, sind das nur die Grundlagen. This is but a important first step, and here must start. Alles deutet darauf hin, dass Docker noch lange bei uns bleiben wird. Es liegt auch im Interesse von uns allen — graues Rätsel in IT-Projekten —, uns Freunden.

Aber bevor du anfängst, muss ich dich warnen! Docker macht süchtig.

Docker ist wie die kostenlose erste Hit Cola. Wie beim nächsten Mal wünscht man sich, dass Sie k8s verwenden Hinter einem Müllcontainer in einer Gasse und frage mich, Wohin dein Leben gegangen ist. - Anonymer Reddit-Nutzer

Related posts

All posts
Blog post image

Technologien

Ein verteiltes Team leiten — wie geht das richtig?

Der Stil des Teammanagements wird oft von vielen Faktoren beeinflusst. Dazu geh...

Read more
Blog post image

Technologien

Was ist Docker und was sind die Vorteile seiner Verwendung?

Bevor Docker-Plattformen entwickelt wurden, mussten zum Starten von Anwendungen...

Read more
Blog post image

Technologien

Wie hat Blockchain unsere Welt verändert?

Jeden Tag wächst die Popularität von Blockchain. Fast seit ihrer Geburt im Ja...

Read more