使用 Azurite 模拟器进行本地 Azure 存储开发

Azurite 开源仿真器提供一个免费的本地环境,用于测试 Azure Blob、队列存储和表存储应用程序。 如果你对应用程序在本地的工作状况感到满意,可以改用云中的 Azure 存储帐户。 该仿真器在 Windows、Linux 和 macOS 上提供跨平台支持。

Azurite 是未来的存储仿真器平台。 Azurite 取代了 Azure 存储仿真器。 Azurite 将持续更新,以支持最新版本的 Azure 存储 API。

可通过多种不同的方法在本地系统上安装并运行 Azurite。 选择这些选项卡中的任意一个。

安装 Azurite

Azurite 在 Visual Studio 2022 自动可用。 如果运行的是早期版本的 Visual Studio,则需要使用节点包管理器或 DockerHub 或者通过克隆 Azurite GitHub 存储库来安装 Azurite。

运行 Azurite

通过一些配置,Azure Functions 或 ASP.NET 项目会自动启动 Azurite。 对于所有其他项目类型,必须从命令行启动 Azurite。

从命令行运行 Azurite

可以在 Visual Studio 安装的扩展文件夹中找到 Azurite 可执行文件。 具体位置根据安装的 Visual Studio 版本而有所不同。 例如,如果已在 Windows 计算机或虚拟机 (VM) 上安装 Visual Studio 2022 专业版,可在此位置找到 Azurite 可执行文件:C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator

运行可执行文件后,Azurite 将侦听连接。

Azurite 命令行输出

从 Azure Functions 项目运行 Azurite

在 Visual Studio 2022 中,创建一个 Azure Functions 项目。 创建项目时,请选择“存储仿真器”。

Azure Functions 项目中的存储模拟器选项

创建项目后,Azurite 会自动启动。

Azure Functions 项目中的 Azurite 命令行输出

从 ASP.NET 项目运行 Azurite

在 Visual Studio 2022 中,创建 ASP.NET Core Web App 项目。 然后打开“连接的服务”对话框,选择“添加服务依赖项”,然后选择“存储 Azurite 仿真器” 。

ASP.NET Core Web 应用项目中的“连接服务”对话框

在“配置存储 Azurite 仿真器”对话框,将“连接字符串名称”字段设置为 StorageConnectionString,然后选择“完成” 。

配置存储 Azurite 模拟器对话框

配置完成后,选择“关闭”。 Azurite 仿真器会自动启动。

ASP.NET 项目中的 Azurite 命令行输出

命令行选项

本部分详细说明启动 Azurite 时可用的命令行开关。

帮助

可选 - 通过使用 -h--help 开关获取命令行帮助。

azurite -h
azurite --help

Blob 侦听主机

可选 - 默认情况下,Azurite 将侦听本地服务器 127.0.0.1。 可根据需要使用 --blobHost 开关设置地址。

仅接受本地计算机上的请求:

azurite --blobHost 127.0.0.1

允许远程请求:

azurite --blobHost 0.0.0.0

注意

允许远程请求可能会导致系统容易受到外部攻击。

Blob 侦听端口配置

可选 - 默认情况下,Azurite 将在端口 10000 上侦听 Blob 服务。 使用 --blobPort 开关可指定所需的侦听端口。

注意

使用自定义端口后,需要在 Azure 存储工具或 SDK 中更新连接字符串或相应的配置。

自定义 Blob 服务侦听端口:

azurite --blobPort 8888

让系统自动选择可用端口:

azurite --blobPort 0

Azurite 启动期间,会显示正在使用的端口。

队列侦听主机

可选 - 默认情况下,Azurite 将侦听本地服务器 127.0.0.1。 可根据需要使用 --queueHost 开关设置地址。

仅接受本地计算机上的请求:

azurite --queueHost 127.0.0.1

允许远程请求:

azurite --queueHost 0.0.0.0

注意

允许远程请求可能会导致系统容易受到外部攻击。

队列侦听端口配置

可选 - 默认情况下,Azurite 将在端口 10001 上侦听队列服务。 使用 --queuePort 开关可指定所需的侦听端口。

注意

使用自定义端口后,需要在 Azure 存储工具或 SDK 中更新连接字符串或相应的配置。

自定义队列服务侦听端口:

azurite --queuePort 8888

让系统自动选择可用端口:

azurite --queuePort 0

Azurite 启动期间,会显示正在使用的端口。

表侦听主机

可选 - 默认情况下,Azurite 将侦听本地服务器 127.0.0.1。 可根据需要使用 --tableHost 开关设置地址。

仅接受本地计算机上的请求:

azurite --tableHost 127.0.0.1

允许远程请求:

azurite --tableHost 0.0.0.0

注意

允许远程请求可能会导致系统容易受到外部攻击。

表侦听端口配置

可选 - 默认情况下,Azurite 将在端口 10002 上侦听表服务。 使用 --tablePort 开关可指定所需的侦听端口。

注意

使用自定义端口后,需要在 Azure 存储工具或 SDK 中更新连接字符串或相应的配置。

自定义表服务侦听端口:

azurite --tablePort 11111

让系统自动选择可用端口:

azurite --tablePort 0

Azurite 启动期间,会显示正在使用的端口。

工作区路径

可选 - 在执行过程中,Azurite 会将数据存储到本地磁盘。 使用 -l--location 开关可将某个路径指定为工作区位置。 默认将使用当前进程的工作目录。 请注意小写的“l”。

azurite -l c:\azurite
azurite --location c:\azurite

访问日志

可选 - 默认情况下,访问日志会显示在控制台窗口中。 使用 -s--silent 开关可以禁止显示访问日志。

azurite -s
azurite --silent

调试日志

可选 - 调试日志包括有关每个请求和异常堆栈跟踪的详细信息。 在 -d--debug 开关中提供有效的本地文件路径可以启用调试日志。

azurite -d path/debug.log
azurite --debug path/debug.log

松散模式

可选 - 默认情况下,Azurite 应用严格模式来阻止不受支持的请求标头和参数。 使用 -L--loose 开关禁用严格模式。 请注意大写的“L”。

azurite -L
azurite --loose

版本

可选 - 通过使用 -v--version 开关显示已安装 Azurite 的版本号。

azurite -v
azurite --version

证书配置 (HTTPS)

可选 - 默认情况下,Azurite 使用 HTTP 协议。 启用 HTTPS 模式的方法是:向隐私增强邮件 (.pem) 提供路径,或者向 --cert 开关提供个人信息交换 (.pfx) 证书文件。

为 PEM 文件提供 --cert 时,必须提供相应的 --key 开关。

azurite --cert path/server.pem --key path/key.pem

为 PFX 文件提供 --cert 时,必须提供相应的 --pwd 开关。

azurite --cert path/server.pfx --pwd pfxpassword

若要详细了解如何创建 PEM 和 PFX 文件,请参阅 HTTPS 设置

OAuth 配置

可选 - 通过使用 --oauth 开关为 Azurite 启用 OAuth 身份验证。

azurite --oauth basic --cert path/server.pem --key path/key.pem

注意

OAuth 需要 HTTPS 终结点。 请确保通过提供 --cert 开关和 --oauth 开关来启用 HTTPS。

Azurite 通过为 --oauth 开关指定 basic 参数来支持基本身份验证。 Azurite 会执行基本身份验证,例如验证传入的持有者令牌;检查颁发者、受众和到期时间。 Azurite 不会检查令牌签名或权限。

跳过 API 版本检查

可选 - 启动时,Azurite 会检查请求的 API 版本是否有效。 以下命令会跳过 API 版本检查:

azurite --skipApiVersionCheck

禁用生产样式 URL

可选。 在请求 URI 主机中使用完全限定的域名(而不是 IP)时,默认情况下,Azurite 将分析来自请求 URI 主机的存储帐户名称。 可以使用 --disableProductStyleUrl 从请求 URI 路径强制分析存储帐户名称:

azurite --disableProductStyleUrl

工具和 SDK 的授权

使用任何身份验证策略从 Azure 存储 SDK 或工具(例如 Azure 存储资源管理器)连接到 Azurite。 需要身份验证。 Azurite 支持使用 OAuth、共享密钥和共享访问签名 (SAS) 进行授权。 Azurite 还支持匿名访问公共容器。

如果使用的是 Azure SDK,请使用 --oauth basic and --cert --key/--pwd 选项启动 Azurite。

已知的存储帐户和密钥

Azurite 接受旧式 Azure 存储模拟器使用的同一个众所周知的帐户和密钥。

  • 帐户名称:devstoreaccount1
  • 帐户密钥:Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==

自定义存储帐户和密钥

Azurite 支持自定义存储帐户名称和密钥,但需将 AZURITE_ACCOUNTS 环境变量设置为以下格式:account1:key1[:key2];account2:key1[:key2];...

例如,使用包含一个密钥的自定义存储帐户:

set AZURITE_ACCOUNTS="account1:key1"
export AZURITE_ACCOUNTS="account1:key1"

注意

帐户密钥必须是 base64 编码的字符串。

也可使用多个存储帐户,每个存储帐户有两个密钥:

set AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"
export AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"

默认情况下,Azurite 每分钟刷新环境变量中的自定义帐户名和密钥。 利用此功能,可以动态轮换帐户密钥,或添加新的存储帐户,而无需重启 Azurite。

注意

设置自定义存储帐户时,将禁用默认的 devstoreaccount1 存储帐户。

帐户密钥必须是 base64 编码的字符串。

连接字符串

从应用程序连接到 Azurite 的最简单方法是在应用程序的配置文件中配置一个引用快捷方式 UseDevelopmentStorage=true 的连接字符串。 下面是 app.config 文件中的连接字符串示例:

<appSettings>
  <add key="StorageConnectionString" value="UseDevelopmentStorage=true" />
</appSettings>

HTTP 连接字符串

可将以下连接字符串传递到 Azure SDK 或者 Azure CLI 2.0 或存储资源管理器等工具。

完整的连接字符串为:

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;

若只连接到 blob 服务,则连接字符串为:

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;

若只连接到队列服务,则连接字符串为:

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;

若只连接到表服务,则连接字符串为:

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

HTTPS 连接字符串

完整的 HTTPS 连接字符串为:

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=https://127.0.0.1:10001/devstoreaccount1;TableEndpoint=https://127.0.0.1:10002/devstoreaccount1;

若只使用 blob 服务,则 HTTPS 连接字符串为:

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;

若只使用队列服务,则 HTTPS 连接字符串为:

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;QueueEndpoint=https://127.0.0.1:10001/devstoreaccount1;

若只使用表服务,则 HTTPS 连接字符串为:

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=https://127.0.0.1:10002/devstoreaccount1;

如果使用了 dotnet dev-certs 生成自签名证书,请使用以下连接字符串。

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://localhost:10000/devstoreaccount1;QueueEndpoint=https://localhost:10001/devstoreaccount1;TableEndpoint=https://localhost:10002/devstoreaccount1;

使用自定义存储帐户和密钥时,请更新连接字符串。

有关详细信息,请参阅配置 Azure 存储连接字符串

Azure SDK

若要将 Azurite 与 Azure SDK 配合使用,请使用 OAuth 和 HTTPS 选项:

azurite --oauth basic --cert certname.pem --key certname-key.pem

Azure Blob 存储

然后,可以实例化 BlobContainerClient、Blobserviceclient 或 BlobClient。

// With container URL and DefaultAzureCredential
var client = new BlobContainerClient(
    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"), new DefaultAzureCredential()
  );

// With connection string
var client = new BlobContainerClient(
    "DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;", "container-name"
  );

// With account name and key
var client = new BlobContainerClient(
    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"),
    new StorageSharedKeyCredential("devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
  );

Azure Queue Storage

还可以实例化 QueueClient 或 QueueServiceClient。

// With queue URL and DefaultAzureCredential
var client = new QueueClient(
    new Uri("https://127.0.0.1:10001/devstoreaccount1/queue-name"), new DefaultAzureCredential()
  );

// With connection string
var client = new QueueClient(
    "DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;QueueEndpoint=https://127.0.0.1:10001/devstoreaccount1;", "queue-name"
  );

// With account name and key
var client = new QueueClient(
    new Uri("https://127.0.0.1:10001/devstoreaccount1/queue-name"),
    new StorageSharedKeyCredential("devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
  );

Azure 表存储

还可以实例化 TableClient 或 TableServiceClient。

// With table URL and DefaultAzureCredential
var client = new Client(
    new Uri("https://127.0.0.1:10002/devstoreaccount1/table-name"), new DefaultAzureCredential()
  );

// With connection string
var client = new TableClient(
    "DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=https://127.0.0.1:10002/devstoreaccount1;", "table-name"
  );

// With account name and key
var client = new TableClient(
    new Uri("https://127.0.0.1:10002/devstoreaccount1/table-name"),
    new StorageSharedKeyCredential("devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
  );

Microsoft Azure 存储资源管理器

可以使用存储资源管理器查看存储在 Azurite 中的数据。

使用 HTTP 连接到 Azurite

在存储资源管理器中,按照以下步骤连接到 Azurite:

  1. 选择“管理帐户”图标
  2. 选择“添加帐户”
  3. 选择“附加到本地仿真器”
  4. 选择“下一步”
  5. 将“显示名称”字段编辑为所选名称
  6. 再次选择“下一步”
  7. 选择“连接”

使用 HTTPS 连接到 Azurite

默认情况下,存储资源管理器不会打开使用自签名证书的 HTTPS 终结点。 如果你是使用 HTTPS 来运行 Azurite,则可能使用的是自签名证书。 在存储资源管理器中,通过“编辑”->“SSL 证书”->“导入证书”对话框导入 SSL 证书。

将证书导入到存储资源管理器
  1. 在本地计算机上找到证书。
  2. 在存储资源管理器中转到“编辑”->“SSL 证书”->“导入证书”,然后导入你的证书。

如果不导入证书,则会出现错误:

unable to verify the first certificateself signed certificate in chain

通过 HTTPS 连接字符串添加 Azurite

按照以下步骤将 Azurite HTTPS 添加到存储资源管理器:

  1. 选择“切换资源管理器”
  2. 选择“本地和附加”
  3. 右键单击“存储帐户”,然后选择“连接到 Azure 存储”。
  4. 选择“使用连接字符串”
  5. 选择“下一步”。
  6. 在“显示名称”字段中输入值。
  7. 输入本文档上一部分中的 HTTPS 连接字符串
  8. 选择“下一步”
  9. 选择“连接”

工作区结构

初始化 Azurite 时,可以在工作区位置创建以下文件和文件夹。

  • __blobstorage__ - 目录,其中包含 Azurite blob 服务持久化二进制数据
  • __queuestorage__ - 目录,其中包含 Azurite 队列服务持久化二进制数据
  • __tablestorage__ - 目录,其中包含 Azurite 表服务持久化二进制数据
  • __azurite_db_blob__.json - Azurite blob 服务元数据文件
  • __azurite_db_blob_extent__.json - Azurite blob 服务盘区元数据文件
  • __azurite_db_queue__.json - Azurite 队列服务元数据文件
  • __azurite_db_queue_extent__.json - Azurite 队列服务盘区元数据文件
  • __azurite_db_table__.json - Azurite 表服务元数据文件
  • __azurite_db_table_extent__.json - Azurite 表服务盘区元数据文件

若要清理 Azurite,请删除以上文件和文件夹,然后重启仿真器。

Azurite 与 Azure 存储之间的差别

Azurite 本地实例与云中的 Azure 存储帐户在功能上有差别。

终结点和连接 URL

Azurite 的服务终结点不同于 Azure 存储帐户的终结点。 本地计算机不执行域名解析,要求 Azurite 终结点是本地地址。

对 Azure 存储帐户中的资源寻址时,帐户名称是 URI 主机名的一部分。 要寻址的资源是 URI 路径的一部分:

<http|https>://<account-name>.<service-name>.core.chinacloudapi.cn/<resource-path>

以下 URI 是 Azure 存储帐户中某个 Blob 的有效地址:

https://myaccount.blob.core.chinacloudapi.cn/mycontainer/myblob.txt

IP 样式 URL

由于本地计算机不解析域名,因此帐户名是 URI 路径的一部分,而不是主机名的一部分。 对 Azurite 中的资源使用以下 URI 格式:

http://<local-machine-address>:<port>/<account-name>/<resource-path>

可使用以下地址访问 Azurite 中的 Blob:

http://127.0.0.1:10000/myaccount/mycontainer/myblob.txt

生产样式 URL

你也可以修改主机文件以访问具有生产样式 URL 的帐户。

首先,在主机文件中添加一行或多行。 例如:

127.0.0.1 account1.blob.localhost
127.0.0.1 account1.queue.localhost
127.0.0.1 account1.table.localhost

接下来,设置环境变量以启用自定义存储帐户和密钥:

set AZURITE_ACCOUNTS="account1:key1:key2"

可以添加更多帐户。 请参阅本文的自定义存储帐户和密钥部分。

启动 Azurite 并使用自定义连接字符串访问你的帐户。 下面的示例连接字符串假设使用默认端口。

DefaultEndpointsProtocol=http;AccountName=account1;AccountKey=key1;BlobEndpoint=http://account1.blob.localhost:10000;QueueEndpoint=http://account1.queue.localhost:10001;TableEndpoint=http://account1.table.localhost:10002;

不要以这种方式使用 Azure 存储资源管理器访问默认帐户。 存在存储资源管理器总是在 URL 路径中添加帐户名称的 bug,从而导致失败。

默认情况下,将 Azurite 与生产样式 URL 一起使用时,帐户名应为完全限定的域名中的主机名,例如“http://devstoreaccount1.blob.localhost:10000/container"”。 若要在 URL 路径中使用具有帐户名的生产样式 URL,例如“http://foo.bar.com:10000/devstoreaccount1/container"”,请确保在启动 Azurite 时使用 --disableProductStyleUrl 参数。

如果使用 host.docker.internal 作为请求 URI 主机(例如:http://host.docker.internal:10000/devstoreaccount1/container),Azurite 将始终从请求 URI 路径中获取帐户名称。 无论在启动 Azurite 时是否使用 --disableProductStyleUrl 参数,都是如此。

缩放和性能

Azurite 不支持大量连接的客户端。 它不提供性能方面的保证。 Azurite 用于开发和测试目的。

错误处理。

Azurite 的错误处理逻辑与 Azure 存储相符,但存在一些差别。 例如,错误消息可能不同,而错误状态代码是一致的。

RA-GRS

Azurite 支持读取访问异地冗余复制 (RA-GRS)。 对于存储资源,可以通过在帐户名称后面追加 -secondary 来访问次要位置。 例如,以下地址可用于访问 Azurite 中使用只读辅助副本的 Blob:

http://127.0.0.1:10000/devstoreaccount1-secondary/mycontainer/myblob.txt

表支持

对 Azurite 中的表支持目前处于预览阶段。 有关详细信息,请参阅 Azurite V3 Table 项目。

支持持久函数需要表。

重要

对表存储的 Azurite 支持目前处于预览阶段。

Azurite 是开源的

欢迎为 Azurite 贡献作品和提出建议。 请访问 Azurite GitHub 项目页或 GitHub 问题了解产品里程碑,以及我们针对即将推出的功能和 bug 修复正在跟进的工作项。 GitHub 中也列出了详细的工作项。

后续步骤