DEV Community

Cover image for Deploy Azure Functions using Azure Container Registry
Jack Lin
Jack Lin

Posted on

Deploy Azure Functions using Azure Container Registry

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"
Enter fullscreen mode Exit fullscreen mode

First, run Azurite and then test the function app:

azurite -l azurite_workspace
func start
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
tjoudeh profile image
Taiseer Joudeh

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.

Collapse
 
blueskyson profile image
Jack Lin

Thanks for the feedback. Will try again and update the command later.