在Docker容器中记录ASP.NET Core/.NET Core控制台应用程序日志

12

如何在运行在Docker容器内的.NET Core应用程序中编写日志,以便日志消息将显示在docker logs <container-id>或者Kitematic UI?

我几乎尝试了所有方法,但最终始终无法从dotnet应用程序中获得日志。 所有其他我在容器中拥有的非dotnet应用程序,例如NODE.js、nginx、rabbitmq都可以正常记录日志。

以下是我已经尝试过的:

  • 使用Console.WriteLine的控制台应用程序(.NET Core)
  • 使用ILogger接口的ASP.NET Core应用程序(使用VS模板自带Docker支持后的默认设置)
  • 在控制台/ASP.NET Core应用程序中使用log4net(实际上RollingFileAppender示例中使用ConsoleAppender可以正常工作)

我无法找到任何遇到相同问题的人(stackoverflow, google, github issues),因此我认为我在这里漏掉了一些基本的东西。

更新1:

这是我的当前设置:

  • Windows 10 Pro
  • Docker for Windows 17.12.0-ce
  • docker-compose版本1.18.0,构建8dd22a96
  • 运行Linux容器

更新2:

可工作的Dockerfile示例(NodeJS应用程序)

FROM node:9-slim
WORKDIR /app
EXPOSE 80

ENV NODE_PATH=/node_modules
ENV PATH=$PATH:/node_modules/.bin

COPY ./MyApp ./
RUN npm install
RUN npm run build
CMD [ "npm", "start" ]

不起作用的Dockerfile示例(由Visual Studio生成,针对ASP.NET Core)

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY *.sln ./
COPY DockerLoggingTest2/DockerLoggingTest2.csproj DockerLoggingTest2/
RUN dotnet restore
COPY . .
WORKDIR /src/DockerLoggingTest2
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

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

正如您所看到的,这并没有什么特别之处。因此问题必须在.NET Core中,因为所有其他类型的应用程序日志都可以正常工作。


我们使用启用了控制台日志记录的Serilog。 - Christian Sauer
请参见 https://dev59.com/pFYN5IYBdhLWcg3wEEcm。 - Marius Steinbach
你使用的是哪个Dockerfile?如果你的容器不是PID 1,那么日志就不会被Docker首先捕获,这也解释了你的症状。 - Christian Sauer
1
@ChristianSauer 我正在使用由 Visual Studio 生成的默认 Dockerfile,当您创建支持 Docker 的新应用程序时会自动生成。它还使用了 Docker Compose v3。 - Radek Stromský
我刚刚意识到这些应用程序(工作/不工作)之间唯一的区别是,我是从Visual Studio运行.NET应用程序。所以也许问题在于Visual Studio像往常一样破坏了某些东西;-) - Radek Stromský
显示剩余3条评论
2个回答

9

将以下内容添加到 appsettings.json 文件中

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "System": "Information",
      "Microsoft": "Information"
    },
    "Console": {
      "IncludeScopes": true
    }
  }

请确保你的项目配置了复制appsettings,在YourProject.csproj文件中进行如下设置:

  <ItemGroup>
    <Content Include="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

然后我将配置添加到日志服务中。

            services.AddLogging(builder =>
                builder
                    .AddDebug()
                    .AddConsole()
                    .AddConfiguration(configuration.GetSection("Logging"))
                    .SetMinimumLevel(LogLevel.Information)
            );

希望这能帮到您。

我知道这是个愚蠢的问题,但 configuration 是从哪里来的呢?-- 默认模板中没有那个变量。(我知道有很多方法可以获得它,但我猜在 docker 服务的这种特定情况下,有一种正确的方法可以获得它,而我不知道是什么。) - BrainSlugs83
FYI,在最新的C#“Worker Service”模板中,我刚刚根据这个答案进行了配置更改(没有代码更改),现在日志既出现在Docker应用程序中,也出现在Visual Studio输出窗口中(使用CTRL+F5,而不是调试...所以很棒)! - BrainSlugs83
1
配置应该是Configuration。 - Cornelis Kuijpers

6

正如我猜测的那样,Visual Studio是中间人,吞噬了所有的日志消息。我认为这可能与docker-compose命令中的yaml覆盖有关,Visual Studio调用该命令以启用所有调试功能。

docker-compose  -f "docker-compose.yml" -f "docker-compose.override.yml" -f "obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose2788718473649893946 up -d --force-recreate --remove-orphans

看起来以下文件 obj\Docker\docker-compose.vs.debug.g.yml 负责我所经历的行为。当我没有运行这个命令时,一切都按预期工作。

感谢大家的头脑风暴,这导致了这个答案。


2
啊,你应该告诉我们你想要调试。是的,VS将所有输出重定向到它自己的输出日志中。这在生产环境中不会发生。 - Christian Sauer
2
我本不想调试,但是Visual Studio默认运行在调试模式下,我没有意识到这可能会造成任何损害。我的错。无论如何还是谢谢。 - Radek Stromský

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接