Blog

Dockern in Azure – Eine Applikation für Azure Container Registry deployen

27 Sep 2022

Docker Container

Docker ist ein Tool, um Applikationen mittels Containerisierung zu bauen, zu installieren und zu betreiben. Diese Container sind leichter und benötigen eine kürzere Startzeit im Vergleich zu traditionellen Servern. Sie verbessern außerdem die Performance und reduzieren Kosten, während sie gleichzeitig gutes Resource Management zur Verfügung stellen. Ein weiterer Vorteil von Docker ist, dass man nicht...
Read More

Docker ist ein Tool, um Applikationen mittels Containerisierung zu bauen, zu installieren und zu betreiben. Diese Container sind leichter und benötigen eine kürzere Startzeit im Vergleich zu traditionellen Servern. Sie verbessern außerdem die Performance und reduzieren Kosten, während sie gleichzeitig gutes Resource Management zur Verfügung stellen. Ein weiterer Vorteil von Docker ist, dass man nicht wie bisher jedem Container vorab einen Datenspeicher zuordnen muss.

Docker-Container und Docker Images

Ein Docker-Container ist eine virtualisierte Runtime-Umgebung, die vor allem bei der Applikationsentwicklung verwendet wird. Wie bereits erwähnt, ist es mit Docker möglich, Applikationen zu bauen, zu implementieren und zu betreiben. Das Besondere ist, dass die Container von der zugrundliegenden Hardware unabhängig sind. Ein Docker-Container kann nur eine Maschine nutzen, seinen Systemkern teilen und das OS virtualisieren, um mehr isolierte Prozesse laufen zu lassen. Docker-Container sind also leichtgewichtig.

Ein Docker Image hingegen ist wie ein Schnappschuss in einer anderen Art von VM Environment. Es handelt sich um die Abbildung eines Docker-Containers zu einem spezifischen Zeitpunkt. Außerdem sind Docker Images nicht veränderbar. Man kann sie zwar nicht verändern, aber dafür kann man sie duplizieren, teilen und löschen. Dieses Feature ist nützlich, um neue Software oder Konfigurationen zu testen, denn das Image bleibt gleich, egal was sonst passiert. Um zu existieren, sind Container auf vorhandene, lauffähige Images angewiesen. Sie sind von Images abhängig, da sie verwendet werden, um Runtime-Umgebungen aufzubauen. Gleichzeitig werden sie benötigt, um Applikationen laufen zu lassen.

Deployment von Containern

Mit der 5-R-Strategie für Cloudmigrationen, die sich mit Containern befasst, können wir uns verdeutlichen, wie wir Applikationen deployen können, wenn wir sie Rehosten oder Refaktorisieren wollen, den Microservices-Ansatz verwenden wollen, um die Architektur zu ändern (Rearchitect) und wie wir Patterns für eine neue Applikation bauen können (Repurchase), um zukünftig eine Cloud-native Strategie umzusetzen (Abb. 1).

rebai_trebalsi_azure_container_registry_1.tif_fmt1.jpg
Abb. 1: Rehosting, Refactoring und Rearchitecting

Container lokal betreiben

Nun sollten wir unsere Entwicklungsumgebung darauf vorbereiten, Container lokal zu betreiben. Hierfür müssen einige Schritte befolgt werden:

  1. Docker Desktop installieren. Die Software ist kostenlos und erhältlich für macOS und Windows.

  2. Visual Studio 2022 oder Visual Studio Code installieren (für diesen Artikel habe ich die neueste Version von Visual Studio 2022 und .NET 6 verwendet)

  3. Einen Azure-Account anlegen, mit dem man eine Azure Container Registry erstellen kann.

  4. PowerShell in Windows oder Azure Cloud Shell öffnen über https://shell-azure.com.

  5. Wenn man Visual Studio Code verwendet, müssen die Extensions Microsoft C# for Visual Studio Code [1], Docker [2] und Azure App Service [3] installiert werden.

Sobald die Entwicklungsumgebung bereit ist, können wir damit anfangen, ein Docker Image einer Webapplikation zu erstellen, für das wir eine existierende Visual-Template-Vorlage verwenden. Man kann aber auch Microsoft ASP.NET Core Images verwenden, um das Image lokal zu pushen und zu betreiben [4]. Zuvor ist es aber wichtig, auf einige der Docker Image Commands einzugehen, die in diesem Artikel noch verwendet werden:

  • docker image build: erstellt ein Image eines Dockerfile

  • docker tag: erzeugt einen Tag, wie bspw. TARGET_IMAGE, der es Nutzer:innen ermöglicht, Container-Images zu gruppieren und zu organisieren

  • docker image pull: zieht ein Image oder Repository aus einer Registry

  • docker image push: pusht ein Image oder Repository in eine Registry

  • docker image rm: entfernt ein oder mehrere Images

Das Application Image erzeugen

Um ein Application Image zu erzeugen, kann das voreingestellte Template in Visual Studio 2022 verwendet werden. Man muss lediglich einen Haken bei Enable Docker für alle ausgewählten Webapplikation setzen (Abb. 2).

rebai_trebalsi_azure_container_registry_2.tif_fmt1.jpg
Abb. 2: Enable Docker im Visual-Studio-2022-Template

Man kann auch einen Klon aus dem Microsoft Repository auf Docker Hub [5] erzeugen. Das wird auch einer unserer nächsten Schritte sein.

  1. Das .NET Docker Repository [6] klonen (Abb. 3):

    git clone https://github.com/dotnet/dotnet-docker
  2. Zur Projektmappe dotnet-docker/samples/aspnetapp navigieren und die Applikation wie in Abbildung 4 lokal ausführen:

    dotnet run --project aspnetapp
  3. Die App unter http://localhost:5000 zum Testen im Browser öffnen

rebai_trebalsi_azure_container_registry_3.tif_fmt1.jpg
Abb. 3: Das .NET-Docker-Repository klonen
rebai_trebalsi_azure_container_registry_4.tif_fmt1.jpg
Abb. 4: run – -project aspnetapp

Sie können Ihre Softwarelösung in jeder IDE öffnen. In Visual Studio 2022 muss nur aspnetapp.sln angeklickt werden und die Applikation wird gestartet. Jetzt kann man Content sehen, ihn kompilieren und ausführen. In Visual Studio Code kann die Projektmappe geöffnet werden (Abb. 5).

rebai_trebalsi_azure_container_registry_5.tif_fmt1.jpg
Abb. 5: Die Projektmappe in Visual Studio Code öffnen

Wenn Sie Visual Studio 2022 verwenden, können Sie das .NET-Docker-Repository verwenden und wie in Abbildung 6 auf Clone a repository klicken. Es ist notwendig, den Repository-Link (https://github.com/dotnet/dotnet-docker) in die Repository Location-Box im Clone a Repository-Fenster zu übernehmen. Hierzu muss man den Pfad zum lokalen Source-File hinzufügen, danach im Browse a Repository-Bereich Github auswählen und abschließend den Clone-Knopf drücken (Abb. 7).

rebai_trebalsi_azure_container_registry_6.tif_fmt1.jpg
Abb. 6: Clone a repository
rebai_trebalsi_azure_container_registry_7.tif_fmt1.jpg
Abb. 7: Clone-a-Repository-Fenster ausfüllen

Da wir nun ein Beispiel für ein Application Image haben, können wir jetzt lokal ein Docker Image erstellen.

Docker Image

Um ein Docker Image zu erstellen, gibt es zwei unterschiedliche Methoden, die beide im Folgenden näher beleuchtet werden:

Interaktive Methode

Mit dieser Methode betreiben Nutzer:innen von einem existierenden Docker Image aus einen Container und nehmen manuell vor dem Speichern des Image Änderungen an der Umgebung vor. Das ist die einfachste Methode, um ein Docker Image zu erzeugen. Für die interaktive Methode sind folgende Schritte nötig:

  1. Docker starten und eine Terminal-Session oder ein PowerShell-Terminal öffnen.

  2. Den Docker Run Command image_name:tag_name verwenden; es wird eine Shell Session mit dem vom Image gelaunchten Container gestartet.

  3. Nun müssen Sie mit dem Befehl docker run -it –rm -p 8000:80 –name aspnetcore_sample mcr.microsoft.com/dotnet/samples:aspnetapp die vorherige Webapplikation laufen lassen.

  4. Wenn der Name des Tags weggelassen wird, verwendet Docker die aktuelle Version des Images.

  5. Das Image sollte in der Ergebnisliste von Docker Desktop auftauchen, wie in Abbildung 8 zu sehen ist.

  6. Mit $ docker images kann die Liste der lokalen Images aufgerufen werden (Abb. 9).

rebai_trebalsi_azure_container_registry_8.tif_fmt1.jpg
Abb. 8: Docker Desktop
rebai_trebalsi_azure_container_registry_9.tif_fmt1.jpg
Abb. 9: Image-Liste

Dockerfile-Methode

Für diesen Ansatz muss ein Plain-Text-Dockerfile erstellt werden. Das Dockerfile enthält alle Spezifikationen, um ein Image zu erstellen (Abb. 10). Dieser Prozess ist schwieriger und zeitaufwendiger, lässt sich aber gut in Continuous Delivery Environments einsetzen. Diese Methode beinhaltet die Erstellung eines Dockerfile und das Hinzufügen von Befehlen, die man für das Image benötigt. Sobald das Dockerfile startet, erstellen die User:innen eine .dockerignore-Datei, um alle Dateien auszuschließen, die für den endgültigen Build nicht benötigt werden (Abb. 11). Die .dockerignore-Datei befindet sich im Root Directory. Als Nächstes wird der Befehl docker build verwendet, um ein Docker Image zu erstellen. Zusätzlich werden ein Image-Name und -Tag festgelegt. Abschließend wird mit dem Befehl docker image das erstellte Image angezeigt.

rebai_trebalsi_azure_container_registry_10.tif_fmt1.jpg
Abb. 10: Dockerfile in der Dockerfile-Methode
rebai_trebalsi_azure_container_registry_11.tif_fmt1.jpg
Abb. 11: Beispiel für eine .dockerignore-Datei

Im Folgenden werden einige der in Abbildung 10 verwendeten Befehle ausführlicher erklärt:

  • FROM mcr.microsoft.com/dotnet/sdk:6.0Das Dockerfile beginnt immer mit dem FROM-Befehl, der eine neue Building Stage initialisiert und das Base Image festlegt, auf dem wir aufbauen.

  • WORKDIR /source: Der WORKDIR-Befehl setzt das aktuelle Directory, an dem wir arbeiten, in unserem Image fest. In unserem Fall handelt es sich hierbei um den /source-Ordner, der das Root-Verzeichnis unserer Lösung ist.

  • COPY *.sln . und COPY aspnetapp/*.csproj ./aspnetapp/Der COPY-Befehlt kopiert alle Dateien vom lokalen System in das aktuell bearbeitete Directory des Image. In unserem Beispiel wird eine .dockerignore-Datei verwendet, an der sich der COPY-Befehl beim kopieren orientiert.

  • RUN dotnet restore: Der RUN-Befehl führt alle Befehle in einem neuen Layer aus und übergibt sie an das Base Image. In unserem Fall werden wir die Packages für unsere Lösung, ähnlich dem lokalen Betrieb, wiederherstellen, allerdings läuft das im Image ab.

  • RUN dotnet publish -c release -o /app –no-restore: Das aktuelle Directory wird zu /publish geändert.

  • ENTRYPOINT [„dotnet“, „aspnetapp.dll“]: Der ENTRYPOINT-Befehl ermöglicht es uns, die Container so zu verändern, dass sie als Executables laufen.

Da wir mit jedem Build alle Dateien in das Docker Image kopieren, verwenden wir die .dockerignore-Datei, um einzelne Daten und Mappen auszuwählen zu können, die wir nicht jedes Mal kopieren wollen. Unser Image ist fertig. Wir erstellen und speichern es mit Azure Container Registry (ACR).

Images erstellen und speichern mit ACR

Azure Container Registry ist ein Azure Service, der es ermöglicht, eigene, private Docker Registries zu erstellen. Er ähnelt Docker Hub, bietet aber einige einzigartige Benefits: Container Registry läuft in Azure Container, ist hochskalierbar und bietet eine erweiterte Durchsatzrate für Docker Pulls, die mehrere Nodes gleichzeitig umfassen kann.

ACR über Azure Portal erstellen

Zunächst klicken wir im Azure Portal auf den Button Create New Ressource (Abb. 12).

rebai_trebalsi_azure_container_registry_12.tif_fmt1.jpg
Abb. 12: Create New Resource im Azure Portal

Nachdem wir Container Registry ausgewählt haben, wird auf der rechten Seite des Bildschirms Containers angeklickt (Abb. 13). Hier wählen wir Create, um eine neue Container-Registry anzulegen.

rebai_trebalsi_azure_container_registry_13.tif_fmt1.jpg
Abb. 13: Auswahl des Menüpunkts Containers in Container Registry

Im nächsten Formular muss die Registry konfiguriert werden. Es werden die Subscription, die Bezeichnung der Registry und die Location, die SKU, ausgewählt. Für diesen Artikel wurde Basic SKU ausgewählt. Wir wählen die Option Enabled bei Availability Zones aus und drücken Review + Create. Sobald alles kontrolliert wurde, kann die Registry erstellt werden. Wenn im Networking-Tab Basic oder Standard SKU ausgewählt ist, kann die Connectivity nicht so konfiguriert werden, dass eine Verbindung zu dieser Registry über öffentliche IP-Adressen oder einen privaten Endpunkt möglich ist. Das geht nur mit Premium SKU.

Wir haben mehr als einen Tab, etwa NetworkingEncryption und Tags. Azure Container Service Encryption schützt die Daten, indem es Images und andere Artifacts verschlüsselt, wenn sie in die Registry geschoben werden, und beim Pull-Vorgang wieder entschlüsselt. Ein Customer Managed Key ist nur für Premium SKU verfügbar.

Eine ACR mit Azure CLI erstellen

Wenn keine Resource Group vorhanden ist, muss über folgenden Befehl eine erstellt werden:

az group create --name <resource-groupe-name> --location <location>

Als Nächstes erstellt man in der Resource Group eine Azure-Container-Registry-Instanz:

az acr create --resource-group <resource_group_name> --name <registry_name> --sku Basic --admin-enabled true

Wenn wir uns verbinden möchten, um uns in der Container Registry anzumelden, benötigen wir Administratorenrechte. Also muss -admin-enabled true hinzugefügt werden, um anzuzeigen, ob der User adminbevollmächtigt ist.

Ein Image mit Docker CLI in die ACR pushen

Selbst wenn wir die Administratoren der Container Registry sind, werden wir uns mit dem folgenden Befehl in das ACR einloggen:

az acr login --name <registry_name>

Dieser Befehl gibt die Nachricht „Login Succeeded“ aus, wenn der Prozess beendet ist. Um jetzt das Application Container Image mit der Azure Container Registry zu verwenden, müssen wir unser Image mit der Log-in-Serveraddresse unserer Registry taggen. Dafür müssen diese Schritte befolgt werden:

  1. Den Befehl $ docker images verwenden, um die Liste lokaler Images anzuzeigen (Abb. 14)

  2. Durch folgenden Befehl die Log-in-Serveraddresse für die Azure Container Registry erhalten:

    az acr list --resource-group <resource_group_name> --query "[].{acrLoginServer:loginServer}" --output table
  3. Jetzt muss das Application Image mit der Log-in-Serveraddress der Registry aus Schritt 2 getaggt werden; das fügt ein Alias des Application Image mit vollständigem Pfad zu unserer Registry hinzu:

    docker tag yourtagtoadd<registry_login_server>/yourtagtoadd:01
  4. Das Docker Image kann verwendet werden, um den Tag zu verifizieren

  5. Jetzt wird das Application Image in die Container Registry gepusht:

    docker push <registry_login_server>/yourtagtoadd:01
  6. Abschließend wird überprüft, ob das Image in die Registry hochgeladen wurde:

    docker push <registry_login_server>/yourtagtoadd:01
rebai_trebalsi_azure_container_registry_14.tif_fmt1.jpg
Abb. 14: Liste lokaler Images

Fazit

Containerized Applications können kompliziert sein. In einer Produktionsumgebung mit verteilten Anwendungen kann es sein, dass hundert bis tausend separate Container benötigt werden. In einem solchen Fall profitieren Container-Runtime-Environments wie Docker vom Gebrauch anderer Tools, um alle verwendeten Container zu orchestrieren und zu managen. Eines der populärsten Tools für diesen Zweck ist Kubernetes, ein Containerorchestrator, der eine Vielzahl an Container-Runtime-Environments inklusive Docker erkennt. Außerdem können wir Azure Kubernetes als verlässliche Lösung nutzen, um DevOps und Kubernetes zusammenzubringen und die Geschwindigkeit und Sicherheit des Entwicklungsprozesses zu verbessern. Durch die Verwendung von Azure DevOps ist es uns möglich, Continuous Integration, Continuous Delivery und sichere DevOps-Implementierungen mit Kubernetes umzusetzen.

rebai_trebalsi_hamida_sw.tif_fmt1.jpg
Hamida Rebaï Trabelsi arbeitet als Senior Cloud Application Architect bei Revenu Quebec, einer kanadischen Government Agency. Seit 2017 wurde sie von Microsoft im Bereich Developer Technologies als Most Valuable Professional ausgezeichnet. Sie ist zertifizierte Microsoft-Trainerin, internationale Rednerin, Azure zertifiziert, Mitglied der .NET Foundation und anerkannter Microsoft DevHero.