Docker容器上的Blazor

时间:2019-04-30 08:35:41

标签: docker .net-core blazor

有人设法在Docker容器上运行服务器端托管的Blazor应用程序吗?

我在运行它时遇到以下异常:

warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {c1fe0008-8b2b-46a3-9f80-233ae59e5d17} may be persisted to storage in unencrypted form.
crit: Microsoft.AspNetCore.Hosting.Internal.GenericWebHostService[6]
      Application startup exception
System.InvalidOperationException: Could not load the embedded file manifest 'Microsoft.Extensions.FileProviders.Embedded.Manifest.xml' for assembly 'Microsoft.AspNetCore.Components.Server'.
   at Microsoft.Extensions.FileProviders.Embedded.Manifest.ManifestParser.Parse(Assembly assembly, String name)
   at Microsoft.Extensions.FileProviders.ManifestEmbeddedFileProvider..ctor(Assembly assembly)
   at Microsoft.AspNetCore.Components.Server.ConfigureStaticFilesOptions.PostConfigure(String name, StaticFileOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.<>c__DisplayClass5_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsManager`1.Get(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.get_Value()
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware..ctor(RequestDelegate next, IWebHostEnvironment hostingEnv, IOptions`1 options, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_0.<UseMiddleware>b__0(RequestDelegate next)
   at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
   at Microsoft.AspNetCore.Hosting.Internal.GenericWebHostService.StartAsync(CancellationToken cancellationToken)

Unhandled Exception: System.InvalidOperationException: Could not load the embedded file manifest 'Microsoft.Extensions.FileProviders.Embedded.Manifest.xml' for assembly 'Microsoft.AspNetCore.Components.Server'.
   at Microsoft.Extensions.FileProviders.Embedded.Manifest.ManifestParser.Parse(Assembly assembly, String name)
   at Microsoft.Extensions.FileProviders.ManifestEmbeddedFileProvider..ctor(Assembly assembly)
   at Microsoft.AspNetCore.Components.Server.ConfigureStaticFilesOptions.PostConfigure(String name, StaticFileOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.<>c__DisplayClass5_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsManager`1.Get(String name)
   at Microsoft.Extensions.Options.OptionsManager`1.get_Value()
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware..ctor(RequestDelegate next, IWebHostEnvironment hostingEnv, IOptions`1 options, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_0.<UseMiddleware>b__0(RequestDelegate next)
   at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
   at Microsoft.AspNetCore.Hosting.Internal.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
   at BlazorUI.ServerSided.Program.Main(String[] args) in /src/BlazorUI.ServerSided/Program.cs:line 19

编辑:这是一个干净的项目,由Visual Studio在创建新的ASP.Net Core Web应用程序> Blazor(服务器端)时添加。该项目没有其他更改。

Dockerfile是通过选择项目(右键单击)>添加> docker支持创建的:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-stretch-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.0-stretch AS build
WORKDIR /src
COPY ["BlazorUI.ServerSided/BlazorUI.ServerSided.csproj", "BlazorUI.ServerSided/"]
RUN dotnet restore "BlazorUI.ServerSided/BlazorUI.ServerSided.csproj"
COPY . .
WORKDIR "/src/BlazorUI.ServerSided"
RUN dotnet build "BlazorUI.ServerSided.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "BlazorUI.ServerSided.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "BlazorUI.ServerSided.dll"]

我正在使用.net-core 3-preview4-011223和linux容器。

图像已发布here

2 个答案:

答案 0 :(得分:1)

您遇到了预览版4中的一个众所周知的问题,该问题会影响Linux构建 参见https://github.com/aspnet/AspNetCore/issues/9402 Asp.NET团队声称已在预览版5中修复了该问题

要解决您的问题,请使用截至2019年5月5日的每日预览版5。

您可以从https://github.com/aspnet/AspNetCore/blob/master/docs/DailyBuilds.md

获取Preview5的内部版本

答案 1 :(得分:0)

这是我到目前为止发现的结果,并且目前可以使用(使用https和子域):

Startup.cs中的设置子域->配置:

        string basePath = Environment.GetEnvironmentVariable("ASPNETCORE_BASEPATH");
        if (!string.IsNullOrEmpty(basePath))
        {
            app.Use((context, next) =>
            {
                context.Request.Scheme = "https";
                return next();
            });

            app.Use((context, next) =>
            {
                context.Request.PathBase = new PathString(basePath);
                if (context.Request.Path.StartsWithSegments(basePath, out var remainder))
                {
                    context.Request.Path = remainder;
                }
                return next();
            });
        }
        app.UseForwardedHeaders(new ForwardedHeadersOptions

Apache配置,例如子域“ helloapp”和docker端口9124 aspnetcore-3.0#configure-apache

<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
<VirtualHost *:443>
  ServerName www.example.com
  ServerAlias example.com

  ErrorLog ${APACHE_LOG_DIR}helloapp-error.log
  CustomLog ${APACHE_LOG_DIR}helloapp-access.log common

  UseCanonicalName On
  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
  SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
  SSLCipherSuite HIGH

  SSLProxyEngine On
  ProxyPreserveHost On

  ProxyRequests Off
  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /helloapp/(.*) wss://localhost:9124/$1 [P,QSA,L]

  <Location /helloapp >
    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module    modules/mod_proxy_http.so
    LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
    ProxyPreserveHost On
    ProxyPass https://127.0.0.1:9124
    ProxyPassReverse https://127.0.0.1:9124
  </Location>

</VirtualHost>

假设您拥有一个letencrypt SSLCertificate,则必须对其进行转换,以便Kestrel可以使用它。在Linux服务器上,在终端中运行以下命令。 privkey,cert和chain文件的路径可以在您的apache配置中找到。这将创建一个certificate.pfx –您必须输入Kestrel的有效密码。

openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem

hub.docker获取Dockerfile,例如bionic/amd64/Dockerfile 在Dockerfile的底部添加以下行:

COPY ./certificate.pfx /root/certificate.pfx

将certificate.pfx文件和Dockerfile复制到一个空文件夹。创建文件docker-compose.yml:

version: '3.3'

services:
  helloapp:
    build: .
    #restart: always
    ports:
      - "9123:80"
      - "9124:443"
    environment:
      ASPNETCORE_BASEPATH: /helloapp
      ASPNETCORE_HTTPS_PORT: 9124
      ASPNETCORE_URLS: "https://+:443;http://+:80"
      Kestrel__Certificates__Default__Path: /root/certificate.pfx
      Kestrel__Certificates__Default__Password: mycertificatesecret
    volumes:
      - ./helloapp:/helloapp
    working_dir: /helloapp
    command: ["dotnet", "helloapp.dll"] 

创建一个子文件夹helloapp并将您已发布的WebApp复制到其中。

然后您可以启动容器,它应该在www.example.com/helloapp中可用

docker-compose build
docker-compose up