Search code examples
dockerlogging.net-coreconsole

Console.ForegroundColor / BackgroundColor not reflected in Docker log


I have a block of logs written as:

Console.ForegroundColor = ConsoleColor.Blue;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine("------------------------------------------");
Console.WriteLine("Kestrel server running on ...");
...

Windows Command Line (proper):

enter image description here

Linux/Docker Log Command Line:

enter image description here

I would normally just assume that docker logs cannot be colorized, but, as evident with the yellow "warn" on a black background, it seems there is definitely a way to colorize the logs, and it seems that the dotnetcore logging is using a different method to display the logging tags (which is why they are colorized properly).

How am I able to write lines to the console with proper color showing in the docker log?


Solution

  • TLDR: Arguably, both behaviours that you are seeing are bugs.

    The colours are actually implemented under the hood by emitting ANSI escape sequences to the "terminal" (or wherever your application is sending output to). These ANSI escape sequences should only be emitted when the "terminal" that is being written to can understand them.

    Depending on how you started your containers and what your orchestrator is, you may or may not have a terminal/log that can understand ANSI escape sequences. For example, running a container under docker using docker run doesn't attach a terminal to the process. Running docker run -t will. So docker run -t should give you full colours.

    The ASP.NET Core behaviour is a bug

    ASP.NET Core writes ANSI colour codes without any understanding of where they are going to. It might be a plain text log. Or it might be a fancy terminal.

    If you run your ASP.NET Core containers in kubernetes, for example, you get garbage in your logs instead of colour:

    �[40m�[1m�[33mwarn�[39m�[22m�[49m: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
          Storing keys in a directory '/opt/app-root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
    �[40m�[1m�[33mwarn�[39m�[22m�[49m: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
          No XML encryptor configured. Key {2c2776a6-be46-4719-9275-b7baed6ebc3f} may be persisted to storage in unencrypted form.
    �[40m�[32minfo�[39m�[22m�[49m: Microsoft.Hosting.Lifetime[0]
          Now listening on: http://[::]:8080
    �[40m�[32minfo�[39m�[22m�[49m: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    �[40m�[32minfo�[39m�[22m�[49m: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Production
    �[40m�[32minfo�[39m�[22m�[49m: Microsoft.Hosting.Lifetime[0]
          Content root path: /opt/app-root/app
    

    The Console behaviour is a bug

    On the flip side, Console disables colours as soon as it detects that the output is being redirected and may not go to a terminal.

    That will avoid garbage in the output. So it wont cause harm.

    But as you can see, you get no colours in your logs even when you are (presmuably? I am not sure) running your application attached to a terminal.

    What can you do?

    Do you really need colours right now?

    If so, you can emit ANSI escape sequences manually. Take a look at the ASP.NET Core implementation here.

    This is probably not a great idea in the long term. The bugs in .NET Core will be fixed and you should get a consistent experience at some point in the future.