c# - web api 无法在 azure 上的 Linux 容器中使用 Net Core 3 Web api 启动

标签 c# azure docker asp.net-core azure-devops

我正在尝试“dockerize”this clean architecture template对于.net Core 3。我使用 docker pull request here作为我的概念应用程序教授的基础。这是一个 .net core 3 webapi 项目,以 Angular 前端作为客户端应用程序。

我有什么:

  1. 拉取请求中的基本代码在本地运行。
  2. 我必须克服的最初问题是在本地非开发环境中为身份服务器 4 设置证书,我必须使用证书挂载一个卷并从 appsettings.json 文件中引用它,例如
  "IdentityServer": {
    "Key": {
      "Type": "File",
      "FilePath": "/security/mycert.pfx",
      "Password": "MyPassword"
    }
  }
  • 我在 azure 中设置了 CI/CD 管道来构建项目并将镜像部署到 azure 容器注册表
  • 我设置了 CI/CD 版本,将 Docker 镜像部署到容器 Web 应用程序 (Linux) Web 应用程序。这两个步骤都可以正常工作
  • 我的问题:

    Web 应用程序加载并运行容器,并显示有角度的前端。但是,似乎 Web API 未运行。任何尝试访问 Web API 端点的行为都会在浏览器控制台中返回以下错误:

    GET https://.....azurewebsites.net/_configuration/CleanArchitecture.WebUI 404 (Not Found)

    Error: Uncaught (in promise): Error: Could not load settings for 'CleanArchitecture.WebUI' Error: Could not load settings for 'CleanArchitecture.WebUI'

    CleanArchitecture.WebUI 是作为 dockerfile 中入口点的程序集的名称:

    ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]

    前端的所有其他方面都工作正常,只有对“后端”api 的调用失败。 另一个问题是,如果我从 azure 容器获取 docker 日志,则没有显示错误

    我尝试了什么

    1. 我尝试将“dotnet CleanArchitecture.WebUI.dll”添加到 Web 应用程序容器设置中容器的启动命令中,但这只会引发错误,找不到 CleanArchitecture.WebUI.dll
    2. 我尝试提高日志记录级别(“LogLevel”:“Default”:“Debug”)以获取更多详细信息,但 Docker 日志中没有显示其他错误详细信息。
    3. 加载 Identity Server 4 证书时可能出现错误,但没有任何错误可以确认此问题。

    这是我的 Azure 管道使用的 docker compose 文件: 版本:'3.4'

    services:
      webui:
        image: ${DOCKER_REGISTRY-}webui
        build:
          context: .
          dockerfile: src/WebUI/Dockerfile
        environment:
          - "UseInMemoryDatabase=false"
          - "ASPNETCORE_ENVIRONMENT=Production"
          - "ConnectionStrings__DefaultConnection=myconnection"
          - "ASPNETCORE_Kestrel__Certificates__Default__Password=mypass"
          - "ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.pfx"
        ports:
            - "5000:5000"
            - "5001:5001"
        volumes: 
            - mcpdata:"/security:/"
        restart: always
    

    mcpdata 是已安装并包含实际证书的 azure 文件共享的名称

    这是我的 CI/CD 的 azure-pipeline.yml:

    trigger:
    - staging
    
    resources:
    - repo: self
    
    variables:
      # Container registry service connection established during pipeline creation
      dockerRegistryServiceConnection: '****'
      imageRepository: 'cleanarchitecture'
      containerRegistry: '****.azurecr.io'
      dockerComposeFilePath: '$(Build.SourcesDirectory)docker-compose.Production.yml'
      tag: '$(Build.BuildId)'
      
      # Agent VM image name
      vmImageName: 'ubuntu-latest'
    
    stages:
    - stage: Build
      displayName: Build and push stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: $(vmImageName)
        steps:
        - task: Docker@2
          displayName: Build and push an image to container registry
          inputs:
            command: buildAndPush
            repository: $(imageRepository)
            dockerComposeFile: $(dockerComposeFilePath)
            containerRegistry: $(dockerRegistryServiceConnection)
            tags: staging
    

    问题?

    有人可以帮我弄清楚为什么我的 Web api 没有运行但没有抛出错误。至少,如果有人可以帮助我查看 docker 日志中的错误,我会很高兴。

    提前致谢

    最佳答案

    我尝试使用以下内容重复“干净的架构”(注意,我在 MacOS 上使用 zsh,但同样也应该在 Windows/Linux 上工作):

    take clean_architecture  
    dotnet new --install Clean.Architecture.Solution.Template
    dotnet new ca-sln 
    

    文档建议,在 Visual Studio 中单击 F5 将启动模板,尽管我必须这样做:

    cd src/WebUI/ClientApp
    npm install
    

    此时,通过按 F5 键可以在本地启动应用程序。请注意,这里发生的情况是 ASP.Net Core 将请求转发到开发服务器,因此有效地,这确实 ngserve --port 53543 并在端口上启动 Asp.Net Core(在我的例子中为 Kestrel) 5001,浏览http://127.0.0.1:53543直接提供Angular页面。浏览 https://localhost:5001 会显示相同的 Angular 页面,由 ASPNetCore 转发到 Angular。一切都非常困惑...详细更多here

    注意Startup.cs中存在以下几行代码,这些代码通常是根据环境变量ASPNETCORE_ENVIRONMENT设置的

                if (!env.IsDevelopment())
                {
                    app.UseSpaStaticFiles();
                }
    
                -- and within "app.UseSpa"
                    if (env.IsDevelopment())
                    {
                        spa.UseAngularCliServer(npmScript: "start");
                    }
    

    无论如何,看起来您已经将该环境变量设置为 Production,它应该只为 ClientApp\dist 文件夹中的构建文件提供服务(而不是转发到开发服务器),这表明如果您看到 Angular,则 .Net Core 服务正在运行...我将首先尝试重建 Dockerfiles...

    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
    ENV ASPNETCORE_URLS=https://+:5001;http://+:5000
    WORKDIR /app
    EXPOSE 5000
    EXPOSE 5001
    
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
    RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
    RUN apt install -y nodejs
    WORKDIR /src
    COPY ./src/WebUI/WebUI.csproj src/WebUI/
    COPY ./src/Application/Application.csproj src/Application/
    COPY ./src/Domain/Domain.csproj src/Domain/
    COPY ./src/Infrastructure/Infrastructure.csproj src/Infrastructure/
    RUN dotnet restore "src/WebUI/WebUI.csproj"
    COPY . .
    WORKDIR "/src/src/WebUI"
    RUN dotnet build "WebUI.csproj" -c Release -o /app/build
    
    FROM build AS publish
    RUN dotnet publish "WebUI.csproj" -c Release -o /app/publish
    
    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app/publish .
    ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]
    

    然后按如下方式构建并运行:

    # build takes a while
    docker build -f ./src/WebUI/Dockerfile -t clean-architecture .
    
    # note, this fails first time, because I set up as clean_architecture so the entry point is incorrect
    docker run --rm -it -p 5000:5000 -p 5001:5001 clean-architecture
    
    # run the container and override the entrypoint
    docker run --rm -it --entrypoint /bin/bash clean-architecture 
    
    # From within the container...
    root@93afb0ad21c5:/app# dotnet clean_architecture.WebUI.dll 
    
    # note, in .Net 3.1, you can also do this directly, as follows:
    root@93afb0ad21c5:/app# ./clean_architecture.WebUI 
    
    

    现在 LocalDB 存在问题:System.PlatformNotSupportedException:此平台不支持 LocalDB。

    将 appsettings.Production.json 切换为“UseInMemoryDatabase”:true

    问题似乎是证书......

    我使用以下方法创建了一个证书:

    dotnet dev-certs https -ep ./https/clean-arch.pfx -p anything   
    

    对于 IdentityServer,我按如下方式更改 appSettings.Production.json:

      "IdentityServer": {
        "Key": {
          "Type": "File",
          "FilePath": "/app/https/https/clean-arch.pfx",
          "Password": "anything"
        }
      }
    

    然后在 Linux 上运行,可能意味着运行 Kestrel,这意味着我们也需要在那里提供 HTTPS 证书,我是通过在 Program.cs 中设置以下内容来实现的

            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.ConfigureKestrel((context, options) =>
                        {
                            options.AllowSynchronousIO = true;
                            options.Listen(IPAddress.Loopback, 5000, listenOptions =>
                            {
                                listenOptions.UseConnectionLogging();
                                listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http1AndHttp2;
                            });
                            options.Listen(IPAddress.Any, 5001, listenOptions =>
                            {
                                listenOptions.UseConnectionLogging();
                                listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http1AndHttp2;
                                listenOptions.UseHttps(new System.Security.Cryptography.X509Certificates.X509Certificate2("/app/https/https/clean-arch.pfx", "anything"));
                            });
                        });
                        webBuilder.UseStartup<Startup>();
                    });
    

    在每个阶段,我都使用...在 docker 中构建应用程序

    \clean_architecture $ docker build -f ./src/WebUI/Dockerfile -t clean-architecture  .  
    /clean_architecture $ docker run --rm -it -v /Users/monkey/src/csharp/clean_architecture/:/app/https/ -p 5000:5000 -p 5001:5001 --entrypoint /bin/bash clean-architecture     
    

    ...在 bash(在 docker 中)中运行后,我使用以下命令来启动应用程序:

    root@c5b4010d03be:/app# ./clean_architecture.WebUI 
    

    祝你好运,希望有帮助。请注意,如果它在您计算机上的 Docker 中运行,它也应该在 Azure 中运行。改天我会考虑在 Azure 中实现它。如果有帮助的话,很高兴将我的代码上传到 GitHub?

    关于c# - web api 无法在 azure 上的 Linux 容器中使用 Net Core 3 Web api 启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64270066/

    相关文章:

    c# - 在 Razor-4 View 中访问模型属性

    debugging - 如何查看Azure fastCGI上的实际错误?

    virtualbox - 是否可以在 docker 容器中运行 virtualbox

    docker - (GitHub Actions,上传工件)尽管授予文件完全权限,但尝试上传文件时访问被拒绝

    c# - Xamarin - 发布后刷新 ListView

    c# - 何时使用 mvvmcross 数据绑定(bind)?

    c# - 如何在 Gtk# 窗口上绘制一些东西(线、圆等)?

    Azure 机器学习阅读器 + 表存储

    python - Azure 函数 blob 存储文件名

    asp.net - 通过 AWS ECS 在 Docker 中 Multi-Tenancy 部署 WebForms 应用程序的 Web.Config 转换