Local Azure Durable Functions Development in WSL2 - 101
Tags: azure, serverless, azurefunctions, wsl2
Published: 2021-05-15 12:26:29

## What to expect
This blog post will walk you through the basics on how to set up a local development environment for _Azure Durable Functions_ using _WSL2_ and _nodeJS_. It should especially help beginners to kick start their development journey and get some obstacles out of their way.  

## Prerequisites

We will not completely start from scratch when it comes to some prerequisites. So before we start, let us make sure that some things are in place on your system, 

* WSL 2 needs to be installed. If you have not yet done this, follow along the [official documentation](https://docs.microsoft.com/en-us/windows/wsl/install-win10?WT.mc_id=DT-MVP-5004195) that guides you through this. In this blog we use the [Ubuntu image](https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6?activetab=pivot:overviewtab).

>> _Remark: Although WSL2 is available for "older" versions of Windows10, you might face some problems if you are using a laptop/PC provides by your corporate as there might be restrictions due to that. So if you run into issues with WSL2 _per se_ it might be useful to sort out limitation due to corporate images or configurations._     

* The WSL environment for NodeJS development must be enabled. There is a very useful description for that on the [official help page](https://docs.microsoft.com/windows/dev-environment/javascript/nodejs-on-wsl?WT.mc_id=DT-MVP-5004195) 

>> _Remark: I use nvm to manage my NodeJS environment and set it to nodeJS version 14_ 

* To do local Azure Functions development we need to install the Azure Functions Core tools. Again the [official Microsoft documentation](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=linux%2Ccsharp%2Cbash#install-the-azure-functions-core-tools?WT.mc_id=DT-MVP-5004195) helps us with this task. 
In addition, start VS Code in your WSL2 environment and install the Azure Functions Extension for VS Code
  ![VS Code Extension for Azure Functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfellngddosad0kemi17.png)

* As we want to see that things get stored correctly, we also need the [Azure Storage Explorer](https://azure.microsoft.com/features/storage-explorer?WT.mc_id=DT-MVP-5004195) installed on our Windows system.

* Last but not least, we also want to see how things work out with remote containers. You probably guess it: the [official Microsoft documentation](https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers?WT.mc_id=DT-MVP-5004195) got you covered.

>> _Remark: I personally also like the description on that topic on the [Visual Studio Code page](https://code.visualstudio.com/blogs/2020/07/01/containers-wsl) quite useful as supplementary material._

Phew, quite some things to make sure, but now we are good to go.  

## What's New in Local Development with Azurite

Local development of Azure Durable Functions comes with one central prerequisite: a _storage emulator_ in order to allow the Durable Functions to store their state and context locally. This was possible on Windows systems for quite some time via the _[Microsoft Azure Storage Emulator](https://docs.microsoft.com/en-us/azure/storage/common/storage-use-emulator?WT.mc_id=DT-MVP-5004195)_. 

As Microsoft aims to support cross-platform development there was an alternative for MacOS and Linux systems called _[Azurite](https://github.com/azure/azurite)_. Unfortunately, this emulator came with one flaw: it did not support the table storage features needed for Azure Durable Functions.

However, things changed on the first of May 2021 when release [3.12.0](https://github.com/Azure/Azurite/releases/tag/v3.12.0) came out: it contained a preview of the needed Table Service. 

This means all signs on go for developing Azure Durable Function in a local setup in WSL2.  

>> _Remark: The Microsoft Azure Storage Emulator is in maintenance mode, so no new features of the Azure Storage API will be supported. If you are developing on Windows I also recommend to get accommodated with Azurite there._      

## Installing Azurite

First of all we open a shell into our Linux (Ubuntu) system. I would recommend to use the [Windows Terminal](https://www.microsoft.com/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab) for that.  

Azurite is available as npm package and as a docker image. For this blog post we install Azurite as an npm package in our WSL2 environment via:

```bash
npm install -g azurite
``` 
Azurite needs a directory to store its data, so we create one e.g. in the home directory:

```bash
mkdir ~/azurite_storage
```  
Next we can spin up the emulator via the following command:

```bash
azurite -s -l /home/<YOUR USER>/azurite_storage -d /home/<YOUR USER>/azurite_storage/debug.log'
```
The output should then look like this:
![Azurite Startup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmt0zb8pqnywsfyhhec9.png)

We can also check the directory that we pointed Azurite to and will see that some basic setup took place:

![Azurite Basic Storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsoutqxo7ufzskl1n33g.png)

With that we can start playing with Azure Durable Functions.

>> _Remark: You have a lot of options in the Azurite CLI to fine tune your setup. They are listed on the [GitHub page](https://github.com/Azure/Azurite) of the project._      

## Local Development in WSL2 with Azurite

Let us start with one simple "Hello World"-ish Durable Function that comes out of the box with the template for Durable Functions in the Azure Functions Extension for VS Code. 

We start VS Code from WSL2 and:

* [Create our local project](https://docs.microsoft.com/azure/azure-functions/durable/quickstart-js-vscode#create-an-azure-functions-project)
* [Install the Durable Functions npm package](https://docs.microsoft.com/en-us/azure/azure-functions/durable/quickstart-js-vscode#install-the-durable-functions-npm-package)
* [Create the Orchestrator Function](https://docs.microsoft.com/en-us/azure/azure-functions/durable/quickstart-js-vscode#orchestrator-function)
* [Create the Activity Function](https://docs.microsoft.com/en-us/azure/azure-functions/durable/quickstart-js-vscode#activity-function)   
* [Create the Client Function](https://docs.microsoft.com/en-us/azure/azure-functions/durable/quickstart-js-vscode#client-function-http-starter)

If you choose TypeScript as programing language make sure that your dev dependencies in the `project.json` file contain the node types (`@types/node`), otherwise your build will fail. 

Before we start the Azure Functions, we need to make sure that the Azure Function runtime knows where to look for the storage. We adjust the `local.setting.json` file accordingly by setting the value for the `AzureWebJobsStorage` to use the development storage :

```json
 "AzureWebJobsStorage": "UseDevelopmentStorage=true"
```
Is this already sufficient  to start and execute the function? Let us find it out and start the function via (I used TypeScript):

```bash
npm run start
```
The output should finally look like this:

![Durable Function Startup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mekhtn726edyzpka27kx.png)

Looks good so far, so let us see if we can call it by opening a browser in Windows and navigating to the URL:

![Execution Durable Function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbno2usk0zpoi7gd4qbd.png)

The result is as expected:

![Result Function Execution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tb5cr5zxqeh2txzmb9l.png)

Next let us check what we need to do to access the storage emulator by opening the Azure Storage Explorer in Windows. Without any further setting we navigate to the local and attached storage accounts and find the expected tables and entries:

![Azure Storage Explorer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqemkfcu1cdv7luf91s4.png)

That was nearly too easy to set up. All works as we are used to in the Windows setup. No tweaking around with ports to be forwarded etc., it all works out of the box. 

When using WSL2 we have one further option for our development namely _remote containers_. Let us see how things work out there.  

## Local Development in WSL2 with Azurite and Remote Containers

As all prerequisites for remote containers are already in place we can directly jump into the development part. In contrast to the previous section, we start VS Code and re-open the directory in a remote container:

1. We tell VS Code to open the directory in a remote container via the command palette:

  ![File in Container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dn0sej6brclfwq4s43gh.png)

2. We confirm the path to the directory:

  ![Confirm Path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/raqffnu210hpd1j1ua5j.png)

3. We specify the development container specification:

  ![Development Container Specification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/up3j4nqlx6ahv3xx6erp.png)

If you do the last step the very first time, this might take a bit as the container image must be downloaded and a build must be executed. 

After that you will see that you are working in a container (lower left corner of VS Code):

![Dev Container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykzgglaup086geikapsu.png)

As in the section before we build a sample Durable Function using the Azure Functions extension. The final structure should look similar to this:

![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62l3mbedtq480bosiq93.png)

The only difference to the setup before is the `.devcontainer` file that contains the configuration of the remote container.

As before we point the `AzureWebJobsStorage` to use the storage emulator:  

```json
 "AzureWebJobsStorage": "UseDevelopmentStorage=true"
```

Let us start the function and see if things work as before. The result is ... no:

![Dev Container error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytm7qevbsjtiwjua1lfi.png)

Something went wrong here, but why? The Azurite emulator is up and running and the connection string points to the local emulator, so what is missing? 

In contrast to the scenario before, we are now running in a _container_. The container has no connection to Azurite that is running outside of the container on the localhost.

The fix for this we enhance the connection string in `local.settings.json` to be able to access the localhost on the host system from within the container (see also [Docker for Windows - Networking](https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds):

```json
"AzureWebJobsStorage": "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://host.docker.internal"
``` 

We restart the functions and this time it starts up smoothly:

![Dev Container Startup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhxo8p13qg47jujcpgnj.png)

We can call the function from the Windows host running within the container using Azurite running in WSL2:

![Dev Container Function Execution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzmozawpfc7gg6ljl69t.png) 

So just one more configuration to specify and you can do all your development within containers on WSL2. Again a quite smooth experience.

>> _Remark: If you are developing in a WSL2 distro that is not your default distro make sure that it is available as resource in the docker configuration. This setting might be reset after an update of Docker, so in case you run into an error like "Docker Daemon not running" - first check this setting._

  ![Docker Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypq3hl2xd20zd0m6678r.png)
     
## Finalizing the setup

Let us do one final step to make the development experience even smoother. When we started Azurite the command to key in was quite lengthy and we do not want to type that in every time. To make things a bit easier we will define an alias for the command and store it in `~/.bashrc`:

```bash
alias AzuriteUp='azurite -s -l /home/<YOUR USER>/azurite_store -d /home/<YOUR USER>/azurite_store/debug.log'
```

In addition we might want to clean up the local Azurite storage from time to time. To do so you must delete the content of the directory you pointed Azurite to (see [GitHub Azurite - Workspace Structure](https://github.com/Azure/Azurite#workspace-structure). Therefore let us define another alias for that:

```bash
alias AzuriteClean='rm -r /home/<YOUR USER>/azurite_storage/*'
``` 

Finally, source the changes to make them available:

```bash
source ~/.bashrc
``` 

>> _Remark: There is also a [VS Code Extension for Azurite](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite). However, as writing this blog post the support for operations on the table storage is not yet there. If the extension contains that, this would probably be the preferred way to interact with Azurite._ 

## Summary

I hope this blog post helped you with getting your local development of Azure Durable Functions started in WSL2 with Azurite. 

Now it is play time to find out what else is possible - Have fun!