loading...

Azure Function App and Docker on Azure made easy in 12 steps

codeprototype profile image Kevin Le Updated on ・6 min read

Abstract

This article shows how to write an Azure Function App on your development computer, aka local machine and deploy it to Docker on Azure. If you're new but want to learn about Azure Function App, Docker containers on Azure, Azure Container Registries etc, and how to use all of them together, you could be overwhelmed with plenty of but disparate Azure documentation (not to mention documentation on Docker website itself), and they won't be so clear especially if you're trying to see how they all fit together. On the hand, this article hopefully provides you with the quickest, step-by-step approach. You will go from zero to deployment in x minutes. Once you see how the Function App finally runs on Azure cloud after a few steps, we will go back to the development computer, makes some changes as we often have to do in real world situations, go through all the steps again, and see the changes reflected on Azure.

Requirements

  1. You must already have an Azure Subscription
  2. Your development (dev) computer must run at least Windows 10 Pro, or latest MacOS or Ubuntu Linux (I have not tried)

Assumptions:

  1. We will write the sample Azure Function App in C#/.Net
  2. The sample Azure Function App is HttpTriggered.
  3. I will show everything using command line interface (CLI). But there's always an UI alternative.
  4. Naming convention: You will find I'm using name like kleSampleResourceGroup in the instructions of this article. Such name like kleSampleResourceGroup can be broken in 3 parts. kle identifies the organization. Sample is the name of this project. ResourceGroup identifies the thing that we are naming.

Step 1: Installation

We have to install a few software programs on the dev computer. However, these installations are extremely simple. Just follow the links listed.

NodeJS https://nodejs.org/download/release/
Docker https://www.docker.com/products/docker-desktop (Docker requires you to signup)
Azure Function Core Tools Once NodeJS and npm have been installed, you can run the following command
% npm install -g azure-functions-core-tools@latest
.NET Core https://dotnet.microsoft.com/download/dotnet-core (Note: I have not tried with .Net Core 3.+)
Azure CLI https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest

Step 2: Create a new Azure Function App on the dev computer

On your terminal, type

% mkdir kleSampleFuncApp
% cd kleSampleFuncApp
% func init . --docker

The last command will prompt us to select a worker runtime. Four choices are presented. As mentioned above, we will choose dotnet. Consequently, this command will generate the following files in the directory: Dockerfile, host.json, kleSampleFuncApp.csproj and local.settings.json

Next, in the newly created Function App, we will create a new Function using the HttpTriggered template. A Function App can have multiple Functions. Each Function in this context represents an URL endpoint.

% func new

This command will prompt us to pick a Function App template. Choose HttpTrigger. It will then prompt for a function name, enter kleSampleFunc. This will generate a file named kleSampleFunc.cs. Open up that file, search for AuthorizationLevel.Function and change it to AuthorizationLevel.Anonymous

Step 3: Build and run the Function App on the dev computer

% func start --build

This command will build and start the Function App. We will see that the application is listening on the default port 7071, can handle both GET and POST requests and the entire URL endpoint is http://localhost:7071/api/kleSampleFunc

If you're on Mac or Linux, you can use curl to quickly test. Alternatively, you can use Postman or any other similar tools.

% curl -X POST http://localhost:7071/api/kleSampleFunc -d '{"name":"kevin"}' -H "Content-Type: application/json"

Step 4: Create a Docker image of the Azure Function App on the dev computer

Earlier in step 2, we typed the command func init . --docker. The option or flag --docker tells Azure Function Core Tool to generate the Dockerfile. With that, now we can create a Docker image of the Function App. This image will be uploaded to a Docker container on the Azure cloud (Azure Container Registry) later.

With Docker Desktop running, on your terminal, type

% docker build -t kle/sampledockerimg .
% docker run -p 7071:80 kle/sampledockerimg

Do not forget to type the dot at the end of the build command

Now test again:

% curl -X POST http://localhost:7071/api/kleSampleFunc -d '{"name":"kevin"}' -H "Content-Type: application/json"

If that's working, we now have created a Docker image of the Function App and run it on Docker Desktop successfully.

Step 5: Log in to Azure CLI on the dev computer

On your terminal, type

% az login

and follow the instructions.

Step 6: Create an Azure Resource Group on Azure cloud

% az group create -l westus -n kleSampleResourceGroup

Step 7: Create an Azure Container Registry on the Azure cloud

% az acr create -n kleSampleRegistry -g kleSampleResourceGroup --sku Standard --admin-enabled true

Notice the JSON output with the key loginServer. Its value should be something like klesampleregistry.azurecr.io

Launch the Azure portal, https://portal.azure.com, then browse your Container Registries, select the Registry you just created (in my case klesampleregistry), click on Access Key under Settings, and note the username and password.

Step 8: Create an Azure Storage Account on Azure cloud

% az storage account create -n klesamplestorage -g kleSampleResourceGroup -l westus

Step 9: Login to your Azure Container Registry

% docker login klesampleregistry.azurecr.io

When prompted, provide the username and password that you noted in step 7.

Step 10: Tag your Docker image

Look at step 4 when you build the docker image of your Function App (kle/sampledockerimg), you will tag this image in the Container Registry as klesample (note this name must be all in lower case)

% docker tag kle/sampledockerimg klesampleregistry.azurecr.io/klesample

Step 11: Push the docker image to the Container Registry

Using Docker, we can now push the image to the Container Registry on Azure

% docker push klesampleregistry.azurecr.io/klesample

Step 12: Create an Azure Function App

There is a command from Azure CLI az functionapp create that we could use. But the problem is it does not allow the created Function App to be published from a Docker container. So we will use the UI https://portal.azure.com

Click on the big Plus button Create a Resource under Azure Services, search for Function App template and click on Create

Alt Text

Click on Next: Hosting >

Alt Text

Click on Review + Create then Create on the last page.

Once the Function App kleSampleFuncApp has been created, click on Platform features, then Container Settings as shown below

Alt Text

On the next screen, select Single Container, Azure Container Registry, the registry that we created in step 7, the image in step 10, latest. Select On for Continuous Deployment, and Save it.

Once saved, you can close the blade. Back on the Overview page, on the Right menu, click on kleSampleFuncApp, expand kleSampleFunc, you can run test directly from this page. Follow the screenshot below:

Alt Text

You can also click the Get Function URL link next to the run button and test from Curl or Postman.

% curl -X POST https://klesamplefuncapp.azurewebsites.net/api/kleSampleFunc -d '{"name":"kevin"}' -H "Content-Type: application/json"

Continuous Deployment

Remember back on step 12, we select On for Continuous Deployment. We did so because if we ever need to make changes of the code, which will certainly happen, we want to push the changes up to the Function App on the Docker container on Azure.

So let's go back to the code and change from Hello to Hi. Save.

First let's test when we run locally. On the terminal, type

func start -build

If you get the error message

Port 7071 is unavailable. Close the process using that port, or specify another port using --port [-p].

That's because we had the Docker image still running from earlier. We need to stop it.

Type

% docker ps

Note the Container Id in the output. Assume it's something like 87d8462f9d63, type

% docker stop 87d8462f9d63

Again, type

% func start -build

Test as we did in step 3. This confirms the change we made is good. Now rebuild the Docker image and run it as we did in step 4.

% docker build -t kle/sampledockerimg .
% docker run -p 7071:80 kle/sampledockerimg

Test again. This confirms the new build of the Docker image contains the change that we made. Now let's tag and push it to Docker on Azure as we did in step 11.

% docker tag kle/sampledockerimg klesampleregistry.azurecr.io/klesample
% docker push klesampleregistry.azurecr.io/klesample

Discussion

pic
Editor guide