/azure-functions-on-container-apps

Docs , samples and issues for Azure Functions on Azure Container Apps

MIT LicenseMIT

Azure Functions on Azure Container Apps (Public Preview) image

Azure functions on container apps helps developers to quickly build event driven, cloud native apps, with the flexibility to run functions along with other microservices, APIs, websites, workflows or any container hosted programs. You can leverage functions programming model and write code using your preferred programming language or framework that Azure functions supports . You will also get the triggers, bindings and get that first class event driven, cloud native experience. Azure Functions is running on the platform service powered by Azure Container Apps to run microservices in containers without managing infrastructure. Container Apps Environment is built on a foundation of powerful open-source technology. Behind the scenes, every container app runs on Azure Kubernetes Service, enables to build microservices with full support for Distributed Application Runtime (Dapr) and scale dynamically based on HTTP traffic or events powered by Kubernetes Event-Driven Autoscaling (KEDA).

Azure Functions on Container Apps Environment offers Azure client tools and DevOps tooling to provide seamless experience. This means simplified client tooling features will be enabled with Portal/AzCLI/CICD tools - Azure Pipelines/GitHub Actions. Network and observability configurations are mapped at Container App Environment so users define these settings at container app environment level which applies to all microservices , functions running as container apps.

  • Polyglot App Management : The environment enables to easily integrate mixed workloads - polyglot and heterogeneous modern apps or microservices consisting of webapps hosted on Azure Container Apps, Azure Spring apps, APIs, websites or any container hosted programs along side with Functions besides providing unified networking, observability, dynamic scaling, configuration, and high productivity
  • Enable cloud-native capabilities such as service discovery, native container support, and integration with open source libraries and frameworks like KEDA, Dapr, Envoy
  • Simplified and seamless client and Devops tooling experiences across Azure Portal, Az CLI, Azure Pipelines, GitHub Actions
  • Dedicated Networking, Observability and pricing plans tied to Container App environment as opposed to a single app types

Scenarios

Here are usecases and scenarios that can be deployed on to Azure Functions on Azure Container Apps

  • React to events from Http/Kafka/Event hubs/Service Bus/Storage Queue and invoke another web or spring based API running in the Container App environment. Scale on-demand as the events increase
  • Web Services – Rest APIs backend with event based execution requirements or Authentication APIs which trigger during login or authorization events
  • Event based data ingestion platform to perform data quality checks for online retail/e-commerce/travel apps. This process helps validating data for data accuracy, data completeness etc. ML workflows get invoked once data quality processing completes
  • Mixed workloads across different app types. Easy integration across other application types like Azure Container Apps and Azure Spring Apps
  • IoT/Point-Of-Sales/Edge event processing microservices applications

Key Features of Azure Functions on Container App Environment

Functions on Container App environment is designed to meet the needs of cloud-native requirements, while preserving approachability for teams of all sizes and capabilities. It provides unified platform with portability, flexibility, and developer-centric entry points for building apps

  • Integrated Azure Functions Programming model and write code using your preferred programming language or framework that Azure functions supports
  • Consistent end to end development experiences across Azure functions plans and hosting options using inner loop, outer loop, runtime and DevOps tooling
  • Build multi type apps and easily integrate with multiple app types for a microservices design like run functions along with other microservices, APIs, websites, workflows or any container hosted programs
  • Scale dynamically based on events all the way to zero or scale to dozens of containers when under high load

Triggers and Bindings that would be available in Public preview

  • Http
  • Azure Storage Queue
  • Azure Service Bus
  • Azure EventHub
  • Kafka Trigger

Azure Regions

Container Apps support for Functions is currently in preview and is only available in the following regions:

  • Australia East
  • Central US
  • East US
  • East Us 2
  • North Europe
  • South Central US
  • UK South
  • West Europe
  • West US3

When your container is hosted in a Consumption + Dedicated plan structure, only the default Consumption plan is currently supported. Dedicated plans in this structure aren't yet supported for Functions. When running functions on Container Apps, you're charged only for the Container Apps usage. For more information, see the Azure Container Apps pricing page. For list of supported regions in this plan see here

Create your first Azure Function on Azure Container Apps

In this section:

Prerequisites

On Your Local computer

C# Isolated Node Python Java PowerShell
.NET 6.0 SDK. or .NET 7.0 SDK when targeting .NET 7.0., Docker, Docker ID OR Azure Container Registry (You must have Docker installed locally. Docker provides packages that easily configure Docker on any [Mac], Windows, or Linux system.) Node.js version 18 or above. Python versions that are supported by Azure Functions The Java Developer Kit, version 8 or 11. The JAVA_HOME environment variable must be set to the install location of the correct version of the JDK.Apache Maven, version 3.0 or above The .NET 6.0 SDKPowerShell 7.2
Azure Functions Core Tools version 4.x. Azure Functions Core Tools version 4.x. Azure Functions Core Tools version 4.x. Azure Functions Core Tools version 4.x. Azure Functions Core Tools version 4.x.
Azure CLI version 2.47 or later. Azure CLI version 2.47 or later. Azure CLI version 2.47 or later. Azure CLI version 2.47 or later. Azure CLI version 2.47 or later.
You also need an Azure account with an active subscription. Create an account for free. You also need an Azure account with an active subscription. Create an account for free. You also need an Azure account with an active subscription. Create an account for free. You also need an Azure account with an active subscription. Create an account for free. You also need an Azure account with an active subscription. Create an account for free.

Note: extension bundle version compatible with host version 4.17+ can be used

Prerequisite check

Verify your prerequisites, which depend on whether you're using Azure CLI for creating Azure resources: Azure CLI

  • In a terminal or command window, run func --version to check that the Azure Functions Core Tools are version 4.x.
  • Run dotnet --list-sdks to check that the required versions are installed.
  • Run az --version to check that the Azure CLI version is 2.4 or later
  • Run az login to sign in to Azure and verify an active subscription.
  • Docker is installed, have a Docker ID and Docker is started

Create the local function project C# isolated - Http Trigger

1. Run the func init command, as follows, to create a functions project in a folder named LocalFunctionProj with the specified runtime: Below sample built for .NET 7

func init LocalFunctionProj --worker-runtime dotnet-isolated --docker --target-framework net7.0

The --docker option generates a Dockerfile for the project, which defines a suitable custom container for use with Azure Functions and the selected runtime.

2. Navigate into the project folder

cd LocalFunctionProj

This folder contains the Dockerfile and other files for the project, including configurations files named local.settings.json and host.json. By default, the local.settings.json file is excluded from source control in the .gitignore file. This exclusion is because the file can contain secrets that are downloaded from Azure.

3. Open the Dockerfile to include following (Usually found in Line 13)

FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated7.0

This version of the base image supports Azure Functions deployment to an Azure Container Apps service check to include below as well in the Dockerfile (found in Line 1) FROM mcr.microsoft.com/dotnet/sdk:7.0 AS installer-env

Sample Dockerfile for .NET 7

FROM  mcr.microsoft.com/dotnet/sdk:7.0 AS installer-env

COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
  mkdir -p /home/site/wwwroot && \
  dotnet publish *.csproj --output /home/site/wwwroot

# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated7.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

Note : If you are using .NET 7 then remember to update the .csproj file to point to net7.0 as shown below

  <TargetFramework>net7.0</TargetFramework>

4. Add a function to your project by using the following command, where the --name argument is the unique name of your function (HttpExample) and the  --template argument specifies the function's trigger (HTTP).

func new --name HttpExample --template "HTTP trigger" --authlevel "anonymous"

Build the container image and Test locally

The Dockerfile in the project root describes the minimum required environment to run the function app in a container. The complete list of supported base images for Azure Functions is documented above as Host images in the pre-requisites section or can be found in the Azure Functions Base by Microsoft | Docker Hub

Build and Push using Docker:

1. In the root project folder, run the docker build command, and provide a name, azurefunctionsimage, and tag, v1.0.0.

Note: Please make sure docker is running in your local The following command builds the Docker image for the container.

docker build --platform linux --tag <DOCKER_ID>/azurefunctionsimage:v1.0.0 .

In this example, replace <DOCKER_ID> with your Docker Hub account ID. When the command completes, you can run the new container locally.

2. To test the build, run the image in a local container using the docker run command, with the adding the ports argument, -p 8080:80.

docker run -p 8080:80 -it <docker_id>/azurefunctionsimage:v1.0.0

Again, replace <DOCKER_ID with your Docker ID and adding the ports argument, -p 8080:80

3. After the image is running in a local container, browse to http://localhost:8080/api/HttpExample?name=Functions, which should display the same "hello" message as before. Because the HTTP triggered function uses anonymous authorization, you can still call the function even though it's running in the container. Function access key settings are enforced when running locally in a container. If you have problems calling the function, make sure that access to the function is set to anonymous.

4. After you've verified the function app in the container, stop docker with Ctrl+C.

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. Docker login

5. If you haven't already signed in to Docker, do so with the docker login command, replacing  <docker_id> with your Docker ID. This command prompts you for your username and password. A "Login Succeeded" message confirms that you're signed in.

6. After you've signed in, push the image to Docker Hub by using the docker push command, again replacing <docker_id> with your Docker ID.

docker push <docker_id>/azurefunctionsimage:v1.0.0

7. Depending on your network speed, pushing the image 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.

Build and Push using ACR (Optional Azure Container Registry)

You can build and deploy functions on Azure container apps using ACR as well. Please make sure you have an ACR repository created by following the steps mentioned in the link. Azure Container Registry is a private registry service for building, storing,and managing container images and related artifacts.

1. Login to the registry

Before pushing and pulling container images, you must log in to the registry. To do so, use the az acr login command. Specify only the registry resource name when logging in with the Azure CLI. Don't use the fully qualified login server name.

az acr login --name <registry-name>

2. Build and Push to the registry

Before you can push an image to your registry, you must tag it with the fully qualified name of your registry login server. The login server name is in the format <registry-name>.azurecr.io (must be all lowercase), for example, mycontainerregistry.azurecr.io. Tag the image using the docker tag command. Replace  with the login server name of your ACR instance.

  docker tag <docker_id>/azurefunctionsimage:v1.0.0 <login-server>/azurefunctionsimage:v1

The following command builds the image, and pushes it to your container registry if the build is successful.

  az acr build --registry $ACR_NAME --image azurefunctionsimage:v1 .

Create Azure resources

Before you can deploy your container to your Azure Container apps you need to create two more resources

a. A Storage account

b. Create the Container Apps environment with a Log Analytics workspace

1. Login to your Azure subscription

az login
  
az account set -subscription | -s <subscription_name>

az upgrade

az extension add --name containerapp --upgrade

az provider register --namespace Microsoft.Web

az provider register --namespace Microsoft.App

az provider register --namespace Microsoft.OperationalInsights

2. Create azure container app environment

Create an environment with an auto-generated Log Analytics workspace.

  az group create --name MyResourceGroup --location northeurope
  az containerapp env create -n MyContainerappEnvironment -g MyResourceGroup --location northeurope

3. Create Storage account

Use the az storage account create command to create a general-purpose storage account in your resource group and region:

az storage account create --name <STORAGE_NAME> --location northeurope --resource-group MyResourceGroup --sku Standard_LRS

Replace <STORAGE_NAME> with a name that is appropriate to you and unique in Azure Storage. Names must contain three to 24 characters numbers and lowercase letters only. Standard_LRS specifies a general-purpose account, which is [supported by Functions](https://learn.microsoft.com/en-us/azure/azure-functions/storage considerations#storage-account-requirements). The --location value is a standard Azure region.

Create the function app

Run the az functionapp create command to create a new function app in the new managed environment backed by azure container apps.

Note: **If you wish to use the quick start demo Http trigger sample you can include the below image url for --image parameter(this is a publicly accessible image so username/password is not required)


azurefunctionstest.azurecr.io/azure-functions/dotnet7-quickstart-demo:1.0

OR you may keep the image url ready for an existing image that you have in your repo which is already "build" for eg: /: -> mydockerusr/azurefunctionsimage:v2

Using Docker Hub


az functionapp create --resource-group MyResourceGroup --name <functionapp_name> \
--environment MyContainerappEnvironment \
--storage-account <Storage_name> \
--functions-version 4 \
--runtime dotnet-isolated \
--image <DOCKER_ID>/<image_name>:<version> 

Using ACR


az functionapp create --resource-group MyResourceGroup --name <functionapp_name> \
--environment MyContainerappEnvironment \
--storage-account <Storage_name> \
--functions-version 4 \
--runtime dotnet-isolated \
--image <acr login-server>/<image_name>:<version> \
--registry-username <user_name> --registry-password <user_password>

In this example, replace MyContainerappEnvironment with the Azure container apps environment name. Also, replace <STORAGE_NAME> with the name of the account you used in the previous step, <APP_NAME> with a globally unique name appropriate to you, and <DOCKER_ID> or  with your Docker Hub ID or ACR , <user_name> with the username to log in to container registry(mostly applicable for ACR) and <user_password> with the password to log in to container registry. If stored as a secret, value must start with 'secretref:' followed by the secret name (mostly applicable for ACR).

The --image 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 the az functionapp config container set command to deploy from a different image.

When you first create the function app, it pulls the initial image from your Docker Hub. You can also Enable continuous deployment to Azure from Docker Hub.

Set required app settings

Run the following commands to create an app setting for the storage account connection string:

az storage account show-connection-string --resource-group <Resource_group> --name <STORAGE_NAME> --query connectionString --output tsv

Copy the output of the above and replace below at

az functionapp config appsettings set --name <app_name> --resource-group <Resource_group> --settings AzureWebJobsStorage="<storageConnectionString>"

Invoke the function on Azure

Because your function uses an HTTP trigger, you invoke it by making an HTTP request to its URL in the browser or with a tool like curl. Execute below command to get the Invoke URL

az functionapp function show -g <Resource_group> -n  <function_app_name>  --function-name <http_funtion_name> --query "invokeUrlTemplate" --output tsv

Copy the complete Invoke URL shown in the output of the publish command into a browser address bar, appending the query parameter ?name=functions or copy the Application Url and append /api/HttpExample?name=HelloWorld. The browser should display similar output as when you ran the function locally.

For eg: The Url generated would be - http://myfuncapponaca.gray-a2b3ceef.northeurope.azurecontainerapps.io/api/httpexample

Update function container image

If you wish to make changes to your code, modify the image with new version tag and build it, and then finally update the function's container app image please use below command. Note: Below sample for docker hub based image

az functionapp config container set --image <acr login-server>/<image_name>:<version> --registry-password <Password>  --registry-username <DockerUserId> --name <MyFunctionApp> --resource-group <MyResourceGroup>

Note: --image should be in the format "/<image_name>:"

Clean up resources

If you're not going to continue on to the next sample function app, you can remove the Azure resources created during this quickstart with the following command.

** Caution**

The following command deletes the specified resource group and all resources contained within it. If the group contains resources outside the scope of this quickstart, they are also deleted.

 az group delete --name $RESOURCE_GROUP

** Tip**

Having issues? Let us know on GitHub by opening an issue here

Next steps

TroubleShooting

Having issues with creating Azure Functions on Azure Container apps please refer to the troubleshooting guide

FAQ

Refer to the FAQ to know more about the offering - FAQ

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.