title | description | ms.date | ms.topic | ms.custom | zone_pivot_groups |
---|---|---|---|---|---|
Create Azure Functions on Linux using a custom image |
Learn how to create Azure Functions running on a custom Linux image. |
10/04/2022 |
tutorial |
devx-track-csharp, mvc, devx-track-python, devx-track-azurepowershell, devx-track-azurecli, devdivchpfy22 |
programming-languages-set-functions-full |
In this tutorial, you create and deploy your code to Azure Functions as a custom Docker container using a Linux base image. You typically use a custom image when your functions require a specific language version or have a specific dependency or configuration that isn't provided by the built-in image.
::: zone pivot="programming-language-other" Azure Functions supports any language or runtime using custom handlers. For some languages, such as the R programming language used in this tutorial, you need to install the runtime or more libraries as dependencies that require the use of a custom container. ::: zone-end
Deploying your function code in a custom Linux container requires Premium plan or a Dedicated (App Service) plan hosting. Completing this tutorial incurs costs of a few US dollars in your Azure account, which you can minimize by cleaning-up resources when you're done.
You can also use a default Azure App Service container as described in Create your first function hosted on Linux. Supported base images for Azure Functions are found in the Azure Functions base images repo.
In this tutorial, you learn how to:
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-java"
[!div class="checklist"]
- Create a function app and Dockerfile using the Azure Functions Core Tools.
- Build a custom image using Docker.
- Publish a custom image to a container registry.
- Create supporting resources in Azure for the function app.
- Deploy a function app from Docker Hub.
- Add application settings to the function app.
- Enable continuous deployment.
- Enable SSH connections to the container.
- Add a Queue storage output binding. ::: zone-end ::: zone pivot="programming-language-other" [!div class="checklist"]
- Create a function app and Dockerfile using the Azure Functions Core Tools.
- Build a custom image using Docker.
- Publish a custom image to a container registry.
- Create supporting resources in Azure for the function app.
- Deploy a function app from Docker Hub.
- Add application settings to the function app.
- Enable continuous deployment.
- Enable SSH connections to the container. ::: zone-end
You can follow this tutorial on any computer running Windows, macOS, or Linux.
[!INCLUDE functions-linux-custom-container-note]
[!INCLUDE functions-requirements-cli]
You also need to get a Docker and Docker ID:
[!INCLUDE functions-cli-create-venv]
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python"
In a terminal or command prompt, run the following command for your chosen language to create a function app project in the current folder:
::: zone-end
::: zone pivot="programming-language-csharp"
func init --worker-runtime dotnet --docker
func init --worker-runtime dotnet-isolated --docker
::: zone-end
::: zone pivot="programming-language-javascript"
func init --worker-runtime node --language javascript --docker
::: zone-end
::: zone pivot="programming-language-powershell"
func init --worker-runtime powershell --docker
::: zone-end
::: zone pivot="programming-language-python"
func init --worker-runtime python --docker
::: zone-end
::: zone pivot="programming-language-typescript"
func init --worker-runtime node --language typescript --docker
::: zone-end
::: zone pivot="programming-language-java"
In an empty folder, run the following command to generate the Functions project from a Maven archetype:
mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=8 -Ddocker
mvn archetype:generate "-DarchetypeGroupId=com.microsoft.azure" "-DarchetypeArtifactId=azure-functions-archetype" "-DjavaVersion=8" "-Ddocker"
mvn archetype:generate "-DarchetypeGroupId=com.microsoft.azure" "-DarchetypeArtifactId=azure-functions-archetype" "-DjavaVersion=8" "-Ddocker"
The -DjavaVersion
parameter tells the Functions runtime which version of Java to use. Use -DjavaVersion=11
if you want your functions to run on Java 11. When you don't specify -DjavaVersion
, Maven defaults to Java 8. For more information, see Java versions.
Important
The JAVA_HOME
environment variable must be set to the install location of the correct version of the JDK to complete this article.
Maven asks you for values needed to finish generating the project on deployment. Follow the prompts and provide the following information:
Prompt | Value | Description |
---|---|---|
groupId | com.fabrikam |
A value that uniquely identifies your project across all projects, following the package naming rules for Java. |
artifactId | fabrikam-functions |
A value that is the name of the jar, without a version number. |
version | 1.0-SNAPSHOT |
Select the default value. |
package | com.fabrikam.functions |
A value that is the Java package for the generated function code. Use the default. |
Type Y
or press Enter to confirm.
Maven creates the project files in a new folder named artifactId, which in this example is fabrikam-functions
.
::: zone-end
::: zone pivot="programming-language-other"
func init --worker-runtime custom --docker
::: zone-end
The --docker
option generates a Dockerfile for the project, which defines a suitable custom container for use with Azure Functions and the selected runtime.
::: zone pivot="programming-language-java"
Navigate into the project folder:
cd fabrikam-functions
::: zone-end
::: zone pivot="programming-language-csharp"
No changes are needed to the Dockerfile.
Open the Dockerfile and add the following lines after the first FROM
statement, if not already present:
# Build requires 3.1 SDK
COPY --from=mcr.microsoft.com/dotnet/core/sdk:3.1 /usr/share/dotnet /usr/share/dotnet
::: zone-end
::: zone pivot="programming-language-csharp"
Use the following command to add a function to your project, where the --name
argument is the unique name of your function and the --template
argument specifies the function's trigger. func new
creates a C# code file in your project.
func new --name HttpExample --template "HTTP trigger" --authlevel anonymous
::: zone-end
::: zone pivot="programming-language-other,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python"
Use the following command to add a function to your project, where the --name
argument is the unique name of your function and the --template
argument specifies the function's trigger. func new
creates a subfolder matching the function name that contains a configuration file named function.json.
func new --name HttpExample --template "HTTP trigger" --authlevel anonymous
::: zone-end
::: zone pivot="programming-language-other"
In a text editor, create a file in the project folder named handler.R. Add the following code as its content:
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)
In host.json, modify the customHandler
section to configure the custom handler's startup command.
"customHandler": {
"description": {
"defaultExecutablePath": "Rscript",
"arguments": [
"handler.R"
]
},
"enableForwardingHttpRequest": true
}
::: zone-end
To test the function locally, start the local Azure Functions runtime host in the root of the project folder. ::: zone pivot="programming-language-csharp"
func start
::: zone-end
::: zone pivot="programming-language-javascript,programming-language-powershell,programming-language-python"
func start
::: zone-end
::: zone pivot="programming-language-typescript"
npm install
npm start
::: zone-end
::: zone pivot="programming-language-java"
mvn clean package
mvn azure-functions:run
::: zone-end ::: zone pivot="programming-language-other"
R -e "install.packages('httpuv', repos='http://cran.rstudio.com/')"
func start
::: zone-end
After you see the HttpExample
endpoint written to the output, navigate to http://localhost:7071/api/HttpExample?name=Functions
. The browser must display a "hello" message that echoes back Functions
, the value supplied to the name
query parameter.
Press Ctrl+C to stop the host.
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-powershell,programming-language-python,programming-language-java,programming-language-typescript" (Optional) Examine the Dockerfile in the root of the project folder. The Dockerfile describes the required environment to run the function app on Linux. The complete list of supported base images for Azure Functions can be found in the Azure Functions base image page. ::: zone-end
::: zone pivot="programming-language-other"
Examine the Dockerfile in the root of the project folder. The Dockerfile describes the required environment to run the function app on Linux. Custom handler applications use the mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
image as its base.
Modify the Dockerfile to install R. Replace the contents of the Dockerfile with the following 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
::: zone-end
In the root project folder, run the docker build command, provide a name as azurefunctionsimage
, and tag as v1.0.0
. Replace <DOCKER_ID>
with your Docker Hub account ID. This command builds the Docker image for the container.
docker build --tag <DOCKER_ID>/azurefunctionsimage:v1.0.0 .
When the command completes, you can run the new container locally.
To test the build, run the image in a local container using the docker run command, replace <docker_id>
again with your Docker Hub account ID, and add the ports argument as -p 8080:80
:
docker run -p 8080:80 -it <docker_id>/azurefunctionsimage:v1.0.0
::: zone pivot="programming-language-csharp"
After the image starts in the local container, browse to http://localhost:8080/api/HttpExample?name=Functions
, which must display the same "hello" message as before. Because the HTTP triggered function you created uses anonymous authorization, you can call the function running in the container without having to obtain an access key. For more information, see authorization keys.
After the image starts in the local container, browse to http://localhost:8080/api/HttpExample
, which must display the same greeting message as before. Because the HTTP triggered function you created uses anonymous authorization, you can call the function running in the container without having to obtain an access key. For more information, see authorization keys.
::: zone-end
::: zone pivot="programming-language-java,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-other"
After the image starts in the local container, browse to http://localhost:8080/api/HttpExample?name=Functions
, which must display the same "hello" message as before. Because the HTTP triggered function you created uses anonymous authorization, you can call the function running in the container without having to obtain an access key. For more information, see authorization keys.
::: zone-end
After verifying the function app in the container, press Ctrl+C to stop the docker.
Docker Hub is a container registry that hosts images and provides image and container services. To share your image, which includes deploying to Azure, you must push it to a registry.
-
If you haven't already signed in to Docker, do so with the
docker login
command, replacing<docker_id>
with your Docker Hub account ID. This command prompts you for your username and password. A "sign in Succeeded" message confirms that you're signed in.docker login
-
After you've signed in, push the image to Docker Hub by using the
docker push
command, again replace the<docker_id>
with your Docker Hub account ID.docker push <docker_id>/azurefunctionsimage:v1.0.0
-
Depending on your network speed, pushing the image for the first time might take a few minutes (pushing subsequent changes is much faster). While you're waiting, you can proceed to the next section and create Azure resources in another terminal.
Before you can deploy your function code to Azure, you need to create three resources:
- A resource group, which is a logical container for related resources.
- A Storage account, which is used to maintain state and other information about your functions.
- A function app, which provides the environment for executing your function code. A function app maps to your local function project and lets you group functions as a logical unit for easier management, deployment, and sharing of resources.
Use the following commands to create these items. Both Azure CLI and PowerShell are supported.
-
If you haven't done already, sign in to Azure.
az login
The
az login
command signs you into your Azure account.Connect-AzAccount
The Connect-AzAccount cmdlet signs you into your Azure account.
-
Create a resource group named
AzureFunctionsContainers-rg
in your chosen region.az group create --name AzureFunctionsContainers-rg --location <REGION>
The
az group create
command creates a resource group. In the above command, replace<REGION>
with a region near you, using an available region code returned from the az account list-locations command.New-AzResourceGroup -Name AzureFunctionsContainers-rg -Location <REGION>
The
New-AzResourceGroup
command creates a resource group. You generally create your resource group and resources in a region near you, using an available region returned from theGet-AzLocation
cmdlet.
-
Create a general-purpose storage account in your resource group and region.
az storage account create --name <STORAGE_NAME> --location <REGION> --resource-group AzureFunctionsContainers-rg --sku Standard_LRS
The
az storage account create
command creates the storage account.New-AzStorageAccount -ResourceGroupName AzureFunctionsContainers-rg -Name <STORAGE_NAME> -SkuName Standard_LRS -Location <REGION>
The
New-AzStorageAccount
cmdlet creates the storage account.
In the previous example, replace
<STORAGE_NAME>
with a name that is appropriate to you and unique in Azure Storage. Storage names must contain 3 to 24 characters numbers and lowercase letters only.Standard_LRS
specifies a general-purpose account supported by Functions. -
Use the command to create a Premium plan for Azure Functions named
myPremiumPlan
in the Elastic Premium 1 pricing tier (--sku EP1
), in your<REGION>
, and in a Linux container (--is-linux
).az functionapp plan create --resource-group AzureFunctionsContainers-rg --name myPremiumPlan --location <REGION> --number-of-workers 1 --sku EP1 --is-linux
New-AzFunctionAppPlan -ResourceGroupName AzureFunctionsContainers-rg -Name MyPremiumPlan -Location <REGION> -Sku EP1 -WorkerType Linux
We use the Premium plan here, which can scale as needed. For more information about hosting, see Azure Functions hosting plans comparison. For more information on how to calculate costs, see the Functions pricing page.
The command also creates an associated Azure Application Insights instance in the same resource group, with which you can monitor your function app and view logs. For more information, see Monitor Azure Functions. The instance incurs no costs until you activate it.
A function app on Azure manages the execution of your functions in your hosting plan. In this section, you use the Azure resources from the previous section to create a function app from an image on Docker Hub and configure it with a connection string to Azure Storage.
-
Create a function app using the following command:
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.0
In the
az functionapp create
command, the deployment-container-image-name parameter specifies the image to use for the function app. You can use the az functionapp config container show command to view information about the image used for deployment. You can also use theaz functionapp config container set
command to deploy from a different image.[!NOTE]
If you're using a custom container registry, then the deployment-container-image-name parameter will refer to the registry URL.New-AzFunctionApp -Name <APP_NAME> -ResourceGroupName AzureFunctionsContainers-rg -PlanName myPremiumPlan -StorageAccount <STORAGE_NAME> -DockerImageName <DOCKER_ID>/azurefunctionsimage:v1.0.0
In this example, replace
<STORAGE_NAME>
with the name you used in the previous section for the storage account. Also, replace<APP_NAME>
with a globally unique name appropriate to you, and<DOCKER_ID>
with your Docker Hub account ID. When you're deploying from a custom container registry, use thedeployment-container-image-name
parameter to indicate the URL of the registry.[!TIP]
You can use theDisableColor
setting in the host.json file to prevent ANSI control characters from being written to the container logs. -
Use the following command to get the connection string for the storage account you created:
az storage account show-connection-string --resource-group AzureFunctionsContainers-rg --name <STORAGE_NAME> --query connectionString --output tsv
The connection string for the storage account is returned by using the
az storage account show-connection-string
command.$storage_name = "glengagtestdockerstorage" $key = (Get-AzStorageAccountKey -ResourceGroupName AzureFunctionsContainers-rg -Name $storage_name)[0].Value $string = "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=" + $storage_name + ";AccountKey=" + $key Write-Output($string)
The key returned by the
Get-AzStorageAccountKey
cmdlet is used to construct the connection string for the storage account.
Replace
<STORAGE_NAME>
with the name of the storage account you created earlier. -
Use the following command to add the setting to the function app:
az functionapp config appsettings set --name <APP_NAME> --resource-group AzureFunctionsContainers-rg --settings AzureWebJobsStorage=<CONNECTION_STRING>
The
az functionapp config appsettings set
command creates the setting.Update-AzFunctionAppSetting -Name <APP_NAME> -ResourceGroupName AzureFunctionsContainers-rg -AppSetting @{"AzureWebJobsStorage"="<CONNECTION_STRING>"}
The
Update-AzFunctionAppSetting
cmdlet creates the setting.
In this command, replace
<APP_NAME>
with the name of your function app and<CONNECTION_STRING>
with the connection string from the previous step. The connection should be a long encoded string that begins withDefaultEndpointProtocol=
. -
The function can now use this connection string to access the storage account.
Note
If you publish your custom image to a private container registry, you must also set the DOCKER_REGISTRY_SERVER_USERNAME
and DOCKER_REGISTRY_SERVER_PASSWORD
variables. For more information, see Custom containers in the App Service settings reference.
With the image deployed to your function app in Azure, you can now invoke the function as before through HTTP requests. In your browser, navigate to the following URL:
::: zone pivot="programming-language-java,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-other"
https://<APP_NAME>.azurewebsites.net/api/HttpExample?name=Functions
::: zone-end
::: zone pivot="programming-language-csharp"
https://<APP_NAME>.azurewebsites.net/api/HttpExample?name=Functions
https://<APP_NAME>.azurewebsites.net/api/HttpExample
:::zone-end
Replace <APP_NAME>
with the name of your function app. When you navigate to this URL, the browser must display similar output as when you ran the function locally.
You can enable Azure Functions to automatically update your deployment of an image whenever you update the image in the registry.
-
Use the following command to enable continuous deployment and to get the webhook URL:
az functionapp deployment container config --enable-cd --query CI_CD_URL --output tsv --name <APP_NAME> --resource-group AzureFunctionsContainers-rg
The
az functionapp deployment container config
command enables continuous deployment and returns the deployment webhook URL. You can retrieve this URL at any later time by using theaz functionapp deployment container show-cd-url
command.Update-AzFunctionAppSetting -Name <APP_NAME> -ResourceGroupName AzureFunctionsContainers-rg -AppSetting @{"DOCKER_ENABLE_CI" = "true"} Get-AzWebAppContainerContinuousDeploymentUrl -Name <APP_NAME> -ResourceGroupName AzureFunctionsContainers-rg
The
DOCKER_ENABLE_CI
application setting controls whether continuous deployment is enabled from the container repository. TheGet-AzWebAppContainerContinuousDeploymentUrl
cmdlet returns the URL of the deployment webhook.
As before, replace
<APP_NAME>
with your function app name. -
Copy the deployment webhook URL to the clipboard.
-
Open Docker Hub, sign in, and select Repositories on the navigation bar. Locate and select the image, select the Webhooks tab, specify a Webhook name, paste your URL in Webhook URL, and then select Create.
:::image type="content" source="./media/functions-create-function-linux-custom-image/dockerhub-set-continuous-webhook.png" alt-text="Screenshot showing how to add the webhook in your Docker Hub window.":::
-
With the webhook set, Azure Functions redeploys your image whenever you update it in Docker Hub.
SSH enables secure communication between a container and a client. With SSH enabled, you can connect to your container using App Service Advanced Tools (Kudu). For easy connection to your container using SSH, Azure Functions provides a base image that has SSH already enabled. You only need to edit your Dockerfile, then rebuild, and redeploy the image. You can then connect to the container through the Advanced Tools (Kudu).
-
In your Dockerfile, append the string
-appservice
to the base image in yourFROM
instruction.::: zone pivot="programming-language-csharp"
FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
::: zone-end
::: zone pivot="programming-language-javascript"
FROM mcr.microsoft.com/azure-functions/node:2.0-appservice
::: zone-end
::: zone pivot="programming-language-powershell"
FROM mcr.microsoft.com/azure-functions/powershell:2.0-appservice
::: zone-end
::: zone pivot="programming-language-python"
FROM mcr.microsoft.com/azure-functions/python:2.0-python3.7-appservice
::: zone-end
::: zone pivot="programming-language-typescript"
FROM mcr.microsoft.com/azure-functions/node:2.0-appservice
::: zone-end
-
Rebuild the image by using the
docker build
command again, replace the<docker_id>
with your Docker Hub account ID.docker build --tag <docker_id>/azurefunctionsimage:v1.0.0 .
-
Push the updated image to Docker Hub, which should take considerably less time than the first push. Only the updated segments of the image need to be uploaded now.
docker push <docker_id>/azurefunctionsimage:v1.0.0
-
Azure Functions automatically redeploys the image to your functions app; the process takes place in less than a minute.
-
In a browser, open
https://<app_name>.scm.azurewebsites.net/
and replace<app_name>
with your unique name. This URL is the Advanced Tools (Kudu) endpoint for your function app container. -
Sign in to your Azure account, and then select the SSH to establish a connection with the container. Connecting might take a few moments if Azure is still updating the container image.
-
After a connection is established with your container, run the
top
command to view the currently running processes.:::image type="content" source="media/functions-create-function-linux-custom-image/linux-custom-kudu-ssh-top.png" alt-text="Screenshot that shows Linux top command running in an SSH session.":::
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-java"
Azure Functions lets you connect your functions to other Azure services and resources without having to write your own integration code. These bindings, which represent both input and output, are declared within the function definition. Data from bindings is provided to the function as parameters. A trigger is a special type of input binding. Although a function has only one trigger, it can have multiple input and output bindings. For more information, see Azure Functions triggers and bindings concepts.
This section shows you how to integrate your function with an Azure Queue Storage. The output binding that you add to this function writes data from an HTTP request to a message in the queue.
[!INCLUDE functions-cli-get-storage-connection] ::: zone-end
::: zone pivot="programming-language-csharp"
::: zone-end
[!INCLUDE functions-register-storage-binding-extension-csharp]
[!INCLUDE functions-add-output-binding-cli]
::: zone pivot="programming-language-csharp"
[!INCLUDE functions-add-storage-binding-csharp-library]
::: zone-end
::: zone pivot="programming-language-java"
[!INCLUDE functions-add-output-binding-java-cli]
::: zone-end
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-java"
With the queue binding defined, you can now update your function to write messages to the queue using the binding parameter. ::: zone-end
::: zone pivot="programming-language-python" [!INCLUDE functions-add-output-binding-python] ::: zone-end
::: zone pivot="programming-language-javascript"
[!INCLUDE functions-add-output-binding-js]
::: zone-end
::: zone pivot="programming-language-typescript"
[!INCLUDE functions-add-output-binding-ts]
::: zone-end
::: zone pivot="programming-language-powershell"
[!INCLUDE functions-add-output-binding-powershell]
::: zone-end
::: zone pivot="programming-language-csharp"
[!INCLUDE functions-add-storage-binding-csharp-library-code]
::: zone-end
::: zone pivot="programming-language-java" [!INCLUDE functions-add-output-binding-java-code]
[!INCLUDE functions-add-output-binding-java-test-cli] ::: zone-end
::: zone pivot="programming-language-csharp,programming-language-javascript,programming-language-typescript,programming-language-powershell,programming-language-python,programming-language-java"
-
In the root folder, run
docker build
again, and this time update the version in the tag tov1.0.1
. As before, replace<docker_id>
with your Docker Hub account ID.docker build --tag <docker_id>/azurefunctionsimage:v1.0.1 .
-
Push the updated image back to the repository with
docker push
.docker push <docker_id>/azurefunctionsimage:v1.0.1
-
Because you configured continuous delivery, updating the image in the registry again automatically updates your function app in Azure.
In a browser, use the same URL as before to invoke your function. The browser must display the same response as before, because you didn't modify that part of the function code. The added code, however, wrote a message using the name
URL parameter to the outqueue
storage queue.
[!INCLUDE functions-add-output-binding-view-queue-cli]
::: zone-end
If you want to continue working with Azure Function using the resources you created in this tutorial, you can leave all those resources in place. Because you created a Premium Plan for Azure Functions, you'll incur one or two USD per day in ongoing costs.
To avoid ongoing costs, delete the AzureFunctionsContainers-rg
resource group to clean up all the resources in that group:
az group delete --name AzureFunctionsContainers-rg