How to: Use Azurite as a service container in Codespaces or Devcontainers
When developing with Azure Storage, it can significantly speed up your development process if you can use a local development environment, rather than constantly connecting directly to storage in Azure itself. This is where Azurite comes in – Azurite is a local storage emulator for Azure Storage, mimicing blob/container, queue and table storage. While there are lots of ways to get it running (e.g. from binary, manually using Docker etc.), I wanted to set it up as a service container in my devcontainer configuration which provides a few benefits:
- consistency – every time i rebuild my devcontainer i know i’m resetting Azurite back to a known, clean state
- Isolation – running it in a separate container means i avoid any potential side effects which might arise if it’s running in my main development container
- Portability – it works consistently on Github codespaces, local devcontainer setups etc.
This guide provides a basic outline for setting up Azurite as a service container in a devcontainer configuration.
Create docker-compose.yml
to define the services
Using a docker compose file inside your devcontainer definition lets you define multiple ‘services’ which all work together. In my case, i’ve set up the devcontainer
service which is the main development environment based on the Microsoft Python devcontainer image, and azurite
which contains azurite. Of course you could add whatever you need – PostgreSQL, Mongo, whatever you need. Here’s my docker-compose
file:
services: devcontainer: image: mcr.microsoft.com/devcontainers/python:1-3.11-bullseye platform: linux/amd64 volumes: - ..:/workspace:delegated ports: - "5000:5000" environment: - POETRY_VIRTUALENVS_IN_PROJECT=true command: /bin/sh -c "while sleep 1000; do :; done" network_mode: "host" azurite: image: mcr.microsoft.com/azure-storage/azurite ports: - "127.0.0.1:10000:10000" - "127.0.0.1:10001:10001" - "127.0.0.1:10002:10002" command: > azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0
Create devcontainer.json
After defining your services, you need to create a devcontainer.json
file. This configures the development environment, and its in the dockerComposeFile
attribute that you point to your docker-compose file, and defining the service
which represents the actual devcontainer. I’ve added a bunch of features which . In my configuration, i’ve also disabled some extensions which are recommended by the base image or other feature extensions by prefixing their names with -
. Finally, i included a postCreateCommand
which marks the /workspace
folder as safe, and installs dependencies using Poetry, although you may want to skip this last step.
{ "name": "Python 3", "dockerComposeFile": ["docker-compose.yml"], "workspaceFolder": "/workspace", "service": "devcontainer", "features": { "ghcr.io/devcontainers-contrib/features/poetry:2": {"version": "1.8.3"}, "ghcr.io/devcontainers/features/github-cli:1": {}, "ghcr.io/devcontainers/features/node:1": {}, "ghcr.io/devcontainers/features/azure-cli:1": {}, "ghcr.io/flexwie/devcontainer-features/pulumi:1": {}, "ghcr.io/prulloac/devcontainer-features/pre-commit:1": {}, "ghcr.io/jlaundry/devcontainer-features/azure-functions-core-tools:1": {}, "ghcr.io/devcontainers/features/rust:1": {}, // for cryptography package "ghcr.io/devcontainers/features/docker-outside-of-docker": {} }, "customizations": { "vscode": { "extensions": [ "-vadimcn.vscode-lldb", "-rust-lang.rust-analyzer", "-tamasfe.even-better-toml", "-dbaeumer.vscode-eslint" ] } }, "forwardPorts": [10000, 10001, 10002], "postCreateCommand": "git config --global --add safe.directory /workspace && poetry self add poetry-plugin-export && poetry config warnings.export false && poetry config virtualenvs.in-project true --local && poetry install --with dev --no-interaction --sync --no-root" }
Next steps
You can connect to the locally emulated storage using a connection string based on a well-known account and key baked in to Azurite:
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;
You might choose to add more advanced configuration, such as persistent storage, or enabling OAuth (to allow the use of the DefaultAzureCredential
).
Finally, you can add additional services, such as PostgreSQL or Mongo, to aid your development process.