Erstellen einer Funktion unter Linux mit einem benutzerdefinierten Container
In diesem Tutorial erstellen Sie Code und stellen ihn anschließend in Azure Functions als benutzerdefinierten Docker-Container mit einem Linux-Basisimage bereit. Normalerweise verwenden Sie ein benutzerdefiniertes Image, wenn Sie für Ihre Funktionen eine bestimmte Sprachversion benötigen oder über eine bestimmte Abhängigkeit oder Konfiguration verfügen, die über das integrierte Image nicht bereitgestellt wird.
Von Azure Functions wird jede Sprache oder Runtime mit benutzerdefinierten Handlern unterstützt. Für einige Sprachen (beispielsweise die in diesem Tutorial verwendete Programmiersprache R) müssen Sie die Runtime oder zusätzliche Bibliotheken als Abhängigkeiten installieren, die die Verwendung eines benutzerdefinierten Containers erfordern.
Die Bereitstellung Ihres Funktionscodes in einem benutzerdefinierten Linux-Container erfordert Hosting im Premium-Tarif oder in einem Dedizierten Tarif (App Service-Tarif). Das Abschließen dieses Tutorials verursacht Kosten von einigen USD auf Ihrem Azure-Konto, die Sie durch Bereinigen der Ressourcen minimieren können, wenn Sie fertig sind.
Sie können auch einen Azure App Service-Standardcontainer verwenden. Dies ist unter Schnellstart: Erstellen Ihrer ersten unter Linux gehosteten Funktion unter Verwendung von Befehlszeilentools beschrieben. Unterstützte Basisimages für Azure Functions finden Sie im Azure Functions-Repository für Basisimages.
In diesem Tutorial lernen Sie Folgendes:
- Erstellen einer Funktions-App und Dockerfile mit den Azure Functions Core Tools.
- Erstellen eines benutzerdefinierten Images mit Docker.
- Veröffentlichen eines benutzerdefinierten Images in einer Containerregistrierung.
- Erstellen von unterstützenden Ressourcen in Azure für die Funktions-App.
- Bereitstellen einer Funktions-App über Docker Hub.
- Hinzufügen von Anwendungseinstellungen für die Funktions-App.
- Aktivieren Sie Continuous Deployment.
- Aktivieren Sie SSH-Verbindungen mit dem Container.
- Fügen Sie eine Queue Storage-Ausgabebindung hinzu.
- Erstellen einer Funktions-App und Dockerfile mit den Azure Functions Core Tools.
- Erstellen eines benutzerdefinierten Images mit Docker.
- Veröffentlichen eines benutzerdefinierten Images in einer Containerregistrierung.
- Erstellen von unterstützenden Ressourcen in Azure für die Funktions-App.
- Bereitstellen einer Funktions-App über Docker Hub.
- Hinzufügen von Anwendungseinstellungen für die Funktions-App.
- Aktivieren Sie Continuous Deployment.
- Aktivieren Sie SSH-Verbindungen mit dem Container.
Sie können dieses Tutorial auf allen Computern durcharbeiten, auf denen Windows, macOS oder Linux ausgeführt wird.
Konfigurieren Ihrer lokalen Umgebung
Bevor Sie beginnen, müssen die folgenden Voraussetzungen erfüllt sein:
Azure Functions Core Tools, Version 4.x.
Eines der folgenden Tools zum Erstellen von Azure-Ressourcen:
Das Az PowerShell-Modul Version 5.9.0 oder höher.
- Node.js, Active LTS- und Maintenance LTS-Versionen (8.11.1 und 10.14.1 empfohlen)
- Python 3.8 (64 Bit), Python 3.7 (64 Bit), Python 3.6 (64 Bit). Diese Versionen werden von Azure Functions unterstützt.
Das Java Developer Kit, Version 8 oder 11.
Apache Maven Version 3.0 oder höher
- Entwicklungstools für die von Ihnen verwendete Sprache. In diesem Tutorial wird als Beispiel die Programmiersprache R verwendet.
Wenn Sie kein Azure-Abonnement haben, erstellen Sie ein kostenloses Azure-Konto, bevor Sie beginnen.
Außerdem müssen Sie Docker und eine Docker-ID abrufen:
Erstellen und Aktivieren einer virtuellen Umgebung
Führen Sie die folgenden Befehle in einem geeigneten Ordner aus, um eine virtuelle Umgebung mit dem Namen .venv zu erstellen und zu aktivieren. Achten Sie darauf, dass Sie Python 3.8, 3.7 oder 3.6 verwenden. Diese Versionen werden von Azure Functions unterstützt.
python -m venv .venv
source .venv/bin/activate
Führen Sie den folgenden Befehl aus, wenn über Python das venv-Paket auf Ihrer Linux-Distribution nicht installiert wurde:
sudo apt-get install python3-venv
Sie führen alle nachfolgenden Befehle in dieser aktivierten virtuellen Umgebung aus.
Erstellen und Testen des lokalen Funktionsprojekts
Führen Sie in einem Terminal oder an einer Eingabeaufforderung den folgenden Befehl für die gewählte Sprache aus, um ein Funktions-App-Projekt im aktuellen Ordner zu erstellen:
func init --worker-runtime dotnet --docker
func init --worker-runtime node --language javascript --docker
func init --worker-runtime powershell --docker
func init --worker-runtime python --docker
func init --worker-runtime node --language typescript --docker
Führen Sie in einem leeren Ordner den folgenden Befehl aus, um das Functions-Projekt über einen Maven-Archetyp zu generieren:
mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=8 -Ddocker
Der -DjavaVersion-Parameter teilt der Functions-Runtime mit, welche Version von Java verwendet werden soll. Verwenden Sie -DjavaVersion=11, wenn Sie Ihre Funktionen in Java 11 ausführen möchten. Wenn Sie -DjavaVersion nicht angeben, wird für Maven standardmäßig Java 8 verwendet. Weitere Informationen finden Sie unter Java-Versionen.
Wichtig
Damit Sie diesen Artikel durcharbeiten können, muss die Umgebungsvariable JAVA_HOME auf den Installationsspeicherort der richtigen Version des JDK festgelegt sein.
Maven fordert Sie zur Eingabe von Werten auf, die erforderlich sind, um die Generierung des Projekts bei der Bereitstellung abzuschließen. Geben Sie an den Eingabeaufforderungen die folgenden Informationen an:
| Prompt | Wert | BESCHREIBUNG |
|---|---|---|
| groupId | com.fabrikam |
Ein Wert, der Ihr Projekt projektübergreifend eindeutig identifiziert. Für den Wert müssen die Paketbenennungsregeln für Java eingehalten werden. |
| artifactId | fabrikam-functions |
Der Name des Behälters (ohne Versionsnummer). |
| version | 1.0-SNAPSHOT |
Wählen Sie den Standardwert aus. |
| package | com.fabrikam.functions |
Das Java-Paket für den generierten Funktionscode. Verwenden Sie den Standardwert. |
Geben Sie zur Bestätigung Y ein, oder drücken Sie die EINGABETASTE.
Maven erstellt die Projektdateien in einem neuen Ordner namens artifactId, in diesem Beispiel fabrikam-functions.
func init --worker-runtime custom --docker
Mit der Option --docker wird eine Dockerfile für das Projekt generiert. Hiermit wird ein geeigneter benutzerdefinierter Container zur Verwendung mit Azure Functions und der ausgewählten Runtime definiert.
Navigieren Sie zum Projektordner:
cd fabrikam-functions
An der Dockerfile-Datei sind keine Änderungen erforderlich.
Fügen Sie mit dem folgenden Befehl dem Projekt eine Funktion hinzu. Hierbei ist das --name-Argument der eindeutige Name Ihrer Funktion, und mit dem --template-Argument wird der Trigger der Funktion angegeben. func new erstellt eine C#-Codedatei in Ihrem Projekt.
func new --name HttpExample --template "HTTP trigger" --authlevel anonymous
Fügen Sie mit dem folgenden Befehl dem Projekt eine Funktion hinzu. Hierbei ist das --name-Argument der eindeutige Name Ihrer Funktion, und mit dem --template-Argument wird der Trigger der Funktion angegeben. Mit func new wird ein Unterordner mit dem Funktionsnamen erstellt, der eine Konfigurationsdatei mit dem Namen func new enthält.
func new --name HttpExample --template "HTTP trigger" --authlevel anonymous
Erstellen Sie in einem Text-Editor eine Datei im Projektordner mit dem Namen handler.R. Fügen Sie den folgenden Code als Inhalt hinzu:
library(httpuv)
PORTEnv <- Sys.getenv("FUNCTIONS_CUSTOMHANDLER_PORT")
PORT <- strtoi(PORTEnv , base = 0L)
http_not_found <- list(
status=404,
body='404 Not Found'
)
http_method_not_allowed <- list(
status=405,
body='405 Method Not Allowed'
)
hello_handler <- list(
GET = function (request) {
list(body=paste(
"Hello,",
if(substr(request$QUERY_STRING,1,6)=="?name=")
substr(request$QUERY_STRING,7,40) else "World",
sep=" "))
}
)
routes <- list(
'/api/HttpExample' = hello_handler
)
router <- function (routes, request) {
if (!request$PATH_INFO %in% names(routes)) {
return(http_not_found)
}
path_handler <- routes[[request$PATH_INFO]]
if (!request$REQUEST_METHOD %in% names(path_handler)) {
return(http_method_not_allowed)
}
method_handler <- path_handler[[request$REQUEST_METHOD]]
return(method_handler(request))
}
app <- list(
call = function (request) {
response <- router(routes, request)
if (!'status' %in% names(response)) {
response$status <- 200
}
if (!'headers' %in% names(response)) {
response$headers <- list()
}
if (!'Content-Type' %in% names(response$headers)) {
response$headers[['Content-Type']] <- 'text/plain'
}
return(response)
}
)
cat(paste0("Server listening on :", PORT, "...\n"))
runServer("0.0.0.0", PORT, app)
Ändern Sie in host.json den Abschnitt , um den Startbefehl des benutzerdefinierten Handlers zu konfigurieren.
"customHandler": {
"description": {
"defaultExecutablePath": "Rscript",
"arguments": [
"handler.R"
]
},
"enableForwardingHttpRequest": true
}
Starten Sie zum lokalen Testen der Funktion den lokalen Azure Functions-Runtimehost im Stammverzeichnis des Projektordners.
func start
func start
npm install
npm start
mvn clean package
mvn azure-functions:run
R -e "install.packages('httpuv', repos='http://cran.rstudio.com/')"
func start
Navigieren Sie zu http://localhost:7071/api/HttpExample?name=Functions, wenn in der Ausgabe der HttpExample-Endpunkt angezeigt wird. Im Browser muss eine Begrüßungsnachricht mit Functions (dem für den Abfrageparameter name angegebenen Wert) angezeigt werden.
Drücken Sie STRG+C, um den Host zu beenden.
Erstellen und lokales Testen des Containerimages
(Optional) Untersuchen Sie die Dockerfile im Stammverzeichnis des Projektordners. In der Dockerfile wird die Umgebung beschrieben, die zum Ausführen der Funktions-App unter Linux benötigt wird. Die vollständige Liste mit den unterstützten Basisimages für Azure Functions finden Sie auf der Seite mit Azure Functions-Basisimages.
Untersuchen Sie das Dockerfile im Stammverzeichnis des Projektordners. In der Dockerfile wird die Umgebung beschrieben, die zum Ausführen der Funktions-App unter Linux benötigt wird. Von Anwendungen mit benutzerdefiniertem Handler wird das Image mcr.microsoft.com/azure-functions/dotnet:3.0-appservice als Grundlage verwendet.
Ändern Sie die Dockerfile, um R zu installieren. Ersetzen Sie den Inhalt der Dockerfile durch folgenden Code:
FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
RUN apt update && \
apt install -y r-base && \
R -e "install.packages('httpuv', repos='http://cran.rstudio.com/')"
COPY . /home/site/wwwroot
Führen Sie im Stammprojektordner den Befehl docker build aus, und geben Sie einen Namen (azurefunctionsimage) und ein Tag (v1.0.0) an. Ersetzen Sie <DOCKER_ID> durch Ihre Docker Hub-Konto-ID. Dieser Befehl erstellt das Docker-Image für den Container.
docker build --tag <DOCKER_ID>/azurefunctionsimage:v1.0.0 .
Nachdem der Befehl abgeschlossen wurde, können Sie den neuen Container lokal ausführen.
Führen Sie das Image zum Testen des Builds in einem lokalen Container aus, indem Sie den Befehl docker run verwenden, erneut <docker_id> durch Ihre Docker Hub-Konto-ID ersetzen und das Portargument -p 8080:80 hinzufügen:
docker run -p 8080:80 -it <docker_id>/azurefunctionsimage:v1.0.0
Nachdem das Image im lokalen Container gestartet wurde, navigieren Sie zu http://localhost:8080/api/HttpExample?name=Functions, das dieselbe Begrüßungsnachricht wie zuvor anzeigen muss. Da die von Ihnen erstellte von HTTP ausgelöste Funktion anonyme Autorisierung verwendet, können Sie die im Container ausgeführte Funktion aufrufen, ohne einen Zugriffsschlüssel abrufen zu müssen. Weitere Informationen finden Sie unter Autorisierungsschlüssel.
Nachdem das Image im lokalen Container gestartet wurde, navigieren Sie zu http://localhost:8080/api/HttpExample?name=Functions, das dieselbe Begrüßungsnachricht wie zuvor anzeigen muss. Da die von Ihnen erstellte von HTTP ausgelöste Funktion anonyme Autorisierung verwendet, können Sie die im Container ausgeführte Funktion aufrufen, ohne einen Zugriffsschlüssel abrufen zu müssen. Weitere Informationen finden Sie unter Autorisierungsschlüssel.
Drücken Sie nach der Überprüfung der Funktions-App im Container auf STRG+C, um Docker zu beenden.
Übertragen des Images per Pushvorgang auf Docker Hub
Docker Hub ist eine Containerregistrierung, mit der Images gehostet und Image- und Containerdienste bereitgestellt werden. Um Ihr Image freizugeben (umfasst auch die Bereitstellung in Azure), müssen Sie es per Pushvorgang in eine Registrierung übertragen.
Wenn Sie sich noch nicht bei Docker angemeldet haben, können Sie dies durchführen, indem Sie den Befehl docker login verwenden und
<docker_id>durch Ihre Docker Hub-Konto-ID ersetzen. Mit diesem Befehl werden Sie zum Eingeben Ihres Benutzernamens und Kennworts aufgefordert. Mit einer Meldung der Art „Anmeldung erfolgreich“ wird bestätigt, dass die Anmeldung erfolgreich war.docker loginÜbertragen Sie das Image nach dem Anmelden per Pushvorgang an Docker Hub, indem Sie den Befehl docker push verwenden und
<docker_id>wieder durch Ihre Docker Hub-Konto-ID ersetzen.docker push <docker_id>/azurefunctionsimage:v1.0.0Je nach Netzwerkgeschwindigkeit kann der erste Pushvorgang für das Image einige Minuten dauern (das Pushen der nachfolgenden Änderungen geht deutlich schneller). Während Sie warten, können Sie mit dem nächsten Abschnitt fortfahren und Azure-Ressourcen in einem anderen Terminal erstellen.
Erstellen von unterstützenden Azure-Ressourcen für Ihre Funktion
Zum Bereitstellen Ihres Funktionscodes in Azure müssen Sie drei Ressourcen erstellen:
- Eine Ressourcengruppe, bei der es sich um einen logischen Container für verwandte Ressourcen handelt.
- Ein Speicherkonto, das verwendet wird, um den Status und andere Informationen zu Ihren Funktionen zu verwalten.
- Eine Funktions-App, die als Umgebung zum Ausführen Ihres Funktionscodes dient. Eine Funktions-App ist Ihrem lokalen Funktionsprojekt zugeordnet und ermöglicht Ihnen das Gruppieren von Funktionen als logische Einheit, um die Verwaltung, Bereitstellung und Freigabe von Ressourcen zu vereinfachen.
Verwenden Sie die folgenden Befehle, um diese Elemente zu erstellen. Sowohl die Azure CLI als auch PowerShell werden unterstützt.
Melden Sie sich bei Azure an, falls dies noch nicht geschehen ist.
az loginMit dem Befehl az login werden Sie bei Ihrem Azure-Konto angemeldet.
Erstellen Sie eine Ressourcengruppe mit dem Namen
AzureFunctionsContainers-rgin der ausgewählten Region.az group create --name AzureFunctionsContainers-rg --location <REGION>Mit dem Befehl az group create wird eine Ressourcengruppe erstellt. Ersetzen Sie im Befehl oben
<REGION>durch eine Region in Ihrer Nähe, indem Sie einen verfügbaren Regionscode verwenden, der mit dem Befehl<REGION>zurückgegeben wird.Erstellen Sie in Ihrer Ressourcengruppe und Region ein universelles Speicherkonto.
az storage account create --name <STORAGE_NAME> --location <REGION> --resource-group AzureFunctionsContainers-rg --sku Standard_LRSDer Befehl az storage account create erstellt ein Speicherkonto.
Ersetzen Sie im vorherigen Beispiel
<STORAGE_NAME>durch einen Namen, der für Sie geeignet und eindeutig in Azure Storage ist. Storage-Namen dürfen nur 3 bis 24 Zeichen lang sein und müssen ausschließlich Ziffern und Kleinbuchstaben enthalten. MitStandard_LRSwird ein universelles Konto angegeben, das von Functions unterstützt wird.Verwenden Sie den Befehl, um einen Premium-Plan für Azure Functions mit dem Namen
myPremiumPlanin der PreisstufemyPremiumPlan(--sku EP1) in Ihrer<REGION>und in einem Linux-Container (--is-linux) zu erstellen.az functionapp plan create --resource-group AzureFunctionsContainers-rg --name myPremiumPlan --location <REGION> --number-of-workers 1 --sku EP1 --is-linuxWir verwenden hier den Premium-Plan, der je nach Bedarf skaliert werden kann. Weitere Informationen zum Hosting finden Sie unter Vergleich von Hostingplänen für Azure Functions. Weitere Informationen zum Berechnen von Kosten finden Sie auf der Seite „Azure Functions – Preise“.
Darüber hinaus wird mit dem Befehl auch eine zugeordnete Azure Application Insights-Instanz in derselben Ressourcengruppe bereitgestellt, mit der Sie Ihre Funktions-App überwachen und Protokolle anzeigen können. Weitere Informationen finden Sie unter Überwachen von Azure Functions. Für die Instanz fallen erst Kosten an, wenn Sie sie aktivieren.
Erstellen und Konfigurieren einer Funktions-App in Azure mit dem Image
Mit einer Funktions-App in Azure wird die Ausführung der Funktionen Ihres Hostingplans verwaltet. In diesem Abschnitt verwenden Sie die Azure-Ressourcen aus dem vorherigen Abschnitt, um eine Funktions-App aus einem Image unter Docker Hub zu erstellen und mit einer Verbindungszeichenfolge für Azure Storage zu konfigurieren.
Erstellen Sie mit dem folgenden Befehl eine Funktions-App:
az functionapp create --name <APP_NAME> --storage-account <STORAGE_NAME> --resource-group AzureFunctionsContainers-rg --plan myPremiumPlan --deployment-container-image-name <DOCKER_ID>/azurefunctionsimage:v1.0.0Im Befehl az functionapp create gibt der Parameter deployment-container-image-name das für die Funktions-App zu verwendende Image an. Sie können den Befehl az functionapp config container show verwenden, um Informationen zum für die Bereitstellung verwendeten Image anzuzeigen. Darüber hinaus können Sie den Befehl az functionapp config container set nutzen, um ein anderes Image für die Bereitstellung zu verwenden.
Hinweis
Wenn Sie eine benutzerdefinierte Containerregistrierung verwenden, verweist der Parameter deployment-container-image-name auf die Registrierungs-URL.
Ersetzen Sie in diesem Beispiel
<STORAGE_NAME>durch den Namen, den Sie im vorherigen Abschnitt für das Speicherkonto verwendet haben. Ersetzen Sie außerdem<APP_NAME>durch einen für Sie geeigneten global eindeutigen Namen und<DOCKER_ID>durch Ihre Docker Hub-Konto-ID. Verwenden Sie bei der Bereitstellung aus einer benutzerdefinierten Containerregistrierung den Parameterdeployment-container-image-name, um die URL der Registrierung anzugeben.Tipp
Sie können die
DisableColor-Einstellung in der host.json-Datei verwenden, um zu verhindern, dass ANSI-Steuerzeichen in die Containerprotokolle geschrieben werden.Verwenden Sie den folgenden Befehl, um die Verbindungszeichenfolge für das von Ihnen erstellte Speicherkonto abzurufen:
az storage account show-connection-string --resource-group AzureFunctionsContainers-rg --name <STORAGE_NAME> --query connectionString --output tsvDie Verbindungszeichenfolge für das Speicherkonto wird mit dem Befehl az storage account show-connection-string zurückgegeben.
Ersetzen Sie
<STORAGE_NAME>durch den Namen des Speicherkontos, das Sie früher erstellt haben.Verwenden Sie den folgenden Befehl, um der Funktions-App die Einstellung hinzuzufügen:
az functionapp config appsettings set --name <APP_NAME> --resource-group AzureFunctionsContainers-rg --settings AzureWebJobsStorage=<CONNECTION_STRING>Der Befehl az functionapp config appsettings set erstellt die Einstellung.
Ersetzen Sie in diesem Befehl
<APP_NAME>durch den Namen Ihrer Funktions-App und<CONNECTION_STRING>durch die Verbindungszeichenfolge aus dem vorherigen Schritt. Die Verbindung sollte eine lang codierte Zeichenfolge sein, die mitDefaultEndpointProtocol=beginnt.Die Funktion kann diese Verbindungszeichenfolge jetzt verwenden, um auf das Speicherkonto zuzugreifen.
Hinweis
Wenn Sie Ihr benutzerdefiniertes Image in einer privaten Containerregistrierung veröffentlichen, müssen Sie stattdessen Umgebungsvariablen in der Dockerfile für die Verbindungszeichenfolge verwenden. Weitere Informationen finden Sie unter der ENV-Anweisung. Sie müssen auch die Variablen DOCKER_REGISTRY_SERVER_USERNAME und DOCKER_REGISTRY_SERVER_PASSWORD festlegen. Zum Verwenden der Werte müssen Sie das Image neu erstellen, in die Registrierung pushen und anschließend die Funktions-App in Azure neu starten.
Überprüfen Ihrer Funktionen in Azure
Nachdem das Image in Ihrer Funktions-App in Azure bereitgestellt wurde, können Sie die Funktion nun wie zuvor über HTTP-Anforderungen aufrufen. Navigieren Sie in Ihrem Browser zur folgenden URL:
https://<APP_NAME>.azurewebsites.net/api/HttpExample?name=Functions
https://<APP_NAME>.azurewebsites.net/api/HttpExample?name=Functions
Ersetzen Sie <APP_NAME> durch den Namen der Funktions-App. Wenn Sie zu dieser URL navigieren, muss der Browser eine ähnliche Ausgabe anzeigen wie bei der lokalen Ausführung der Funktion.
Aktivieren von Continuous Deployment in Azure
Sie können Azure Functions aktivieren, um Ihre Bereitstellung eines Images jeweils automatisch zu aktualisieren, wenn Sie das Bild in der Registrierung aktualisieren.
Verwenden Sie den folgenden Befehl, um Continuous Deployment zu aktivieren und die Webhook-URL abzurufen:
az functionapp deployment container config --enable-cd --query CI_CD_URL --output tsv --name <APP_NAME> --resource-group AzureFunctionsContainers-rgDer Befehl az functionapp deployment container config aktiviert Continuous Deployment und gibt die Webhook-URL der Bereitstellung zurück. Sie können diese URL später jederzeit abrufen, indem Sie den Befehl az functionapp deployment container show-cd-url verwenden.
Ersetzen Sie wie zuvor
<APP_NAME>durch den Namen Ihrer Funktions-App.Kopieren Sie die Webhook-URL der Bereitstellung in die Zwischenablage.
Öffnen Sie Docker Hub, melden Sie sich an, und wählen Sie in der Navigationsleiste die Option Repositorys aus. Suchen Sie nach dem Image, und wählen Sie es aus. Wählen Sie die Registerkarte Webhooks aus, geben Sie einen Webhooknamen ein, fügen Sie unter Webhook-URL Ihre URL ein, und wählen Sie Erstellen aus.
Nachdem der Webhook festgelegt wurde, wird Ihr Image von Azure Functions jeweils erneut bereitgestellt, wenn Sie es in Docker Hub aktualisieren.
Aktivieren von SSH-Verbindungen
SSH ermöglicht die sichere Kommunikation zwischen einem Container und einem Client. Wenn SSH aktiviert ist, können Sie mithilfe der erweiterten App Service-Tools (Kudu) eine Verbindung mit Ihrem Container herstellen. Azure Functions stellt ein Basisimage bereit, für das SSH bereits aktiviert ist, um das Herstellen einer Verbindung mit Ihrem Container per SSH zu vereinfachen. Sie müssen nur Ihre Dockerfile bearbeiten und dann das Image neu erstellen und bereitstellen. Anschließend können Sie mit den Advanced Tools (Kudu) eine Verbindung mit dem Container herstellen.
Fügen Sie in Ihrer Dockerfile die Zeichenfolge
-appservicedem Basisimage in IhrerFROM-Anweisung an.FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appserviceFROM mcr.microsoft.com/azure-functions/node:2.0-appserviceFROM mcr.microsoft.com/azure-functions/powershell:2.0-appserviceFROM mcr.microsoft.com/azure-functions/python:2.0-python3.7-appserviceFROM mcr.microsoft.com/azure-functions/node:2.0-appserviceErstellen Sie das Image neu, indem Sie den Befehl
docker buildverwenden und<docker_id>durch Ihre Docker Hub-Konto-ID ersetzen.docker build --tag <docker_id>/azurefunctionsimage:v1.0.0 .Pushen Sie das aktualisierte Image an Docker Hub. Dies sollte deutlich weniger Zeit als der erste Pushvorgang in Anspruch nehmen. Nur die aktualisierten Segmente des Images müssen jetzt hochgeladen werden.
docker push <docker_id>/azurefunctionsimage:v1.0.0Azure Functions stellt das Image automatisch für Ihre Funktions-App bereit. Der Prozess dauert weniger als eine Minute.
Öffnen Sie in einem Browser
https://<app_name>.scm.azurewebsites.net/, und ersetzen Sie<app_name>durch Ihren eindeutigen Namen. Diese URL ist der Advanced Tools-Endpunkt (Kudu) für Ihren Funktions-App-Container.Melden Sie sich an Ihrem Azure-Konto an, und wählen Sie SSH aus, um eine Verbindung mit dem Container herzustellen. Die Verbindungsherstellung könnte etwas dauern, falls das Containerimage von Azure noch aktualisiert wird.
Nachdem eine Verbindung mit Ihrem Container hergestellt wurde, können Sie den Befehl
topausführen, um die derzeit ausgeführten Prozesse anzuzeigen.
Schreiben in Azure Queue Storage
Mit Azure Functions können Sie Ihre Funktionen mit anderen Azure-Diensten und -Ressourcen verbinden, ohne dass Sie eigenen Integrationscode schreiben müssen. Diese Bindungen, die sowohl Eingabe als auch Ausgabe darstellen, werden innerhalb der Funktionsdefinition deklariert. Daten von Bindungen werden der Funktion als Parameter bereitgestellt. Ein Trigger ist ein spezieller Typ von Eingabebindung. Eine Funktion hat zwar nur einen Trigger, kann aber mehrere Ein- und Ausgabebindungen haben. Weitere Informationen finden Sie unter Konzepte für Azure Functions-Trigger und -Bindungen.
In diesem Abschnitt wird gezeigt, wie Sie Ihre Funktion in eine Azure Queue Storage-Instanz integrieren. Die Ausgabebindung, die Sie dieser Funktion hinzufügen, schreibt Daten aus einer HTTP-Anforderung in eine Nachricht in der Warteschlange.
Abrufen der Azure Storage-Verbindungszeichenfolge
Zuvor haben Sie ein Azure Storage-Konto erstellt, das von der Funktions-App verwendet werden kann. Die Verbindungszeichenfolge für dieses Konto wird sicher in App-Einstellungen in Azure gespeichert. Indem Sie die Einstellung in die Datei local.settings.json herunterladen, können Sie diese Verbindung zum Schreiben in eine Storage-Warteschlange unter demselben Konto verwenden, wenn Sie die Funktion lokal ausführen.
Führen Sie im Stammverzeichnis des Projekts den folgenden Befehl aus, indem Sie
<APP_NAME>durch den Namen Ihrer Funktions-App aus der vorherigen Schritt ersetzen. Mit diesem Befehl werden alle vorhandenen Werte in der Datei überschrieben.func azure functionapp fetch-app-settings <APP_NAME>Öffnen Sie die Datei local.settings.json, und suchen Sie nach dem Wert mit dem Namen
AzureWebJobsStorage. Dies ist die Verbindungszeichenfolge des Storage-Kontos. Sie verwenden den NamenAzureWebJobsStorageund die Verbindungszeichenfolge noch in anderen Abschnitten dieses Artikels.
Wichtig
Da die Datei local.settings.json aus Azure heruntergeladene Geheimnisse enthält, schließen Sie diese Datei stets von der Quellcodeverwaltung aus. In der GITIGNORE-Datei, die für ein lokales Funktionsprojekt erstellt wird, ist die Datei standardmäßig ausgeschlossen.
Registrieren von Bindungserweiterungen
Mit Ausnahme von HTTP- und Timertriggern werden Bindungen als Erweiterungspakete implementiert. Führen Sie den folgenden dotnet add package-Befehl im Terminalfenster aus, um Ihrem Projekt das Storage-Erweiterungspaket hinzuzufügen.
dotnet add package Microsoft.Azure.WebJobs.Extensions.Storage
Dann können Sie dem Projekt die Storage-Ausgabebindung hinzufügen.
Hinzufügen einer Ausgabebindungsdefinition zur Funktion
Eine Funktion kann zwar nur über einen Trigger verfügen, aber über mehrere Eingabe- und Ausgabebindungen. Hiermit können Sie eine Verbindung mit anderen Azure-Diensten und -Ressourcen herstellen, ohne benutzerdefinierten Integrationscode zu schreiben.
Sie deklarieren diese Bindungen in der Datei function.json in Ihrem Funktionsordner. In der vorherigen Schnellstartanleitung hat die Datei function.json im Ordner HttpExample zwei Bindungen in der Sammlung enthalten:
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "Response"
}
]
Jede Bindung verfügt mindestens über einen Typ, eine Richtung und einen Namen. Im obigen Beispiel hat die erste Bindung den Typ httpTrigger und die Richtung in. Für die Richtung in wird mit name der Name eines Eingabeparameters angegeben, der an die Funktion gesendet wird, wenn sie vom Trigger aufgerufen wird.
Die zweite Bindung in der Sammlung hat den Namen res. Diese http-Bindung ist eine Ausgabebindung (out), die zum Schreiben der HTTP-Antwort verwendet wird.
Fügen Sie zum Schreiben in eine Azure Storage-Warteschlange aus dieser Funktion eine out-Bindung vom Typ queue mit dem Namen msg hinzu. Dies ist im Code unten veranschaulicht:
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "queue",
"direction": "out",
"name": "msg",
"queueName": "outqueue",
"connection": "AzureWebJobsStorage"
}
]
}
Die zweite Bindung der Sammlung hat den Typ http mit der Richtung out. In diesem Fall wird mit dem speziellen name-Element von $return angegeben, dass für diese Bindung der Rückgabewert der Funktion verwendet wird, anstatt einen Eingabeparameter bereitzustellen.
Fügen Sie zum Schreiben in eine Azure Storage-Warteschlange aus dieser Funktion eine out-Bindung vom Typ queue mit dem Namen msg hinzu. Dies ist im Code unten veranschaulicht:
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
},
{
"type": "queue",
"direction": "out",
"name": "msg",
"queueName": "outqueue",
"connection": "AzureWebJobsStorage"
}
]
Die zweite Bindung in der Sammlung hat den Namen res. Diese http-Bindung ist eine Ausgabebindung (out), die zum Schreiben der HTTP-Antwort verwendet wird.
Fügen Sie zum Schreiben in eine Azure Storage-Warteschlange aus dieser Funktion eine out-Bindung vom Typ queue mit dem Namen msg hinzu. Dies ist im Code unten veranschaulicht:
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "Response"
},
{
"type": "queue",
"direction": "out",
"name": "msg",
"queueName": "outqueue",
"connection": "AzureWebJobsStorage"
}
]
}
In diesem Fall wird msg als Ausgabeargument für die Funktion bereitgestellt. Für einen queue-Typ müssen Sie auch den Namen der Warteschlange in queueName und den Namen (name) der Azure Storage-Verbindung (aus der Datei local.settings.json) in connection angeben.
In einem C#-Projekt werden die Bindungen als Bindungsattribute der Funktionsmethode definiert. Bestimmte Definitionen hängen davon ab, ob Ihre App In-Process (C#-Klassenbibliothek) oder in einem isolierten Prozess ausgeführt wird.
Öffnen Sie die Projektdatei HttpExample.cs, und fügen Sie der Definition der Methode den folgenden Parameter hinzu:
[Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg,
Der Parameter msg ist ein ICollector<T>-Typ und stellt eine Sammlung von Nachrichten dar, die in eine Ausgabebindung geschrieben werden, wenn die Funktion abgeschlossen wird. In diesem Fall ist die Ausgabe eine Speicherwarteschlange mit dem Namen outqueue. StorageAccountAttribute legt die Verbindungszeichenfolge für das Storage-Konto fest. Dieses Attribut gibt die Einstellung an, die die Verbindungszeichenfolge des Storage-Kontos enthält, und kann auf Klassen-, Methoden- oder Parameterebene angewandt werden. In diesem Fall können Sie StorageAccountAttribute weglassen, da Sie bereits das Standardspeicherkonto verwenden.
Die Run-Methodendefinition muss nun wie der folgende Code aussehen:
[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg,
ILogger log)
In einem Java-Projekt werden die Bindungen als Bindungsanmerkungen für die Funktionsmethode definiert. Die Datei function.json wird dann automatisch auf der Grundlage dieser Anmerkungen generiert.
Navigieren Sie zum Speicherort Ihres Funktionscodes (unter src/main/java), öffnen Sie die Projektdatei Function.java, und fügen Sie der Definition der Methode die folgenden Parameter hinzu:
@QueueOutput(name = "msg", queueName = "outqueue", connection = "AzureWebJobsStorage") OutputBinding<String> msg
Der msg-Parameter hat den Typ OutputBinding<T>, der eine Sammlung von Zeichenfolgen darstellt. Diese Zeichenfolgen werden als Nachrichten in eine Ausgabebindung geschrieben, wenn die Funktion abgeschlossen wird. In diesem Fall ist die Ausgabe eine Speicherwarteschlange mit dem Namen outqueue. Die Verbindungszeichenfolge für das Storage-Konto wird durch die Methode connection festgelegt. Übergeben Sie anstelle der eigentlichen Verbindungszeichenfolge die Anwendungseinstellung, die die Verbindungszeichenfolge für das Storage-Konto enthält.
Die Definition der Methode run muss nun wie im folgenden Beispiel aussehen:
@FunctionName("HttpTrigger-Java")
public HttpResponseMessage run(
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION)
HttpRequestMessage<Optional<String>> request,
@QueueOutput(name = "msg", queueName = "outqueue", connection = "AzureWebJobsStorage")
OutputBinding<String> msg, final ExecutionContext context) {
...
}
Hinzufügen von Code für die Verwendung der Ausgabebindung
Nachdem die Warteschlangenbindung definiert wurde, können Sie nun Ihre Funktion aktualisieren, um Nachrichten mithilfe des Bindungsparameters in die Warteschlange zu schreiben.
Aktualisieren Sie HttpExample\__init__.py so, dass es dem folgenden Code entspricht, indem Sie den Parameter msg zur Funktionsdefinition und msg.set(name) unter der if name:-Anweisung hinzufügen:
import logging
import azure.functions as func
def main(req: func.HttpRequest, msg: func.Out[func.QueueMessage]) -> str:
name = req.params.get('name')
if not name:
try:
req_body = req.get_json()
except ValueError:
pass
else:
name = req_body.get('name')
if name:
msg.set(name)
return func.HttpResponse(f"Hello {name}!")
else:
return func.HttpResponse(
"Please pass a name on the query string or in the request body",
status_code=400
)
Der Parameter msg ist eine Instanz der azure.functions.Out class. Die set-Methode schreibt eine Zeichenfolgennachricht in die Warteschlange. In diesem Fall ist dies der Name, der in der URL-Abfragezeichenfolge an die Funktion übergeben wird.
Fügen Sie Code hinzu, der das Ausgabebindungsobjekt msg für context.bindings verwendet, um eine Warteschlangennachricht zu erstellen. Fügen Sie diesen Code vor der context.res-Anweisung hinzu.
// Add a message to the Storage queue,
// which is the name passed to the function.
context.bindings.msg = (req.query.name || req.body.name);
Die Funktion muss nun wie folgt aussehen:
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.name || (req.body && req.body.name)) {
// Add a message to the Storage queue,
// which is the name passed to the function.
context.bindings.msg = (req.query.name || req.body.name);
context.res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + (req.query.name || req.body.name)
};
}
else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
};
Fügen Sie Code hinzu, der das Ausgabebindungsobjekt msg für context.bindings verwendet, um eine Warteschlangennachricht zu erstellen. Fügen Sie diesen Code vor der context.res-Anweisung hinzu.
context.bindings.msg = name;
Die Funktion muss nun wie folgt aussehen:
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
context.log('HTTP trigger function processed a request.');
const name = (req.query.name || (req.body && req.body.name));
if (name) {
// Add a message to the storage queue,
// which is the name passed to the function.
context.bindings.msg = name;
// Send a "hello" response.
context.res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + (req.query.name || req.body.name)
};
}
else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
};
export default httpTrigger;
Fügen Sie Code hinzu, der das Cmdlet Push-OutputBinding verwendet, um Text unter Verwendung der Ausgabebindung msg in die Warteschlange zu schreiben. Fügen Sie diesen Code hinzu, bevor Sie den OK-Status in der if-Anweisung festlegen.
$outputMsg = $name
Push-OutputBinding -name msg -Value $outputMsg
Die Funktion muss nun wie folgt aussehen:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
$name = $Request.Body.Name
}
if ($name) {
# Write the $name value to the queue,
# which is the name passed to the function.
$outputMsg = $name
Push-OutputBinding -name msg -Value $outputMsg
$status = [HttpStatusCode]::OK
$body = "Hello $name"
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please pass a name on the query string or in the request body."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $status
Body = $body
})
Fügen Sie Code hinzu, der das Ausgabebindungsobjekt msg verwendet, um eine Warteschlangennachricht zu erstellen. Fügen Sie diesen Code vor der Rückgabe der Methode hinzu.
if (!string.IsNullOrEmpty(name))
{
// Add a message to the output collection.
msg.Add(name);
}
Die Funktion muss nun wie folgt aussehen:
[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
if (!string.IsNullOrEmpty(name))
{
// Add a message to the output collection.
msg.Add(name);
}
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
Nun können Sie den neuen Parameter msg verwenden, um von Ihrem Funktionscode aus in die Ausgabebindung zu schreiben. Fügen Sie vor der Erfolgsantwort die folgende Codezeile hinzu, um der Ausgabebindung msg den Wert name hinzuzufügen:
msg.setValue(name);
Bei Verwendung einer Ausgabebindung müssen Sie weder den Azure Storage SDK-Code für die Authentifizierung verwenden noch einen Warteschlangenverweis abrufen oder Daten schreiben. Die Functions-Runtime und die Warteschlangenausgabebindung übernehmen diese Aufgaben für Sie.
Die Methode run muss nun wie im folgenden Beispiel aussehen:
public HttpResponseMessage run(
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
@QueueOutput(name = "msg", queueName = "outqueue",
connection = "AzureWebJobsStorage") OutputBinding<String> msg,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String query = request.getQueryParameters().get("name");
String name = request.getBody().orElse(query);
if (name == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Please pass a name on the query string or in the request body").build();
} else {
// Write the name to the message queue.
msg.setValue(name);
return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
}
}
Aktualisieren der Tests
Da der Archetyp auch eine Reihe von Tests erstellt, müssen Sie diese Tests aktualisieren, um den neuen Parameter msg in der Signatur der Methode run zu behandeln.
Navigieren Sie zum Speicherort Ihres Testcodes (unter src/test/java), öffnen Sie die Projektdatei Function.java, und ersetzen Sie die Codezeile unter //Invoke durch den folgenden Code:
@SuppressWarnings("unchecked")
final OutputBinding<String> msg = (OutputBinding<String>)mock(OutputBinding.class);
final HttpResponseMessage ret = new Function().run(req, msg, context);
Aktualisieren des Images in der Registrierung
Führen Sie im Stammordner erneut
docker buildaus, und aktualisieren Sie die Version im Tag dieses Mal aufv1.0.1. Ersetzen Sie<docker_id>wie zuvor durch Ihre Docker Hub-Konto-ID.docker build --tag <docker_id>/azurefunctionsimage:v1.0.1 .Übertragen Sie das aktualisierte Image per
docker pushzurück in das Repository.docker push <docker_id>/azurefunctionsimage:v1.0.1Da Sie Continuous Delivery konfiguriert haben, wird Ihre Funktions-App beim erneuten Aktualisieren des Images in der Registrierung automatisch in Azure aktualisiert.
Anzeigen der Nachricht in der Azure Storage-Warteschlange
Verwenden Sie in einem Browser dieselbe URL wie zuvor, um Ihre Funktion aufzurufen. Im Browser muss dieselbe Antwort wie zuvor angezeigt werden, da Sie diesen Teil des Funktionscodes nicht geändert haben. Aufgrund des hinzugefügten Codes wurde aber eine Nachricht in die Speicherwarteschlange outqueue geschrieben, indem der URL-Parameter name verwendet wurde.
Sie können die Warteschlange im Azure-Portal oder im Microsoft Azure Storage Explorer anzeigen. Sie haben auch die Möglichkeit, die Warteschlange per Azure CLI anzuzeigen. Dies ist in den folgenden Schritten beschrieben:
Öffnen Sie die Datei local.setting.json des Funktionsprojekts, und kopieren Sie den Wert der Verbindungszeichenfolge. Führen Sie in einem Terminal- oder Befehlsfenster den folgenden Befehl aus, um eine Umgebungsvariable namens
AZURE_STORAGE_CONNECTION_STRINGzu erstellen, und fügen Sie Ihre spezifische Verbindungszeichenfolge anstelle von<MY_CONNECTION_STRING>ein. (Die Verwendung dieser Umgebungsvariablen bewirkt, dass Sie die Verbindungszeichenfolge nicht für jeden weiteren Befehl per--connection-string-Argument angeben müssen.)export AZURE_STORAGE_CONNECTION_STRING="<MY_CONNECTION_STRING>"(Optional) Verwenden Sie den Befehl
az storage queue list, um die Storage-Warteschlangen in Ihrem Konto anzuzeigen. Die Ausgabe dieses Befehls muss eine Warteschlange mit dem Namenoutqueueenthalten. Sie wurde erstellt, als die Funktion ihre erste Nachricht in diese Warteschlange geschrieben hat.az storage queue list --output tsvVerwenden Sie den Befehl
az storage message get, um die Nachricht aus dieser Warteschlange zu lesen. Dies sollte der Wert sein, den Sie zuvor beim Testen der Funktion angegeben haben. Mit dem Befehl wird die erste Nachricht der Warteschlange gelesen und daraus entfernt.echo `echo $(az storage message get --queue-name outqueue -o tsv --query '[].{Message:content}') | base64 --decode`Da der Nachrichtentext im Base64-codierten Format gespeichert ist, muss die Nachricht vor dem Anzeigen decodiert werden. Nachdem Sie
az storage message getausgeführt haben, wird die Nachricht aus der Warteschlange entfernt. Falls inoutqueuenur eine Nachricht enthalten war, rufen Sie keine Nachricht ab, wenn Sie diesen Befehl zum zweiten Mal ausführen, sondern erhalten einen Fehler.
Bereinigen von Ressourcen
Wenn Sie mit Azure Functions weiterarbeiten und die in diesem Tutorial erstellten Ressourcen weiterhin nutzen möchten, können Sie sie alle beibehalten. Da Sie einen Premium-Plan für Azure Functions erstellt haben, fallen für Sie pro Tag ein oder zwei US-Dollar an laufenden Kosten an.
Löschen Sie zur Vermeidung laufender Kosten die Ressourcengruppe AzureFunctionsContainers-rg, um alle Ressourcen dieser Gruppe zu bereinigen:
az group delete --name AzureFunctionsContainers-rg