Answers: <p>On Windows (Dotnet Core) it can be done using powershell remote-invoke.</p>
  
  <p>In the container you need to set a trusted host by doing:</p>
  
  <p><code>RUN @powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force</code> </p>
  
  <p>Ideally replace the <code>*</code> with the host actual IP address. Keep in mind it changes between system restarts.</p>
  
  <p>On the host you need to create an Event Source called <code>MyLogger</code>.</p>
  
  <p>After that in your app you can create a custom logger that you add to the Microsoft Logging pipeline.</p>
  
  <p><strong>RemoteEventLogProvider.cs:</strong></p>
  
  <pre><code>using System.Management.Automation;
  using System.Net;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      public class RemoteEventLogProvider : ILoggerProvider
      {
          private readonly string _computer;
          private readonly PowerShell _powershell;
          private readonly NetworkCredential _credential;
  
          public RemoteEventLogProvider(string computer, NetworkCredential credential)
          {
              _computer = computer;
              _credential = credential;
              _powershell = PowerShell.Create();
          }
  
          public ILogger CreateLogger(string category)
          {
              return new RemoteEventLogger(_computer, _credential, _powershell, category);
          }
  
          public void Dispose()
          {
              _powershell.Dispose();
          }
      }
  }
  </code></pre>
  
  <p><strong>RemoteEventLogger.cs</strong></p>
  
  <pre><code>using System;
  using System.Management.Automation;
  using System.Net;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      public class RemoteEventLogger : ILogger
      {
          private readonly string _computer;
          private readonly string _category;
          private readonly PowerShell _powershell;
          private readonly NetworkCredential _credential;
  
          public RemoteEventLogger(string computer, NetworkCredential credential, PowerShell powershell, string category)
          {
              _computer = computer;
              _category = category;
              _credential = credential;
              _powershell = powershell;
          }
  
          public IDisposable BeginScope&lt;TState&gt;(TState state)
          {
              throw new NotImplementedException();
          }
  
          public bool IsEnabled(LogLevel logLevel)
          {
              return true;
          }
  
          public void Log&lt;TState&gt;(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func&lt;TState, Exception, string&gt; formatter)
          {
              var script = ScriptBlock.Create($"$password = ConvertTo-SecureString '{_credential.Password}' -AsPlainText -Force;" +
                                              $"$credential = New-Object System.Management.Automation.PSCredential ('{_credential.UserName}', $password);" +
                                              $"Invoke-Command -ScriptBlock {{ Write-EventLog -EntryType {logLevel} -EventId 0 -Source MyLogger -LogName Application -Message \"{formatter(state, exception)}\" }} -ComputerName {_computer} -Credential $credential;");
  
              var results = _powershell.AddScript(script.ToString()).Invoke();
  
              _powershell.Commands.Clear();
          }
      }
  }
  </code></pre>
  
  <p>Example usage <strong>Program.cs:</strong></p>
  
  <pre><code>using System;
  using System.Net;
  using System.Threading.Tasks;
  using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      class Program
      {
          static async Task Main(string[] args)
          {
              var config = new ConfigurationBuilder()
                        .AddCommandLine(args)
                        .AddEnvironmentVariables()
                        .Build();
  
              var computer = config["ConnectionStrings:Host.Address"];
              var provider = new RemoteEventLogProvider(computer, new NetworkCredential($"{computer}\\username", "password"));
  
              using (var factory = new LoggerFactory().AddConsole())
              {
                  factory.AddProvider(provider);
  
                  var logger = factory.CreateLogger("MyLogger");
  
                  logger.LogInformation($"Remote log at {computer}");
  
                  while (true)
                  {
                      try
                      {
                          logger.LogInformation($"The time is {DateTime.UtcNow}");
  
                          if (DateTime.UtcNow.Second % 2 == 0)
                          {
                              throw new Exception("random shit");
                          }
                          else
                          {
                              logger.LogWarning("Example warning");
                          }
                      }
                      catch (Exception ex)
                      {
                          logger.LogError(ex, ex.Message);
                      }
  
                      await Task.Delay(TimeSpan.FromSeconds(5));
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>Example <strong>Dockerfile</strong>:</p>
  
  <pre><code># Build
  FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
  WORKDIR /app
  COPY . /app
  
  RUN dotnet publish -c Release -o /app/out
  
  # Runtime
  FROM mcr.microsoft.com/windows/servercore:ltsc2019
  RUN curl -o c:\dotnet.exe https://download.visualstudio.microsoft.com/download/pr/a9bb6d52-5f3f-4f95-90c2-084c499e4e33/eba3019b555bb9327079a0b1142cc5b2/dotnet-hosting-2.2.6-win.exe
  RUN c:\dotnet.exe /quiet /install
  
  # Host
  RUN @powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force
  
  # Application
  WORKDIR /app
  COPY --from=build-env /app/out .
  
  ENTRYPOINT dotnet LogWriter.dll
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2019-07-30T07:36:19.803Z
Answers: 2019-07-30T07:36:19.803Z
Answers: Wojtek Turowicz
Body: <p>I run all my services as Docker containers on Linux by default. Recently got an order from a very large company to deploy to their Windows Servers. They have a very specific request for all application logs to appear in the host machine's EventLog. Their administrators don't know much about Docker and they don't want a centralised logging solution, like Kibana, for this deployment.</p>
  
  <p>Is there a feasible way to achieve that on Windows?</p>
  
  <p>Cheers</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>The services are all written in .NET Core 2.2.</p>
  
Tags: <docker><windows>
Title: Docker on Windows: Write directly to host's EventLog?
UserDisplayName: Wojtek Turowicz
ThreadText: # Docker on Windows: Write directly to host's EventLog?
  
  (Asked by: username_0 on 2019-07-25)
  
  I run all my services as Docker containers on Linux by default. Recently got an order from a very large company to deploy to their Windows Servers. They have a very specific request for all application logs to appear in the host machine's EventLog. Their administrators don't know much about Docker and they don't want a centralised logging solution, like Kibana, for this deployment.
  
  Is there a feasible way to achieve that on Windows?
  
  Cheers
  
  **EDIT**
  
  The services are all written in .NET Core 2.2.
  
  **Tags:** docker, windows
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2019-07-30. Score: 0 | Accepted answer
  
  On Windows (Dotnet Core) it can be done using powershell remote-invoke.
  
  In the container you need to set a trusted host by doing:
  
  `RUN @powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force`
  
  Ideally replace the `*` with the host actual IP address. Keep in mind it changes between system restarts.
  
  On the host you need to create an Event Source called `MyLogger`.
  
  After that in your app you can create a custom logger that you add to the Microsoft Logging pipeline.
  
  **RemoteEventLogProvider.cs:**
  
  ```
  using System.Management.Automation;
  using System.Net;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      public class RemoteEventLogProvider : ILoggerProvider
      {
          private readonly string _computer;
          private readonly PowerShell _powershell;
          private readonly NetworkCredential _credential;
  
          public RemoteEventLogProvider(string computer, NetworkCredential credential)
          {
              _computer = computer;
              _credential = credential;
              _powershell = PowerShell.Create();
          }
  
          public ILogger CreateLogger(string category)
          {
              return new RemoteEventLogger(_computer, _credential, _powershell, category);
          }
  
          public void Dispose()
          {
              _powershell.Dispose();
          }
      }
  }
  
  ```
  
  **RemoteEventLogger.cs**
  
  ```
  using System;
  using System.Management.Automation;
  using System.Net;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      public class RemoteEventLogger : ILogger
      {
          private readonly string _computer;
          private readonly string _category;
          private readonly PowerShell _powershell;
          private readonly NetworkCredential _credential;
  
          public RemoteEventLogger(string computer, NetworkCredential credential, PowerShell powershell, string category)
          {
              _computer = computer;
              _category = category;
              _credential = credential;
              _powershell = powershell;
          }
  
          public IDisposable BeginScope<TState>(TState state)
          {
              throw new NotImplementedException();
          }
  
          public bool IsEnabled(LogLevel logLevel)
          {
              return true;
          }
  
          public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
          {
              var script = ScriptBlock.Create($"$password = ConvertTo-SecureString '{_credential.Password}' -AsPlainText -Force;" +
                                              $"$credential = New-Object System.Management.Automation.PSCredential ('{_credential.UserName}', $password);" +
                                              $"Invoke-Command -ScriptBlock {{ Write-EventLog -EntryType {logLevel} -EventId 0 -Source MyLogger -LogName Application -Message \"{formatter(state, exception)}\" }} -ComputerName {_computer} -Credential $credential;");
  
              var results = _powershell.AddScript(script.ToString()).Invoke();
  
              _powershell.Commands.Clear();
          }
      }
  }
  
  ```
  
  Example usage **Program.cs:**
  
  ```
  using System;
  using System.Net;
  using System.Threading.Tasks;
  using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.Logging;
  
  namespace LogWriter
  {
      class Program
      {
          static async Task Main(string[] args)
          {
              var config = new ConfigurationBuilder()
                        .AddCommandLine(args)
                        .AddEnvironmentVariables()
                        .Build();
  
              var computer = config["ConnectionStrings:Host.Address"];
              var provider = new RemoteEventLogProvider(computer, new NetworkCredential($"{computer}\\username", "password"));
  
              using (var factory = new LoggerFactory().AddConsole())
              {
                  factory.AddProvider(provider);
  
                  var logger = factory.CreateLogger("MyLogger");
  
                  logger.LogInformation($"Remote log at {computer}");
  
                  while (true)
                  {
                      try
                      {
                          logger.LogInformation($"The time is {DateTime.UtcNow}");
  
                          if (DateTime.UtcNow.Second % 2 == 0)
                          {
                              throw new Exception("random shit");
                          }
                          else
                          {
                              logger.LogWarning("Example warning");
                          }
                      }
                      catch (Exception ex)
                      {
                          logger.LogError(ex, ex.Message);
                      }
  
                      await Task.Delay(TimeSpan.FromSeconds(5));
                  }
              }
          }
      }
  }
  
  ```
  
  Example **Dockerfile**:
  
  ```
  # Build
  FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
  WORKDIR /app
  COPY . /app
  
  RUN dotnet publish -c Release -o /app/out
  
  # Runtime
  FROM mcr.microsoft.com/windows/servercore:ltsc2019
  RUN curl -o c:\dotnet.exe https://download.visualstudio.microsoft.com/download/pr/a9bb6d52-5f3f-4f95-90c2-084c499e4e33/eba3019b555bb9327079a0b1142cc5b2/dotnet-hosting-2.2.6-win.exe
  RUN c:\dotnet.exe /quiet /install
  
  # Host
  RUN @powershell Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force
  
  # Application
  WORKDIR /app
  COPY --from=build-env /app/out .
  
  ENTRYPOINT dotnet LogWriter.dll
  
  ```
  
  
  ---
  
  