【问题标题】:web api does not start up with NetCore 3 web api in linux container on azureweb api 无法在 azure 上的 linux 容器中使用 Net Core 3 web api 启动
【发布时间】:2021-01-23 22:42:24
【问题描述】:

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

我有什么:

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

我的问题:

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

GET https://.....azurewebsites.net/_configuration/CleanArchitecture.WebUI 404(未找到)

错误:未捕获(承诺):错误:无法加载“CleanArchitecture.WebUI”的设置错误:无法加载“CleanArchitecture.WebUI”的设置

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

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

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

我尝试了什么

  1. 我尝试在 Web 应用程序的容器设置中将“dotnet CleanArchitecture.WebUI.dll”添加到容器的启动命令中,但这只会引发找不到 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 日志中的错误,我会很高兴。

提前致谢

【问题讨论】:

  • 好像没有生成CleanArchitecture.WebUI.dll?或者它位于不同的文件夹中。应用程序在推送到 ACR 之前是否在 docker 中构建?您可以查看 [this thread](CleanArchitecture.WebUI.dll) 的答案以查看日志。
  • @LeviLu-MSFT 构建发生在 azure ci/cd 管道中,并被推送到 Azure 容器注册。当我在本地运行“docker-compose -f 'docker-compose.Production.yml' up --build”时,容器可以工作。另一个奇怪的事情是日志中没有显示错误,你会认为如果 Cleanarchitecture 缺少 docker 会在尝试运行它时产生错误。

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


【解决方案1】:

我尝试重复,使用以下“干净架构”(注意,我在 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 将请求转发到开发服务器,如此有效,ng serve --port 53543 并在端口 5001 上启动 Asp.Net Core(在我的情况下为 Kestrel),浏览到 http://127.0.0.1:53543 提供了角度直接翻页。浏览到https://localhost:5001 会显示与 ASPNetCore 转发到 Angular 相同的 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 is not supported on this platform.

将 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?

【讨论】:

  • 感谢您的努力,我终于解决了问题,请参阅下面的答案
【解决方案2】:

感谢 0909EM 为回答问题付出的巨大努力,但解决方案不同。

我知道发生了什么。有两个问题。

  1. docer-compose.override.yml 文件如下所示:
version: '3.4'

services:
  webui:
    environment:
      - "ASPNETCORE_ENVIRONMENT=Development"
      - "SpaBaseUrl=http://clientapp:4200"

  clientapp:
    image: ${DOCKER_REGISTRY-}clientapp
    build:
      context: src/WebUI/ClientApp
      dockerfile: Dockerfile
    depends_on:
      - webui
    restart: on-failure

  db:
    ports:
      - "1433:1433"

注意 src/webui/clientapp 上下文中的 dockerfile: Dockerfile 行。在 azure 管道构建期间,此 dockerfile 覆盖了 src/webui 中的正确 docker 文件。出于某种原因,当我在本地运行以下命令时: docker-compose -f 'docker-compose.Production.yml' up --build 它不会拉入 docker-compose.override 设置,但是覆盖设置确实在 azure 管道构建中使用。

因此,Angular dockerfile 是唯一构建的,并且该映像不包含 .net core web api 项目。这解释了为什么我看到前端但无法访问 api 端点,以及为什么 dockerfile 没有 .net 核心错误。

我可以通过两种方式解决这个问题。

首先: 将 src/webui/clientapp 中的 dockerfile 重命名为 Dockerfile.clientapp 并将 docker.overrride 文件中的行更改为 dockerfile: Dockerfile。客户端应用程序

第二个:只需从 azure 管道从中提取的在线存储库中删除 docker override 文件。

因此使用了正确的 dockerfile,并且 web api 项目位于映像中。

  1. 第二个问题:现在正确的图像正在运行,.net core web api 抛出一个关于为身份服务器加载证书的错误。这证实了我的猜想。因为这个问题与我最初关于让 web api 在容器中运行的问题无关,i have opened another question about it.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    • 2021-11-20
    • 1970-01-01
    • 2021-10-21
    • 2020-06-09
    相关资源
    最近更新 更多