Develop in Linux through the command line with:
- .NET 6.0 SDK
- Azure Functions Core Tools 4.x
- Azurite storage emulator
- Azure CLI 2.4.0 or newer
- Docker
Create Project
Use the following command to create a Timer Trigger function in the current directory, and generate the default Dockerfile.
func init --name ContainerApp --worker-runtime dotnet --docker func new --name TimerTriggerExample --template "timer trigger"
First, run Azurite and then test the function app:
azurite -l azurite_workspace func start
After testing the app, package the image and run it. Note that when running with docker, you need to set AzureWebJobsStorage
to UseDevelopmentStorage=true
and simulate storage through Azurite. Enter the name of your Azure Container Registry in the ACR_NAME
environment variable in the following command block:
export ACR_NAME=<your azure container registry name> docker build -t ${ACR_NAME}.azurecr.io/container-app:latest . docker run --name container-app -p 8000:80 --network host \ -e AzureWebJobsStorage="UseDevelopmentStorage=true" ${ACR_NAME}.azurecr.io/container-app:latest
Please note that Azure Functions containers cannot currently run directly on Mac M1.
By the way, Azurite also provides a Docker image that can be run directly with the following command:
docker run --name azurite -p 10000:10000 -p 10001:10001 -p 10002:10002 -d mcr.microsoft.com/azure-storage/azurite
After testing the local image, push it to Azure Container Registry:
az login az acr login -n ${ACR_NAME} docker push ${ACR_NAME}.azurecr.io/container-app:latest
You can then deploy Azure Functions using Azure Container Registry in two ways:
Method 1: Admin Credentials
Give Functon App a Container Registry account password, so that Function App can log in to Container Registry and pull the image file through this set of account password.
First, create a resource group in Azure Portal, fill in the name of this resource group into the RG_NAME
environment variable in the command block below, and create and deploy the resources required by Azure Function in this resource group:
export ACR_NAME=<azure container registry name> export RG_NAME=<function app resource group> export APP_NAME=<function app name> export STORAGE_NAME=<storage account name> # Create a storage account az storage account create --name ${STORAGE_NAME} --resource-group ${RG_NAME} --sku Standard_LRS --kind StorageV2 # Create App Service Plan az appservice plan create --name PlanB1 --resource-group ${RG_NAME} --is-linux --sku B1 # Get the username of ACR az acr credential show -n ${ACR_NAME} --query username --output tsv # Get ACR password az acr credential show -n ${ACR_NAME} --query passwords[0].value --output tsv # Create/re-deploy the Function App, set all the necessary information at once az functionapp create --name ${APP_NAME} --storage-account ${STORAGE_NAME} --resource-group ${RG_NAME} \ --plan PlanB1 --functions-version 4 \ --deployment-container-image-name ${ACR_NAME}.azurecr.io/container-app:latest \ --docker-registry-server-password <acr password> \ --docker-registry-server-user <acr username>
That's it.
Method 2: Managed Identity
Setup an Identity for the Function App, and let Container Registry give it the "AcrPull" permission.
export ACR_NAME=<azure container registry name> export RG_NAME=<function app resource group> export APP_NAME=<function app name> export STORAGE_NAME=<storage account name> # Create a storage account az storage account create --name ${STORAGE_NAME} --resource-group ${RG_NAME} --sku Standard_LRS --kind StorageV2 # Create App Service Plan az appservice plan create --name PlanB1 --resource-group ${RG_NAME} --is-linux --sku B1 # Create a Function App and specify the address of the image az functionapp create --name ${APP_NAME} --storage-account ${STORAGE_NAME} --resource-group ${RG_NAME} \ --plan PlanB1 --functions-version 4 \ --deployment-container-image-name ${ACR_NAME}.azurecr.io/container-app:latest # Set an Identity for the Function App and get the principalId az functionapp identity assign --resource-group ${RG_NAME} --name ${APP_NAME} --query principalId --output tsv # get subscriptionId az account show --query id --output tsv # Give Function App "AcrPull" permission az role assignment create --assignee <principal-id> \ --scope /subscriptions/<subscription-id>/resourceGroups/<container registry resource group>/providers/Microsoft.ContainerRegistry/registries/${ACR_NAME} \ --role "AcrPull" # Set the permission to pull from Container Registry that must be authenticated by Identity az resource update --ids /subscriptions/<subscription-id>/resourceGroups/${RG_NAME}/providers/Microsoft.Web/sites/${APP_NAME}/config/web --set properties.acrUseManagedIdentityCreds=True # Deploy Function App az functionapp config container set --name ${APP_NAME} --resource-group ${RG_NAME} \ --docker-custom-image-name ${ACR_NAME}.azurecr.io/container-app:latest \ --docker-registry-server-url https://${ACR_NAME}.azurecr.io
At this time, the terminal will display "No credential was provided to access Azure Container Registry. Trying to look up...", azure will automatically apply the current identity to log in to ACR.
Top comments (2)
Thanks for sharing this, was easy to follow up. The params --docker-custom-image-name and --docker-registry-server-url are deprecated now. Cli will suggest the new names.
Thanks for the feedback. Will try again and update the command later.