使用 .NET Core、SQL Server、Elasticsearch 和 cerebro 服务的 Docker Compose

Docker compose with .NET Core, SQL Server, Elasticsearch, and cerebro services

提问人:Francesco 提问时间:8/17/2021 最后编辑:Francesco 更新时间:6/25/2023 访问量:1723

问:

我正在尝试使用 docker-compose 文件运行许多服务。 首先,假设 Docker 版本 20.10.3 运行在 Red Hat Enterprise Linux 版本 8.3 上。

这是 docker-compose 文件:

version: "3.8"
services:
  projmssql:
    image: "mcr.microsoft.com/mssql/server:2019-latest"
    container_name: proj-core-sqlserver
    environment:
        SA_PASSWORD: "mypassword"
        ACCEPT_EULA: "Y"
    ports:
      - "1401:1433"
    volumes:
      - type: bind
        source: ./data-mssql
        target: /var/opt/mssql/data
      - type : bind
        source: ./log-mssql
        target: /var/opt/mssql/log
    restart: always
  projelastic:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1
    container_name: proj-core-elastic
    environment:
      - node.name=es01
      - cluster.name=proj-docker-cluster
      - discovery.type=single-node
      - bootstrap.memory_lock=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
      - path.repo=/usr/share/elasticsearch/backup
      - path.logs=/usr/share/elasticsearch/logs
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - type: bind
        source: ./data-es01
        target: /usr/share/elasticsearch/data
      - type : bind
        source: ./_backup-es01
        target: /usr/share/elasticsearch/backup
      - type : bind
        source: ./logs-es01
        target: /usr/share/elasticsearch/logs
    ports:
      - 9220:9200
      - 9320:9300
  projcerebro:
    image: lmenezes/cerebro
    container_name: proj-core-cerebro
    ports:
      - "9020:9000"
    command:
      - -Dhosts.0.host=http://projelastic:9200
  projapi:
    image: proj/projcoreapp 
    depends_on:
       - projmssql
    container_name: proj-core-api
    ports:
      - "8080:80"
    restart: always
    #Specify Environment Variables for the Api Service
    environment: 
      - ASPNETCORE_ENVIRONMENT=Docker
      

projApi 服务来自我的本地映像 (proj/projcoreapp),该映像使用以下 Dockerfile 构建:

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
WORKDIR /app

COPY . ./
RUN dotnet publish proj.api.net -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build-env /app/out .

ENTRYPOINT ["dotnet", "Proj.Api.dll"]

在我的 .net core 应用程序中,我有一个专用的 appsettings。Docker.json 文件

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Elasticsearch": {
    "Server": "http://projelastic:9200",
    "DebugMode": true,
    "UpdateMapping": false
  },
  "ConnectionStrings": {
    "DatabaseConnection": "Server=projmssql;Database=PROJ-NET;Persist Security Info=False;User ID=sa;Password=mypassword;MultipleActiveResultSets=True;TrustServerCertificate=False;Connection Timeout=30;"
  }
}

API .net 核心项目的.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DocumentationFile></DocumentationFile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="5.0.5" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
    <PackageReference Include="Microsoft.Identity.Web" Version="1.9.1" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.14" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\domain.net\Domain.csproj" />
  </ItemGroup>

</Project>

域库的.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="Entities\Organisation.cs" />
    <Compile Remove="Entities\OrganisationTeam.cs" />
    <Compile Remove="Entities\OrganisationTeamRole.cs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Elasticsearch.Net" Version="7.10.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.5" />
    <PackageReference Include="NEST" Version="7.10.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>

  <ItemGroup>
    <Folder Include="Utilities\" />
    <Folder Include="ViewModels\" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\filter.net\Filter.csproj" />
  </ItemGroup>

</Project>

筛选器库的.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Elasticsearch.Net" Version="7.10.0" />
    <PackageReference Include="GeoJSON.Net" Version="1.2.19" />
    <PackageReference Include="NEST" Version="7.10.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>

  <ItemGroup>
    <Folder Include="Entities\" />
    <Folder Include="Helpers\" />
    <Folder Include="ViewModelMapper\" />
  </ItemGroup>

</Project>

在我的.net核心启动中,我有以下配置

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ProjdbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection"))
            );
            services.AddScoped<IProjUserService, ProjUserService>();
            services.AddSingleton<IProjEntitiesService>(s =>
                new ProjEntitiesService
                (
                    Configuration.GetValue<string>("Elasticsearch:Server"),
                    Configuration.GetValue<bool>("Elasticsearch:DebugMode"),
                    Configuration.GetValue<bool>("Elasticsearch:UpdateMapping")
                ));

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {

现在让我们谈谈这个问题: 一旦我运行了docker-compose文件,所有服务都会正常运行,并且我可以从主机与所有这些服务进行交互。API 服务能够在内部连接到数据库,但是一旦我运行一些 API 来与 elasticsearch 服务交互,就会收到以下错误:

Elasticsearch.Net.UnexpectedElasticsearchClientException: The information requested is unavailable on the current platform.
 ---> System.PlatformNotSupportedException: The information requested is unavailable on the current platform.
   at System.Net.NetworkInformation.StringParsingHelpers.ParseActiveTcpConnectionsFromFiles(String tcp4ConnectionsFile, String tcp6ConnectionsFile)
   at System.Net.NetworkInformation.LinuxIPGlobalProperties.GetActiveTcpConnections()
   at Elasticsearch.Net.Diagnostics.TcpStats.GetStates()
   at Elasticsearch.Net.HttpConnection.Request[TResponse](RequestData requestData)
   at Elasticsearch.Net.RequestPipeline.CallElasticsearch[TResponse](RequestData requestData)
   at Elasticsearch.Net.Transport`1.Request[TResponse](HttpMethod method, String path, PostData data, IRequestParameters requestParameters)
   --- End of inner exception stack trace ---

正如我所说,所有服务都正常工作,甚至 Cerebro 服务也能够在内部连接到 elasticsearch 服务,因此看起来仅与 .net 核心服务有关。

我找不到有关上述问题的任何主题,所以我希望这里有人可以帮助我弄清楚。

PS:本地部署在 Windows 计算机(Kestrel Web 服务器)上的 .NET Core API 可以正常运行,连接到数据库和 elasticsearch,两者都在 Docker 上运行。

更新:

我忘了提到这台机器在公司代理后面运行。牢记这一点,我想检查我的 API 服务是否能够访问 Elasticsearch 服务端点:。 为此,我在我的 API 服务容器上执行了一个交互式 bash shell:.在这里,我注意到我的容器无法访问互联网http://projelastic:9200docker exec -it proj-core-api /bin/bash

root@8e7c81f98455:/app# apt-get update
Err:1 http://security.debian.org/debian-security buster/updates InRelease
  Could not connect to security.debian.org:80 (111: Connection refused) 

因此,我在 docker-compose 文件中添加了代理服务器的变量,包括 Elasticsearch 服务域的no_proxy变量。

projapi:
    image: proj/projcoreapp 
    depends_on:
       - projmssql
    container_name: proj-core-api
    ports:
      - "8080:80"
    restart: always
    #Specify Environment Variables for the Api Service
    environment: 
      - ASPNETCORE_ENVIRONMENT=Docker
      - http_proxy=http://user:pwd@address      
      - https_proxy=http://user:pwd@address
      - no_proxy=projelastic

通过上述更改,我能够在我的 API 容器中安装 curl 并执行我的初始测试:

root@0573a44a6836:/app# curl -X GET http://projelastic:9200
{
  "name" : "es01",
  "cluster_name" : "proj-docker-cluster",
  "cluster_uuid" : "j7mdpxkrSRKxpHnktvnZIw",
  "version" : {
    "number" : "7.10.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
    "build_date" : "2020-12-05T01:00:33.671820Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

无论如何,添加代理变量并不能解决最初的错误,因此作为最终测试,我将源代码放在运行代理且没有代理的地方。我构建了 API 映像并运行 docker-compose。所有服务都正常工作,所以我仍然认为在 Linux 机器上,代理在我当前的问题中发挥着重要作用。Windows 10 machineDocker version 20.10.7

更新2:多亏了@AndrewSilver建议,我才能够解决这个问题。 也非常感谢@kha提供更多细节。

C# elasticsearch .net-core docker-compose

评论

0赞 Max 8/17/2021
您可以确认在您以框架为目标的框架中?尝试将运行时从 也许在 ubuntu 上有更好的兼容性。查看完整标签列表*.csprojnet5aspnet:5.0aspnet:5.0-focal
0赞 Francesco 8/17/2021
我可以确认目标框架中的内容如下:<TargetFramework>net5.0</TargetFramework>。我将尝试更改 Docker 文件中的运行时并通知您。
9赞 AndrewSilver 10/21/2021
看起来这是你的问题。我能看到的唯一建议是禁用 TcpStats(如果您启用了它)。
2赞 kha 11/3/2021
@AndrewSilver 非常感谢!禁用 TcpStats 奏效了!也许你应该把它添加为答案。确切的命令是 。请记住,如果使用 DebugMode,则会启用 TcpStats,因此请确保在建立连接之前将其作为最后一个参数添加到连接设置中。connectionSettings.EnableTcpStats(false);
1赞 Ryabchenko Alexander 9/29/2023
@Francesco请自己写下问题的答案

答:

1赞 Francesco 11/23/2023 #1

只是为了确保以上是一个有用的问题,我在这里写了帮助我和其他人解决问题的解决方案,那就是禁用 TcpStats

@kha还补充说:确切的命令是 .请记住,如果使用 DebugMode,则会启用 TcpStats,因此请确保在建立连接之前将其作为最后一个参数添加到连接设置中。connectionSettings.EnableTcpStats(false);