【问题标题】:Connecting to azurite using a hostname fails使用主机名连接到 azurite 失败
【发布时间】:2020-04-24 04:29:51
【问题描述】:

更新:我可以验证此行为已在 Azure.Storage.Blobs 12.5.1 https://www.nuget.org/packages/Azure.Storage.Blobs https://github.com/Azure/azure-sdk-for-net/issues/9404 中得到修复


如何使用主机名连接到 azurite?

我正在尝试使用 Azurite 在 docker 中模拟 Azure Blob Storage 以进行集成测试。

一切正常,以至于我必须通过主机名访问 Azurite(这是 Docker 网络所需的 AFAIK)

我的连接字符串如下所示(这是默认的知名连接字符串):

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

我的 docker compose 部分为 azurite 如下所示:

services:
  azurite:
    image: mcr.microsoft.com/azure-storage/azurite
    hostname: azurite
    command: "azurite-blob --loose --blobHost 0.0.0.0"
    ports:
      - "10000:10000"
    volumes:
      - ./test/azurite:/data
    networks:
      - stillsnet

  images:
    container_name: images
    image: myapp/images
    build:
      context: .
      dockerfile: Dockerfile
    ports:
       - "5000:5000"
       - "5001:5001"
    environment:
      - ASPNETCORE_ENVIRONMENT=Test
      - ASPNETCORE_URLS=http://+:5000
      - imagesStorage__AzureBlobStorage__ConnectionString=AccountName=devstoreaccount1;DefaultEndpointsProtocol=http;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000;
    depends_on:
      - azurite
    links:
      - azurite
    networks:
      - stilssnet

我的代码如下所示:

private const string ConnectionString ="AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://azurite:10000/devstoreaccount1;";

[Fact]
public async Task UploadFile()
{
   var container = new BlobContainerClient(ConnectionString, "images");
   await using var stream = File.OpenRead(@"C:\temp\output\3ee9bc41-40ea-4d05-b180-e74bd5065622\images\00000000.jpg");
   await container.UploadBlobAsync("test.jpg", stream);
}

这会抛出异常:

System.Xml.XmlException : Root element is missing.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
   at System.Xml.Linq.XDocument.Load(Stream stream, LoadOptions options)
   at Azure.Storage.Blobs.BlobRestClient.Container.CreateAsync_CreateResponse(Response response)
   at Azure.Storage.Blobs.BlobRestClient.Container.CreateAsync(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri resourceUri, PublicAccessType access, Nullable`1 timeout, IDictionary`2 metadata, String requestId, Boolean async, String operationName, CancellationToken cancellationToken)
   at Azure.Storage.Blobs.BlobContainerClient.CreateInternal(PublicAccessType publicAccessType, IDictionary`2 metadata, Boolean async, CancellationToken cancellationToken, String operationName)
   at Azure.Storage.Blobs.BlobContainerClient.CreateIfNotExistsInternal(PublicAccessType publicAccessType, IDictionary`2 metadata, Boolean async, CancellationToken cancellationToken)
   at Azure.Storage.Blobs.BlobContainerClient.CreateIfNotExistsAsync(PublicAccessType publicAccessType, IDictionary`2 metadata, CancellationToken cancellationToken)

如果我将连接字符串从azurite 更改为127.0.0.1,一切正常。

【问题讨论】:

  • 你解决过这个问题吗?我也有同样的问题...
  • @the_witch_king_of_angmar 只有我在下面描述的黑客,我已经在 Azure 存储 SDK 提交了一个错误
  • @the_witch_king_of_angmar 此行为已在 Azure.Storage.Blobs 12.5.1 中修复

标签: c# azure-blob-storage


【解决方案1】:

更新:我可以验证此行为已在 Azure.Storage.Blobs 12.5.1 https://www.nuget.org/packages/Azure.Storage.Blobs 中得到修复 https://github.com/Azure/azure-sdk-for-net/issues/9404


如果您使用 localhost 或 IP 地址以外的任何其他内容,BlobContainerClient 本身似乎会从 URL 中删除帐户名称,因此客户端会生成以下内容:

PUT /images?restype=container HTTP/1.1" 400 - 代替 PUT /devstoreaccount1/images?restype=containerHTTP/1.1 201

作为一个丑陋的解决方法,我们可以在针对 azurite 进行测试时在容器名称中包含帐户名称: var container = new BlobContainerClient(ConnectionString, "devstoreaccount1/images");

虽然 await container.CreateIfNotExistsAsync();对蓝铜矿不能正常工作(当它已经存在时抛出 409 异常......

所以我们要么有:

  • 丑陋的黑客攻击
  • 放弃蓝铜矿以支持真正的 blob 存储帐户
  • 删除 BlobContainerClient,这似乎基于主机名执行了太多魔法。

它似乎与 Azurite 本身无关,或者理想情况下它应该支持与 Azure blob 存储兼容的根 URL,而无需指定帐户名前缀。

【讨论】:

    【解决方案2】:

    该网络中的主机名是 azurite,因此您可以使用此连接字符串 UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://azurite

    为我工作,我认为是这样做的方法。

    您还可以使用旧版存储模拟器(包括表格),而不是您放置的 azurite docker.host.internal

    【讨论】:

    • 不幸的是,似乎对我不起作用,我得到了同样的例外
    【解决方案3】:

    问题的根源在于 azure-storage-queue 库内部如何拆分 URL。我的问题是通过使用较新版本的连接器来解决的。我知道它是 c# 线程,但在 java 中我遇到了同样的问题。如果c#版本号相同,请使用12.6.0-beta.1或更高版本。

    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-storage-queue</artifactId>
        <version>12.6.0-beta.1</version>
    </dependency>
    

    12.0.1 版似乎无法正常工作。

    【讨论】:

    【解决方案4】:

    我用这个命令运行了 azurite(来自 docker hub 页面https://hub.docker.com/_/microsoft-azure-storage-azurite?tab=description

    docker run -p 10000:10000 -p 10001:10001 mcr.microsoft.com/azure-storage/azurite

    我的配置文件是这样的:

    <add name="BlobStorage" connectionString="UseDevelopmentStorage=true" />
    

    在连接字符串部分 (从页面: https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azurite#install-and-run-the-azurite-docker-image)

    【讨论】:

    • 当然可以,但是当您想使用 docker 网络从另一个容器开始使用 Azurite 时会出现我的问题。您需要提供主机名,因为它是不同的容器,因此 UseDevelopmentStorage=true 不会不行。
    【解决方案5】:

    我同时运行 Sql server 和 Azurite。我只是使用 docker compose 来启动它们。注意重启:总是。这将在 docker 启动时启动容器。 就像运行已安装的 Azure 存储模拟器一样。

    version: "2"
    
    services:
    
      sql-server-db:
        container_name: sql-server-db
        image: microsoft/mssql-server-linux:2017-latest
        restart: always
        ports:
          - "1433:1433"
          - "1434:1434"
        environment:
          SA_PASSWORD: "<EnterYourPasswordHere!!!>"
          ACCEPT_EULA: "Y"
    
      azure_storage_emulator:
        container_name: azurite
        image: mcr.microsoft.com/azure-storage/azurite
        restart: always
        ports:
          - "10001:10001"
          - "10000:10000"
    

    【讨论】:

    • 嗨,迈克,谢谢!是的,这确实很可爱。现在,如果您成功地将另一个容器添加到连接到 Azurite 的 docker compose 并告诉我您是如何做到的,您将回答我的问题 :)
    猜你喜欢
    • 1970-01-01
    • 2020-07-15
    • 2011-07-20
    • 2014-03-21
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    相关资源
    最近更新 更多