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.