Deploy Python Docker Image to Azure Function App

Objective

You have a working Azure Python Docker function and the source code is managed in a Git repository. The goal of the tutorial is to automate the build and publish of a Docker image to Azure Function App. This automation will include:

  • cloning the Python application codebase from the Git repository

  • building the Docker image

  • publishing the Docker image to Azure Container Registry

  • packaging the Application Setting/Connection String properties files

  • updating relevant Application Setting and Connection String properties in Azure Function App

  • deploying the Docker image to Azure Function App

We will walk through each of the FlexDeploy features that will be created/configured to accomplish this goal and have the Python Docker function deployed in a very short amount of time.

This tutorial does not cover every feature or configuration option available in FlexDeploy.

Checklist

Checklist

Description

Checklist

Description

Azure Tenant Id

Azure Tenant Id for the company

Azure Subscription Id

Azure Subscription where the Function App exists

Azure Client ID

Client ID to connect to desired Azure Subscription

Azure Client Key

Password for the Client ID

Azure Client ID permission

The Client ID must have relevant access in the target Function App to deploy code

Azure Function App

The Function App with relevant runtime should already be created

Azure Resource Group

The Resource Group containing the Function App

Azure CLI installation

Azure CLI needs to be installed on the Target Endpoint where the plugin operation will run

Azure CLI in class path

Azure CLI should be added to the classpath on the Target Endpoint. Otherwise, the path can also be set under FlexDeploy environment level property

Docker Registry Address

Target Azure Container Registry URL

Docker Registry User

Azure Client ID to push/pull images against Azure Container Registry

Docker Registry Token/Password

Password for the above Client ID

Docker Registry User permission

The user must have relevant access to push/pull images from Azure Container Registry

Configure Cloud Account

FlexDeploy will connect to your Azure Subscription using the cloud account details provided.

  1. Navigate to Integrations

  2. Open the Cloud tab

  3. Create a new Cloud account by pressing the Create button. Create a new cloud account of provider type Azure

image-20240322-194231.png

It should have a Client ID, Client Key, Tenant Id, and Subscription Id configured in it. The Client ID must have relevant access in the target Function App to deploy code and make other associated changes. (Application Setting update, etc.)

Configure Container Account

Next, a Docker Registry account needs to be configured under Topology. FlexDeploy will connect to the right Container Registry with provided details and push the Docker image.

  1. Navigate to Integrations

  2. Open the Containers tab

  3. Create a new Containers account by pressing the Create button. Create a new Docker Registry account of provider type DockerRegistry

0ea93bb3-967b-47c9-9363-3e6b725580b4-20240322-194613.png

It should have a Docker Registry Address, Docker Registry User, and Docker Registry Token/Password configured in it.

Git Repository Structure

The Git repository should contain the function codebase. Alongside it can also contain any application setting and connection string related attributes in respective files (any naming convention allowed). These files are not mandatory, however, in case someone has any Application Setting and Connection String property to update this is recommended. Please review the Application Setting and Connection String Property Update section for a more detailed explanation.

A sample Git repository structure is given below:

Build and Deploy Workflows

Navigate to Workflows and create a build and a deploy workflow using the button as highlighted below.

Build Workflow

Below is a sample build workflow to build and push the Docker image and create an artifact from the Application Setting and Connection String files.

Step-i: Clone Git Repository

This step will clone the Git repository codebase into the project execution working directory. The Git URL will be retrieved from Source Control configured under Project Configuration.

Below is the Git code structure and corresponding exported codebase during execution as a result of the above step.

Git Codebase

EXPORTED CODEBASE

Step-ii: Copy the properties file to the intermediate dir

Application Setting and Connection String JSON files(if applicable/present) will be moved to the intermediate directory. An intermediate directory can have any name, in this case, we are using the artifactsObjects folder inside the TEMP directory. File names are mentioned under File Filter with ‘##’ separated (as advised in the description). Application Setting and Connection String values can also be passed as input to deploy workflow. Application Setting and Connection String files are optional, please review the Application Setting and Connection String property update for a detailed explanation.

It's essential to make sure Consumes Artifacts and Produces Artifacts checkbox is marked only when required. Please follow the screenshots for all execution steps to avoid any discrepancy.  

Step-iii: Build and Push Docker image to ACR

Below given is the Docker plugin(buildImage operation) configurations.

The plugin operation by default would look for the Dockerfile under TEMP directory. In case the same exist in some other folder, relative path has to be specified from TEMP directory.

Below given is the Git project folder structure. Since our Dockerfile is under the PythonDockerProj folder in the Git repository we had to provide the relative path accordingly.

By default Docker image and image tag details will be retrieved from Project Properties. However, one can always provide the details as part of the plugin operation input(highlighted in above plugin operation diagram). Plugin operation input shall take precedence over Project Properties.

We have also marked the “Push Image to Repository” checkbox to ensure the created image is deployed to Docker Registry. pushImage operation under the Docker plugin can also be used to push the image to target Docker registry.

If the Container Registry Account is properly configured it would push the image to Docker Registry. In our case, the image will be pushed to Azure Container Registry.

Step-iv: Save all from the intermediate dir as Artifact 

Post execution of the above steps the intermediate directory(artifactObjects) should contain files as shown below.

These objects are required as part of the deployment flow. Hence we create an archive(artifacts.zip) with them inside the Artifacts directory. We also enable Produces Artifacts checkbox to save the zip file as an artifact.

Note: The directory name/artifact name can be anything. The deployment workflow expects only one .zip file inside the artifact containing the relevant files.

Note: the deployFunctions operation(Azure plugin) will search for the Application Setting and Connection String file name provided as part of Project properties. Irrespective of folder structure it will find the file. In case more than one file exists with the same name, flow shall fail.

Deploy Workflow

Below given is a sample deployment workflow to deploy the archive to Azure Function App.

This step first updates the Application Setting/Connection String values from the files present in the artifact(optional). Instead of using Application Setting and Connection String files, one can directly provide the values as part of plugin input.

In such case, we can create input variables on deployment workflow like given below and pass them as deployFunctions operation input argument. This is optional and any other way to pass the arguments(e.g. hardcoded value) is also acceptable.

First, click on the Inputs button to open the popup. Create two input variables, one each for Application Setting and Connection String as shown below.

The input arguments are then mapped to the input properties of the deployFunctions operation as shown below. The plugin will take the input values and process them accordingly.

The deployFunctions operation returns four output variables. To capture them and use them for further processing/evaluation, create four variables and map them against the output parameters of deployFunctions operation. Return As Output option should be checked.

  1. First, click on the X2 button to open the Variables popup

  2. Next use Create option to add four output variables.

Map the variables against the output of the deployFunctions plugin operation to capture the responses.

Project Configuration

Navigate to the Project tab and create a Project with a logical name (PythonDockerAzFunction in this case).

Configure the Build and Deploy workflow that has been created in previous steps as shown below

Source Control

Configure the Source SCM repository under Source Control as shown below.

  1. To configure Project specific Source Control one first need to navigate to the Project Configuration tab.

  2. Next, expand the SOURCE CONTROL option from the left-hand pane.

  3. Select SOURCES for configuring the Source Repository

  4. Select the appropriate Source Control Type

  5. Configure Source Repository. For detailed steps of Source Control configuration please refer to Configure Source Control in FlexDeploy

Project Properties

To configure Project specific settings one can navigate to Configuration Properties as shown below.

  1. To configure Project specific settings one can navigate to the Project Configuration tab as shown above.

  2. Next, select the PROPERTIES option from the left-hand pane.

  3. To deploy a Function to Azure Function App, the first two mandatory properties are the Function App Name and Resource Group Name. These need to be configured under Project properties.

  4. Under Project properties, one also needs to provide the Application Setting/Connection String file names(if applicable).

  5. Docker Image Name and Docker Image Tag are essential to build the Docker image.

Application Setting and Connection String property

These Application Setting/Connection String properties are non-mandatory and can be directly provided as plugin Input as well. Or even may not be passed at all. However this is the recommended way and the files should exist in working directory(TEMP) during execution(folder hierarchy is not required, the plugin will search the file based on the file name).--

Although only one Application Setting and one Connection String file are allowed per project.

Application Setting and Connection String are two separate entities so whichever files exist, the same will be considered during deployment.

Let’s review the sample Application Setting file first(same structure as the local.settings.json file). In our scenario, there are two dynamic values that need to be propagated to Function App Application Setting.

One of them DYNAMIC_TESTKEY1: is project specific and env agnostic

DYNAMIC_ENV_TESTKEY2: another one however changes env-wise

Both are already added to the AppSettings.json file present in Git Repository.

Both properties need to be configured in workflow Properties with relevant Property Scope.

  1. To pass the value for DYNAMIC_TESTKEY1(Project specific) one first needs to navigate to the Configuration tab

  2. Next, select the PROPERTIES option from the left-hand pane and provide the proper value against the property.

For Environment property, the same needs to be added against Environment-Target Group properties.

  1. First, navigate to the Topology.

  2. Next, navigate to the Environment-Target Group properties section for the intended Target.

  3. Next, select the PROPERTIES tab and provide the value for DYNAMIC_ENV_TESTKEY2(environment specific) as shown below.

Application Setting/Connection String can also be passed as an input argument to the deployFunction operation. The sample is shown as given below.

Please refer to this link for the input structure of Application Setting and Connection String both when passed as a file or as input parameter - Application Setting/Connection String file and input content acceptable structure

In case both the Application Setting file and Application Setting input argument are passed, a consolidated list of properties will be considered while updating Function App. If the same attribute is used both in the file and input, the value provided as part of the input will take precedence. The same applies to Connection String as well.

Also, it’s not mandatory to have dynamic values. One can always pass static hard-coded value if needed (although not recommended).

Application Setting and Connection String values will be updated against the Function Slot Name configured at the environment level. Refer to the Deploy to slot section for further details.

There could also be scenarios where someone only need to update the Application Setting or Connection String without actually deploying the code. In that case one can use upsertFunctionApplicationSetting or upsertFunctionConnectionString operations respectively. The workflow execution will be exactly same only the code archive creation /Docker image update step will not be required. Build workflow generated artifact should only container AppSetting.json or ConnString.json. These values can also be passed as input as already mentioned in detail in above section.

Target Properties

Select Topology from the menu and then select Topology Overview from the left menu. You will see a table that has Instances as the rows and Environments as the columns with colored circles representing the Environment Instance. Color coding represents:

  • RED - no required properties are set and/or the Endpoint is not configured

  • YELLOW - some of the required properties are set and/or the Endpoint is not configured

  • GREEN - all required properties are set and the Endpoint is configured

Selecting the GREEN circle for DEV will display the configurable properties/Endpoint and allows for the configuration of

Properties

Mandatory field

Description

Slot Name

 

Target slot for deployment

Target slot to swap

Optional

In case slot swap is required

Azure Cloud Account

 

An azure account with relevant details

The absolute path of Azure CLI

Optional

Not required if Azure CLI already added to workflow execution m/c classpath

Docker Server

Optional

Docker server address. Required if Docker Unix Socket is not set.

Docker Server Port

Optional

The port to connect to on the Docker server.

Docker Unix Socket

Optional

The socket the Docker daemon listens on

The default value is [/var/run/Docker.sock]

Registry Account

 

Docker Registry account with relevant details

GIT Path

Optional

Path to the Git executable. Required only if git is not on class path.

Below given are the env-specific values which need to be updated.

Also in case, we are adding any env-specific properties for Application Setting/Connection String(as mentioned in the previous step), those values should also be updated.

The Azure Could and Docker Registry account needs to be set here from the drop-down. It will show all Cloud/Container Accounts configured under Topology, which we have already mentioned earlier.

Deploy to slot

Azure Function App default slot is production. However, one can configure multiple slots and deploy Functions on those slots inside Function App. Function Slot Name is a mandatory field, where the code needs to deploy.

In case someone wants to do a slot swap, they can provide the Target Slot to swap with as shown below.

executeFunctionAppSlotSwap operation can be used to perform the slot swap.

Post deployment debugging

Post deployment success it can take 1-2 mins to download the image from Docker Registry and start the container by Azure Function App.

Currently once a Docker image is deployed to Azure Function App through the plugin operation, Azure updates the image details in Function App configurations and responds back. However if the container is up and running or have failed, can’t be verified immediately. It takes a little while for containers to start and accept requests.

Issues can happen if image/repository/Registry Account details provided are incorrect or credential provided in Docker Account under Topology doesn’t have sufficient privilege to access the Docker images.

In such scenario functions deployed will reflect as none with Azure Function may be in unreachable state as shown below.

 

Best way to check logs: https://$func_name.scm.azurewebsites.net/api/logstream or logstream  from console  or https://$func_name.scm.azurewebsites.net/api/logs/Docker

So in case the Function Url is : https://function0610.azurewebsites.net

The log can be accessed at -https://function0610.scm.azurewebsites.net/api/logstream

In case of failure we can easily debug the issue from log. Such as in this case it’s evident that the image tag is not present in Docker Registry.

In case of successful execution, we can find below msg stating the container is up and running.

Build Execution

For detailed steps on how to initiate Build Azure Function, review artifacts, and ultimately deploy to Azure Function App please refer to Build and deploy execution through FlexDeploy

Congratulations! You have successfully completed the Python Docker image deployment to the Azure Function App tutorial.

Now that you have configured FlexDeploy for one Azure Function, it is extremely easy to replicate the same for other Azure Functions. Simply use the Copy Project feature and a new project will be created with all of the configuration completed already. You just need to make the necessary configuration changes.

 

The following macros are not currently supported in the footer:
  • style