Nachdem ich im letzten Artikel einen Blick auf den Azure App Service geworfen habe, der auch letztlich auf Docker-Containern basiert, stand als nächstes der Test des von Microsoft Azure Container Instances getauften Services auf dem Plan. Dabei wird eine Docker-Umgebung bereit gestellt, innerhalb der die jeweiligen Container lauffähig sind.
Das Ganze funktioniert, ohne dass vorab virtuelle Maschinen eingerichtet werden müssen. Als Ressourcen lassen sich Anzahl CPU-Cores und RAM wählen.
Dennoch erscheint mir die Unterscheidung zwischen App Service, der wiederum auch einen Web-App für Container beinhaltet, und Container Instances nicht allzu trennscharf. Zum Service namens Web-App für Container innerhalb des Azure App Service komme ich in einem späteren Artikel, aber da beide Services auch auf Docker-Containern basieren, könnte Microsoft hier ein wenig konkreter werden und die Unterschiede deutlicher herausstellen.
Container-Instanz Quickstart
Zunächst habe ich mich wieder an das einfache Beispiel im Quickstart-Artikel gehalten. Das Erstellen der Ressourcengruppe hatte ich im letzten Artikel ausführlich beschrieben. Für den Test der Container-Instances habe ich daher zunächst eine neue Ressourcengruppe namens geschkenetrgcnt1
erstellt.
Microsoft stellt eine kleine Beispiel-Anwendung bereit, die im Docker-Hub öffentlich verfügbar ist. Ebenfalls können eigene und private Docker-Images verwendet werden, dazu bietet Azure wiederum eine Image Registry an. Doch zunächst zum einfachsten Beispiel, ein Container wird allgemein erstellt mit:
az container create --resource-group myResourceGroup --name mycontainer --image microsoft/aci-helloworld --dns-name-label aci-demo --ports 80
Bezogen auf die vormals erstellte Ressourcengruppe und mit einem eindeutigen Container- sowie DNS-Namen gibt das az-Kommando folgendes zurück:
geschke@gohlis:~/azurecontainer1$ az container create --resource-group geschkenetrgcnt1 --name gncontainertest1 --image microsoft/aci-helloworld --dns-name-label gncntdemo --ports 80 { "containers": [ { "command": null, "environmentVariables": [], "image": "microsoft/aci-helloworld", "instanceView": null, "name": "gncontainertest1", "ports": [ { "port": 80, "protocol": null } ], "resources": { "limits": null, "requests": { "cpu": 1.0, "memoryInGb": 1.5 } }, "volumeMounts": null } ], "id": "/subscriptions/eine id/resourceGroups/geschkenetrgcnt1/providers/Microsoft.ContainerInstance/containerGroups/gncontainertest1", "imageRegistryCredentials": null, "instanceView": { "events": null, "state": "Pending" }, "ipAddress": { "dnsNameLabel": "gncntdemo", "fqdn": "gncntdemo.westeurope.azurecontainer.io", "ip": "IP-Adresse", "ports": [ { "port": 80, "protocol": "TCP" } ] }, "location": "westeurope", "name": "gncontainertest1", "osType": "Linux", "provisioningState": "Pending", "resourceGroup": "geschkenetrgcnt1", "restartPolicy": "Always", "tags": null, "type": "Microsoft.ContainerInstance/containerGroups", "volumes": null }
Zumindest ist darin keine Fehlermeldung zu lesen, auch wenn der Status zunächst „pending“ lautet. Es dauert einen Moment, denn das Image muss auch zunächst herunter geladen werden, bevor es gestartet werden kann. Mit dem Parameter --dns-name-label
wird der Hostname gewählt, unter dem der Container auf Port 80 (--ports
) später erreichbar sein soll. Die restlichen Parameter sind ebenso selbsterklärend.
Nun kann geprüft werden, ob der neu erstellte Container wirklich läuft.
Einerseits wie immer per Azure-Web-UI, andererseits auch via az-Kommando. Dabei kann auch die Ausgabe eingeschränkt werden, denn ansonsten würde Azure immer sämtliche Container-Daten übermitteln. Zur Einschränkung dient der Parameter „--query
„, beispielsweise ‚--query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}"
‚. Wenn zusätzlich noch das Ausgabeformat von JSON auf eine Tabellendarstellung geändert wird, erhält man z.B. folgendes:
geschke@gohlis:~/azurecontainer1$ az container show --resource-group geschkenetrgcnt1 --name gncontainertest1 --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" --out table FQDN ProvisioningState -------------------------------------- ------------------- gncntdemo.westeurope.azurecontainer.io Succeeded
Hier werden insofern nur der vollständige Hostname (FQDN) und der Bereitstellungsstatus angezeigt. Aufgrund des erfolgreichen Starts konnte daraufhin auch die entsprechende Website angezeigt werden.
Analog zu den App Services lassen sich auch die Log-Ausgaben des Containers betrachten. Allgemein:
az container logs --resource-group myResourceGroup --name mycontainer
Und in diesem Beispiel:
geschke@gohlis:~/azurecontainer1$ az container logs --resource-group geschkenetrgcnt1 --name gncontainertest1 listening on port 80 ::ffff:10.240.255.107 - - [01/Jul/2018:10:24:15 +0000] "GET / HTTP/1.1" 200 1663 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36" ::ffff:10.240.255.107 - - [01/Jul/2018:10:24:15 +0000] "GET /favicon.ico HTTP/1.1" 404 150 "http://gncntdemo.westeurope.azurecontainer.io/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36"
Dabei wurden die Logs des Containers auf die Standardausgabe geleitet, so dass sie außerhalb des Containers erreichbar sind. Darüber hinaus lässt sich auch der Ausgabestream anzeigen, was wiederum analog zum Docker-Befehl „docker logs -f <containername>
“ ist.
Zuletzt wurde der Container noch gelöscht, allgemein lautet das Kommando wie folgt:
az container delete --resource-group myResourceGroup --name mycontainer
Konkret wiederum:
geschke@gohlis:~/azurecontainer1$ az container delete --resource-group geschkenetrgcnt1 --name gncontainertest1 Are you sure you want to perform this operation? (y/n): y { "containers": [ { "command": null, "environmentVariables": [], "image": "microsoft/aci-helloworld", "instanceView": { "currentState": { "detailStatus": "", "exitCode": null, "finishTime": null, "startTime": "2018-07-01T10:20:33+00:00", "state": "Running" }, [...]
Zwar wird hier bei der Ausgabe noch der Status „running“ angezeigt, jedoch wurde kurz darauf der Container entfernt. Dies lässt sich wiederum mit dem Kommando „az container show...
“ überprüfen.
In der Web-UI waren die Ergebnisse weniger eindeutig. Denn im Dashboard wurde die soeben gelöschte Container-Instanz noch angezeigt.
Demgegenüber zeigt sich folgendes Bild, wenn man die Container-Instanz unter „Alle Ressourcen“ im Dashboard angeklickt hat:
Dies erscheint mir ein wenig inkonsistent zu sein, evtl. ist die Cache-Zeit im Dashboard zu hoch eingestellt oder ähnliches, denn nach einer gewissen Wartezeit war auch die Container-Instanz in der Übersicht nicht mehr zu sehen.
Ein eigenes Image als Container-Instanz
Der erste Test war somit erfolgreich abgeschlossen. Da jedoch der Test einer PHP-Anwendung mit dem Azure App Service so grandios gescheitert ist, wollte ich testen, ob diese Grav-Installation vielleicht im Rahmen der Container Instances, also innerhalb eines Containers funktionieren würde. Die nächsten Schritte im Azure Container Instances Tutorial versprachen dabei Unterstützung bei Azure-relevanten Teil. Konkret wird im ersten Teil auf die Vorbereitung eingegangen, d.h. Erstellen eines Beispiel-Images und ein lokaler Test. Da ich diesmal jedoch die Grav-Installation in einem Image verpacken wollte, war der Teil für mich erstmal weniger interessant. Auf dem Entwicklungsrechner, d.h. der Linux-Server, auf dem die Azure-CLI installiert ist, lief bereits Docker. Der nächste Schritt bestand daraus, ein Docker-Image zu erstellen und lokal zu testen. Darauf werde ich im Folgenden nicht weiter eingehen, nur soviel – für den Test habe ich sämtliche notwendigen Dateien und Dienste in ein Docker-Image gepackt. Dies war so ungefähr das genaue Gegenteil von dem, was an anderer Stelle beschrieben ist. Und für eine Produktionsumgebung würde ich ein derartiges Vorgehen auch nicht empfehlen. Letztlich umfasste das Docker-Image nicht nur Nginx, sondern auch PHP als php-fpm, beide wurden mittels Supervisord gestartet, dazu diente wiederum ein minimales Shellskript. Darüber hinaus wurden alle Dateien, die zu Grav gehörten, in das Image kopiert, was ebenfalls das Gegenteil aller Empfehlungen darstellt. Daher sei auch deutlich an dieser Stelle gesagt, dass es sich nur um ein Test-Image handelte, da ich wissen wollte, ob die Azure Container Instances mit der PHP-Anwendung zurecht kommen. Es sprach zwar nichts dagegen, aber beim App Service hatte das Deployment nicht funktioniert, insofern war der Test eher darauf ausgerichtet, die Verwendung eines eigenen Images zu testen, als dass eine Produktionsumgebung hergestellt werden sollte. Oberhalb von Container Instances lassen sich übrigens Containergruppen bilden, die wiederum aus mehreren Containern auf einem Host bestehen können. Wenn es hingegen darum geht, viele Container verwenden und diese orchestrieren zu wollen, so existiert dafür eine Lösung bei Azure, die auf Kubernetes basiert.
Als Voraussetzung für die folgende Beschreibung gilt nun, dass Docker auf dem lokalen Rechner bzw. Entwicklungsserver läuft, dass das zu verwendende Docker-Image ebenso dort vorhanden ist, und im besten Fall ist es darauf bereits getestet und funktioniert ohne auffällige Fehler.
Anlegen einer Docker Image Registry
Der erste Schritt besteht darin, eine private Image-Registry anzulegen. Azure bietet eine derartige Möglichkeit, so dass eigene Docker-Images in eine private Registry hochgeladen werden können. Die Registry ist jedoch nicht nur innerhalb von Azure verfügbar, sondern bietet letztlich eine gemanagte Version einer privaten Image-Registry, wie sie auch von Docker selbst angeboten wird.
Die Ressourcengruppe war bereits angelegt, insofern konnte die Azure Container Registry direkt erstellt werden. Allgemein wie folgt:
az acr create --resource-group myResourceGroup --name <acrName> --sku Basic --admin-enabled true
Und konkret:
geschke@gohlis:~/azurecontainer1/dockerimage$ az acr create --resource-group geschkenetrgcnt1 --name geschkenetphpapp --sku Basic --admin-enabled true { "adminUserEnabled": true, "creationDate": "2018-07-01T18:27:47.161082+00:00", "id": "/subscriptions/eine id/resourceGroups/geschkenetrgcnt1/providers/Microsoft.ContainerRegistry/registries/geschkenetphpapp", "location": "westeurope", "loginServer": "geschkenetphpapp.azurecr.io", "name": "geschkenetphpapp", "provisioningState": "Succeeded", "resourceGroup": "geschkenetrgcnt1", "sku": { "name": "Basic", "tier": "Basic" }, "status": null, "storageAccount": null, "tags": {}, "type": "Microsoft.ContainerRegistry/registries" }
Zwar dauerte das Erstellen der Container Registry relativ lange, aber der Status versprach, dass es funktioniert hätte.
Danach kann sich bei der Container Registry per Azure-CLI eingeloggt werden:
az acr login --name <acrName>
Insofern:
geschke@gohlis:~/azurecontainer1/dockerimage$ az acr login --name geschkenetphpapp Login Succeeded
Zwar wird der Hostname des Registry-Servers bereits beim Erstellen ausgegeben, aber auch dieser Details lassen sich jederzeit nachträglich anzeigen.
geschke@gohlis:~/azurecontainer1/dockerimage$ az acr show --name geschkenetphpapp --query loginServer --output tableResult --------------------------- geschkenetphpapp.azurecr.io
Bereitstellen eines Docker-Images im Registry-Server
Das Vorgehen des Hochladens zum Registry-Server ist völlig analog zu Docker – oder vielmehr, es ist handelt sich um das Docker-Standard-Verfahren, wie auch im Artikel zum Aufbau einer privaten Registry beschrieben. Zunächst wird das lokale Image mit einem Tag versehen. Das von mir genutzt Test-Image ist unter dem Namen „phpapp“ lokal auffindbar, insofern wird dieses Image mit dem entsprechend mit dem Hostname des Registry-Servers, dem Image-Namen und der Versionsnummer „getaggt“:
geschke@gohlis:~/azurecontainer1/dockerimage$ docker tag phpapp geschkenetphpapp.azurecr.io/phpapp:v1 geschke@gohlis:~/azurecontainer1/dockerimage$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE phpapp latest 89163196864e 14 minutes ago 489MB geschkenetphpapp.azurecr.io/phpapp v1 89163196864e 14 minutes ago 489MB
Die Auflistung zeigt den erfolgreichen Abschluss, der Tag ist verfügbar, beide Einträge in der Liste referenzieren dasselbe Image, die Image-ID ist identisch.
Danach muss das Image noch mit „docker push
“ an den Registry-Server übertragen werden. Auch bei dieser Standard-Aktion von Docker kommt kein Azure-CLI-Kommando zum Einsatz.
geschke@gohlis:~/azurecontainer1/dockerimage$ docker push geschkenetphpapp.azurecr.io/phpapp:v1 The push refers to repository [geschkenetphpapp.azurecr.io/phpapp] 99023e0c3b19: Pushed b6380e798db5: Pushed 7f466fb71a23: Pushed 31cd8ee1c74e: Pushed 8eac3c904da2: Pushed 0b905428c5f9: Pushed 6879b7d2d863: Pushed 0c7d1545367e: Pushed 8bfa54c47c9b: Pushed bc9c56bc1a66: Pushed e880e7eb0dde: Pushed b6f13d447e00: Pushed a20a262b87bd: Pushed 904d60939c36: Pushed 3a89e0d8654e: Pushed db9476e6d963: Pushed v1: digest: sha256:8205546ed6890c83ab2cabe65f1e373f5797944f94c91bda1c1f7a52a8325213 size: 3653
Ob das Hochladen funktioniert hat, lässt sich wiederum mit einem Azure-Cli-Kommando überprüfen:
az acr repository list --name <acrName> --output table
Dabei steht „acr“ für Azure Container Registry, die Ausgabe sieht nach dem erfolgreichen Hochladen wie folgt aus:
geschke@gohlis:~/azurecontainer1/dockerimage$ az acr repository list --name geschkenetphpapp --output table Result -------- phpapp
Auch die Versionsbezeichnung, d.h. der Tag kann betrachtet werden:
az acr repository show-tags --name <acrName> --repository aci-tutorial-app --output table
Konkret somit:
az acr repository show-tags --name geschkenetphpapp --repository phpapp --output table geschke@gohlis:~/azurecontainer1/dockerimage$ az acr repository show-tags --name geschkenetphpapp --repository phpapp --output table Result -------- v1
Dieser Schritt hat insofern wie gewünscht funktioniert. Natürlich lassen sich die Images auch in der Azure-UI finden.
Üblicherweise muss man sich bei privaten Registries einloggen, bei Docker wäre dies per „docker login <Registry>
“ und anschließender Eingabe des Passworts möglich. Falls man sich beim Ausführen des docker-Kommandos gefragt haben sollte, wieso keine Authentifizierung notwendig war – diesen Schritt hat die Azure-CLI bereits erledigt. Docker speichert die Authenfizierungsdaten. d.h. den entsprechenden Key, also kein Passwort im Klartext, in der Datei „~/.docker/config.json“. Genau darin ist für die Azure Container Registry ein Eintrag zu finden, so dass Docker diese Daten nutzt, um sich bei der Registry zu identifizieren.
Erstellen der Container-Instanz
Um nun einen Container aus dem frisch erstellten und in die Azure Registry hochgeladenen Image zu erstellen, fehlt noch ein Schritt. Dieser mutet vielleicht etwas seltsam an, denn bei der Erzeugung des Containers müssen neben dem Hostnamen des Registry-Servers auch der Username und das Passwort für die Azure Container Registry übergeben werden. Als Username fungiert der Name, unter dem die Registry erstellt wurde, im Beispiel weiter oben war dies „geschkenetphpapp
„. Doch beim Erzeugen musste kein Passwort gewähnt werden. Azure hat jedoch ein Passwort generiert, die Credentials sogar im Docker-Config-File eingetragen. Insofern wäre es sicherlich auch möglich gewesen, dass Azure einfach auf die Credentials zurück greift, die im System ja bereits gespeichert sind, sobald ein Registry-Server von Azure selbst genutzt wird. Sich das Passwort tatsächlich mit einem Query-Kommando anzeigen lassen und dann wiederum beim Erzeugen des Containers übergeben zu müssen, erscheint mir recht hakelig. Natürlich besteht auch die Möglichkeit, andere private Docker-Image-Registries zu nutzen, aber das sollte Azure doch recht einfach herausfinden können. Und besonders sicher erscheint mir die explizite Query eines Passworts mit anschileßender Übergabe per Azure-CLI ebenfalls nicht.
Um die Registry-Informationen anzusehen, wird das Kommando „az acr show…“ verwendet. Beispielsweise kann der Name des Servers abgefragt werden:
az acr show --name <acrName> --query loginServer
Wie erwartet erscheint somit:
geschke@gohlis:~/azurecontainer1$ az acr show --name geschkenetphpapp --query loginServer "geschkenetphpapp.azurecr.io"
Um das Passwort zu erhalten, bedient man sich folgender Query:
az acr credential show --name <acrName> --query "passwords[0].value"
Im Beispiel wäre das dann:
geschke@gohlis:~/azurecontainer1$ az acr credential show --name geschkenetphpapp --query "passwords[0].value" "hier_steht_das_passwort"
Mit all diesen Daten kann nun endlich der Container erzeugt werden. Das Kommando ist etwas länger geraten und lautet:
az container create --resource-group myResourceGroup --name aci-tutorial-app \ --image <acrLoginServer>/<imageName:Tag> --cpu 1 --memory 1 \ --registry-login-server <acrLoginServer> --registry-username <acrName> \ --registry-password <acrPassword> --dns-name-label aci-demo --ports 80
Wie man anhand der Parameter erkennt, lassen sich dabei auch Eigenschaften des Containers übermitteln, in dem Fall die Anzahl der CPU-Cores und die zu nutzende RAM-Kapazität. Darüber hinaus wird der Port 80 nach außen hin freigegeben.
Im Beispiel:
geschke@gohlis:~/azurecontainer1$ az container create --resource-group geschkenetrgcnt1 --name phpapptest1 --image geschkenetphpapp.azurecr.io/phpapp:v1 --cpu 1 --memory 1 --registry-login-server geschkenetphpapp.azurecr.io --registry-username geschkenetphpapp --registry-password "mein Passwort" --dns-name-label devgeschkenet --ports 80 { "containers": [ { "command": null, "environmentVariables": [], "image": "geschkenetphpapp.azurecr.io/phpapp:v1", "instanceView": null, "name": "phpapptest1", "ports": [ { "port": 80, "protocol": null } ], "resources": { "limits": null, "requests": { "cpu": 1.0, "memoryInGb": 1.0 } }, "volumeMounts": null } ], "id": "/subscriptions/eine id/resourceGroups/geschkenetrgcnt1/providers/Microsoft.ContainerInstance/containerGroups/phpapptest1", "imageRegistryCredentials": [ { "password": null, "server": "geschkenetphpapp.azurecr.io", "username": "geschkenetphpapp" } ], "instanceView": { "events": null, "state": "Pending" }, "ipAddress": { "dnsNameLabel": "devgeschkenet", "fqdn": "devgeschkenet.westeurope.azurecontainer.io", "ip": "eine IP", "ports": [ { "port": 80, "protocol": "TCP" } ] }, "location": "westeurope", "name": "phpapptest1", "osType": "Linux", "provisioningState": "Pending", "resourceGroup": "geschkenetrgcnt1", "restartPolicy": "Always", "tags": null, "type": "Microsoft.ContainerInstance/containerGroups", "volumes": null }
Die Ausgabe ist sehr umfangreich, es finden sich so gut wie alle Daten zum neuen Container darin. Der Status wird noch als „pending“ angezeigt, was daran liegt, dass das Docker-Image erst von der Azure Container Registry herunter geladen werden muss. Danach wird der Container erzeugt. Der Status kann auch wieder via az-Kommando überprüft werden:
az container show --resource-group myResourceGroup --name aci-tutorial-app --query instanceView.state
Oder konkret:
geschke@gohlis:~/azurecontainer1$ az container show --resource-group geschkenetrgcnt1 --name phpapptest1 --query instanceView.state "Running"
Das war es auch schon! Der Container konnte erfolgreich gestartet werden, natürlich lassen sich noch Informationen herausfinden wie der Hostname, unter dem die Website erreicht werden konnte, aber dieselben Informationen sind auch bereits in der Rückgabe des Start-Kommandos enthalten:
geschke@gohlis:~/azurecontainer1$ az container show --resource-group geschkenetrgcnt1 --name phpapptest1 --query ipAddress.fqdn "devgeschkenet.westeurope.azurecontainer.io"
Der Container läuft, das Login in die Admin-UI von Grav war problemlos möglich.
Die Geschwindigkeit ist ebenfalls zufriedenstellend. Zumindest konnte ich keine größeren Verzögerungen bemerken. Jedoch darf nicht vergessen werden, dass es sich dabei auch nur um einen einzigen Container handelt. Darin verpackt sind alle notwendigen Server-Dienste, aber auch Dateien. Mehrere Container lassen sich in Container-Gruppen strukturieren, so ist es möglich, z.B. den Web-Server getrennt von der Datenbank zu betreiben. Wobei hier im Beispiel keine Datenbank genutzt wurde, eine Möglichkeit der Aufteilung wäre etwa die Trennung von Nginx (Web-Server bzw. Proxy) und php-fpm-Service.
Darüber hinaus gehende Funktionen, etwa zur Orchestrierung mehrerer oder einer Vielzahl von Containern ist erst mit den Kubernetes-Diensten möglich.
Fazit
Letztlich bieten die Azure Container-Instances somit eine Teilmenge dessen, was im einfachsten Fall mit einer Installation eines Docker-Daemons auf einem Host möglich ist. Denn wenn man sich die verfügbaren Kommandos für die Container-Gruppe ansieht, wird man feststellen, dass darin kein Kommando für das Stoppen eines Containers vorhanden ist:
geschke@gohlis:~/azurecontainer1/multicontainerwordpress$ az container --help Group az container: Manage Azure Container Instances. Commands: attach: Attach local standard output and error streams to a container in a container group. create: Create a container group. delete: Delete a container group. exec : Execute a command from within a running container of a container group. export: Export a container group in yaml format. list : List container groups. logs : Examine the logs for a container in a container group. show : Get the details of a container group.
Es ist also nicht möglich, einen laufenden Container zu stoppen und wieder fortzusetzen. Das ist aus Sicht des Cloud-Providers auch logisch, denn möglicherweise wird beim Erzeugen des Containers ein völlig anderer Host verwendet, der zufällig an der Reihe war. Infolge dessen sind auch die im Container während der Laufzeit geänderten Daten nicht mehr vorhanden. Das entspricht zwar einerseits dem Konzept der „ephemeral“ („flüchtig“) Container , die nach Belieben gestartet, gestoppt, verschoben usw. werden können, bedingt aber auch, dass sich der Nutzer von Azure eine Möglichkeit suchen muss, um Persistenz zu erhalten. Für eine Datenbank besitzt Azure dafür ebenso gemanagte Lösungen wie zur Speicherung von Dateien (z.B. Azure-Dateifreigabe). Somit gilt wie immer – es kommt auf die Anwendung an! Die Komplexität ist gegenüber eines einfachen Docker-Daemons, der auf einer fest definierten (virtuellen) Maschine genutzt wird, natürlich höher. Es können keine lokalen Verzeichnisse in die Container gemountet werden, die Container lassen sich nicht beenden und neu starten, ohne dass sie ihren Zustand verlieren. Das alles wäre bei Docker auf einer klassischen VM möglich. Andererseits sind dort die Möglichkeiten zur Skalierung beschränkt bzw. der Aufwand dafür, z.B. verteilen Speicher oder verteilte Datenbanken zu betreiben, ist wesentlich höher.
Nicht zuletzt ist auch der Preis zu berücksichtigen. Die einfachste Container Instanz mit einem CPU-Core und einem GB RAM würde pro Monat laut Prognose mehr als 40 EUR kosten. Darin inbegriffen sind die Container Registry, die momentan zwei Versionen eines Docker-Images beinhaltet. In Relation zu Angeboten von günstigen VMs der einschlägigen Provider wären die Kosten damit um ein Vielfaches höher. Für das Hosting einer kleinen Website im privaten Rahmen, oder auch für einen Freiberufler, der auch kein Problem damit hat, eine VM zu administrieren, lohnt sich die Nutzung von Azure somit kaum. In der Zielgruppe von Unternehmenskunden mag dies schon wieder ganz anders aussehen, wenn eine Stunde Personalaufwand mit einem höheren Aufwand zu beziffern ist als die Kosten für einen Monat Azure Container Instances. Davon abgesehen bietet Azure ebenfalls im einfachsten Fall virtuelle Maschinen an, auf denen dann beliebige Services installiert werden können. Der Preisunterschied zwischen der einfachsten Azure-Variante verglichen mit anderen VM-Anbietern ist hier nicht ganz zu hoch, wobei Azure wesentlich mehr Ausstattungsvarianten bietet als klassische Provider.
Ich habe mir nach den Container Instances noch die Containergruppen angesehen und die „Web-App für Container“ genannten Dienste getestet. Letzterer Dienst ist wiederum beim App Service angesiedelt. Die Ergebnisse werde ich noch kurz zusammenfassen, danach jedoch auch den Test von Azure voraussichtlich beenden, auch wenn ich damit insgesamt nur einen Bruchteil von Azure unter die Lupe genommen haben werde. Immerhin stimmen die Ergebnisse des Tests der Container Instances positiv – sie haben letztlich wie erwartet funktioniert.