Deploying a Python Azure function as .zip

11 May, 2022
Xebia Background Header Wave

Deploying a Python Azure function app as .zip with remote building

While working on a Python Azure function app, I struggled with deploying resources through Terraform and then deploying the project itself as .zip with remote build from the Azure CLI. In this post I’ll show a relatively minimal example of how I made it work, and the two pitfalls that I encountered.

You can see my example solution in this github repo. Check the README to deploy the example for yourself.

Why deploy as .zip?

The reason for wanting to package and deploy the function as .zip file is three-fold.

  1. This approach is similar to, but requires one less tool than using func azure functionapp publish.
  2. The project had grown a bit and it had become cumbersome to update the .funcignore file. So, instead it was easier to select the files and folders relating to the function app and package those.
  3. I like that a remote build should prevent the leaking of quirks of whatever local system I’m running.

If you’re interested in building the function app locally and deploying that directly with only Terraform then check out this post by Niels.

Azure portal vs Terraform

For this project I started out by provisioning resources manually through the Azure portal website. But then, as the basic system was up and running, I ran into the first pitfall when I started deploying the resources through Terraform. There is a subtle, but crucial difference in how the Azure portal configures function apps compared to Terraform (azurerm_function_app).

The difference is that the Azure portal automatically sets FUNCTIONS_WORKER_RUNTIME = "python" for Python function apps, while Terraform does not. Part of the issue is that this setting does not show up in the function app’s JSON definition. And so while the resource definitions look the same, they crucially are not.

Also, when you trigger a remote build, the Azure CLI checks if SCM_DO_BUILD_DURING_DEPLOYMENT = true, and if it is not then this value is set. But this logic does not apply to FUNCTIONS_WORKER_RUNTIME.

Below is the relevant section of how I configured my function app resource in the end. See the repo for the full Terraform config and variables.

resource "azurerm_function_app" "function_app" {
  site_config {
    linux_fx_version = "Python|3.9"

  app_settings = {
    FUNCTIONS_WORKER_RUNTIME       = "python"

.zip contents

The second issue that I ran into, is that I thought that the remote build process was failing due to some problem with the .zip file contents and I couldn’t find a good overview of the minimum contents of such a .zip file. So hopefully a written out list will help others, and luckily it turns out to be pretty straightforward.

The requirements are:

  • the function app host.json file
  • all function folders containing function.json and the python file it refers to as scriptFile
  • all files and folder containing business logic that are needed for the functions
  • the requirements.txt file.

The command line zip command that I use for the example repo (generated by the Terraform deploy_azure_function resource) is:

zip -r build/ 
    app/ function/ host.json requirements.txt 
    -x '*__pycache__*' 

Note that Niels’ blog post also showed how to build a zip with Terraform. That example would however need to be extended/modified for the project I’m working on, because the required files and folders are not all grouped into a single folder.

Triggering remote build & deploy

After creating the .zip file, I deploy the example function app like this with the Azure CLI:

az functionapp deployment source config-zip 
    --resource-group devzipdeploy 
    --name dev-zipdeploy-functions 
    --src build/ 
    --build-remote true 

I like to add the --verbose flag so that I can see the stages of the build process as they happen.

Wrap up

And just like that, we can spin up resources in Azure and have Azure build and deploy our Python function app for us. I hope that this post and example Github repo help make the process a bit more straightforward, and help avoiding the pitfalls that I ran into.

Attribution: zip icon created by Freepik – Flaticon


Get in touch with us to learn more about the subject and related solutions

Explore related posts