Azure Storage Emulator in Docker
This post explains how to containerise the Azure Storage Emulator and how to reconfigure your .NET application to access it. This can be extremely useful when deploying a containerised application for testing and/or demonstration purposes.
Overview
The basic steps necessary to get the emulator working are:
- Install SQL Server 2012 LocalDB.
- Create a database for the emulator to use.
- Install the Azure Storage Emulator.
- Configure the emulator to use the database we created for it.
- Configure the emulator to listen on the correct IP address.
- Launch the emulator.
Initial preparation
- Create a new folder for your Docker container
- The Azure Storage Emulator requires SQL Server 2012 LocalDB. Unfortunately there is no direct download link for this MSI, instead you have to go to the SQL Server 2012 download page, click on the "Download" button, check the "ENU\x64\SqlLocalDB.msi" checkbox and then click on the "Next" button. Save the MSI into the folder you just created and make sure you save it as
SqlLocalDB.msi
.
mkdir azure-storage-emulator
cd azure-storage-emulator
Build the container image
Use the following as the basis for your dockerfile
:
# escape=`
FROM microsoft/windowsservercore
# SQL Server 2012 LocalDB
COPY SqlLocalDB.msi .
RUN Start-Process -FilePath msiexec -ArgumentList /q, /i, SqlLocalDB.msi, IACCEPTSQLLOCALDBLICENSETERMS=YES -Wait;
RUN "& 'C:\Program Files\Microsoft SQL Server\110\Tools\Binn\SqlLocalDB.exe' create azure -s"
# Azure Storage Emulator
ADD https://go.microsoft.com/fwlink/?linkid=717179&clcid=0x409 MicrosoftAzureStorageEmulator.msi
RUN Start-Process -FilePath msiexec -ArgumentList /q, /i, MicrosoftAzureStorageEmulator.msi -Wait;
RUN "& 'C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe' init /server '(localdb)\azure'"
EXPOSE 10000 10001 10002
# Configure and launch
COPY start.ps1 .
CMD .\start
The start.ps1
Powershell script is responsible for reconfiguring the emulator and launching it. It contains one little bit of magic to rewrite the default config file so that the emulator listens on the container's IP address, as by default it will only listen on 127.0.0.1, which is useless when it's isolated inside its own container:
# Find our external IP address
$ip = (get-netipaddress | where {$_.AddressFamily -eq "IPv4" -and $_.AddressState -eq "Preferred" -and $_.PrefixOrigin -ne "WellKnown" }[0]).IPAddress
# Rewrite AzureStorageEmulator.exe.config to use it
$config = "C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe.config"
(get-content $config) -replace "127.0.0.1",$ip | out-file $config
# Launch the emulator
& "C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" start -inprocess
Build the container image:
docker build -t azure-storage-emulator .
and then run it:
docker run --rm --name storage azure-storage-emulator
How to access it from another container
Modify your application's config file by replacing "UseDevelopmentStorage=true"
with the following, taking care to replace storage
with whatever name you gave your container.
"DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://storage:10000/devstoreaccount1;TableEndpoint=http://storage:10002/devstoreaccount1;QueueEndpoint=http://storage:10001/devstoreaccount1"
As documented here, the UseDevelopmentStorage
option is just shorthand for a full connection string that points to 127.0.0.1
.