It's great to be able to develop locally without needing a "real" database to connect to. Azurite is an Azure Storage emulator which exists to support just that. This post demonstrates how to run Azurite v3 in a dev container, such that you can access the Table Storage API, which is currently in preview.
Azurite v3.12.0 recently shipped, and with it came:
Preview of Table Service in npm package and docker image. (Visual Studio Code extension doesn't support Table Service in this release)
You'll note that whilst there's a VS Code extension for Azurite, it doesn't have support for the Table Service yet. However, we do have it available in the form of a Docker image. So whilst we may not be able to directly use the Table APIs of Azurite in VS Code, what we could do instead is use a dev container.
We'll start by making ourselves a new directory and open VS Code in that location:
We're going to initialise a dev container there for function apps based upon the example Azure Functions & C# - .NET Core 3.1 container. We'll use it later to test our Azurite connectivity. To do that let's create ourselves a
And inside there we'll add a
As we can see, we're referencing a
docker-compose.yml file; let's add that:
It consists of two services;
azurite is the Docker image of Azurite, which exposes the Azurite ports so
app can access it. Note the name of
azurite; that will turn out to be significant later. We're actually only going to use the Table Storage port of
10002, but this would allow us to use Blobs and Queues also. The
azurite service is effectively going to be executing this command for us when it runs:
Now let's look at
app. This is our Azure Functions container. It references a
Dockerfile which we need to add:
We now have ourselves a dev container! VS Code should prompt us to reopen inside the container:
Now we're inside our container, we're going to make ourselves a function app that will use Azurite. Let's fire up the terminal in VS Code and create a function app containing a simple HTTP function:
We need to add a package for the APIs which interact with Table Storage:
The name is somewhat misleading, as it's both for Cosmos and for Table Storage. Famously, naming things is hard 😉.
Our mission is to be able to write and read from Azurite Table Storage. We need something to read and write that we care about. I like to visit Kew Gardens and so let's imagine ourselves a system which tracks visitors to Kew.
We're going to add a class called
Now we have our entity, let's add a class called
HelloAzuriteTableStorage which will contain functions which interact with the storage:
There's a couple of things to draw attention to here:
AZURITE_TABLESTORAGE_CONNECTIONSTRING- this mega string is based upon the Azurite connection string docs. The account name and key are the Azurite default storage accounts. You'll note we target
azuritehere is replacing the standard
127.0.0.1where Azurite typically listens. This
azuritename comes from the name of our service in the
We're creating two functions
SaveVisitcreates an entry in our storage to represent someone's visit. It's a hardcoded value representing me, and we're exposing a write operation at a
GETendpoint which is not very RESTful. But this is a demo and Roy Fielding would forgive us.
GetTodaysVisitsallows us to read back the visits that have happened today.
Let's see if it works by entering
func start and browsing to
Looking good. Now let's see if we can query them at
You may be thinking "This is great! But in the end I need to write to Azure Table Storage itself; not Azurite."
That's a fair point. Fortunately, it's only the connection string that determines where you read and write to. It would be fairly easy to dependency inject the appropriate connection string, or indeed a service that is connected to the storage you wish to target. If you want to make that happen, you can.