本投稿はAWS Containers Advent Calendar 2021の16日目の記事です。投稿時間は16日の34時過ぎでしょうか。
9日での記事で書いた内容で、Windows on FargetでWindowsコンテナを動かす準備が終わった!と言いたい所ですが、前回の内容だと1つ大きな問題点が残ってます。
そう、それはログ
ログが出力されてないんです
前回のサンプルをベースにWindowsコンテナを起動してみると、docker container logs
でログを確認することができません。標準的なIISのアクセスログの出力先は、ファイル出力になりますし、Windowsのメジャーなログ出力先にはEventLogがありますよね。STDOUT/STDERRにログを出力することができれば、これまでのLinuxコンテナ流でのログ取得ができそうです。
また、Windows Container on Fargateは logging driverとしてawslogsをサポートしているので、STDOUT/STDERRに出力できれば、Cloudwatch Logsにログを出力することもできるでしょう。
さて、どうしたものかと調べていると Microsoftからコンテナ向けのロギングツールのblog記事が公開されていました。ロギングツールであるWindows Container Log MonitorのソースはGithub上で確認することができます。
Log MonitorはLinuxコンテナでのメジャーなログ出力方法を Windows 環境でも実現するためのツールです。
先ほどのblog記事の中にあるアーキテクチャ図をみて頂けると、どんな雰囲気が理解しやすくなると思います。
Log Monitorは、以下のログをサポートしており、IIS周りであれば、ひとまずこれを使えばよさそうですね
- ETW (Event Tracing for Windows)
- Event Logs
- Log files
では、早速、やってみましょう。
Log Monitorの導入
実行ファイルはGitHubのreleaseからダウンロードしてきます。ダウンロードした実行ファイルと設定ファイルを準備するだけでOKです。前回のサンプルのDockerfileをベースに以下の様な形に修正してみました。
ほとんどはオリジナルなサンプル通りなのですが、今回は、Dockerfile全体を載せてみます。
# escape=`
# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:6.0.100-windowsservercore-ltsc2019 AS build
WORKDIR /source
# copy csproj and restore as distinct layers
COPY *.sln .
COPY aspnetapp/*.csproj ./aspnetapp/
RUN dotnet restore
# copy everything else and build app
COPY aspnetapp/. ./aspnetapp/
WORKDIR /source/aspnetapp
RUN dotnet publish -c release -o /app --no-restore
# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:6.0.0-windowsservercore-ltsc2019
# Only needed for this sample because the sample project is targeting .NET 5
ENV DOTNET_ROLL_FORWARD=LatestMajor
RUN powershell -Command `
$ErrorActionPreference = 'Stop'; `
$ProgressPreference = 'SilentlyContinue'; `
`
# Install IIS
Add-WindowsFeature Web-Server; `
Remove-Item -Recurse C:\inetpub\wwwroot\*; `
`
# Acquire ServiceMonitor
Invoke-WebRequest -OutFile C:\ServiceMonitor.exe -Uri https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.10/ServiceMonitor.exe; `
`
# Install the ASP.NET Core Module
Invoke-WebRequest -OutFile c:\dotnet-hosting-win.exe https://aka.ms/dotnet/6.0/preview/dotnet-hosting-win.exe; `
$process = Start-Process -Filepath C:\dotnet-hosting-win.exe -ArgumentList @('/install', '/q', '/norestart', 'OPT_NO_RUNTIME=1', 'OPT_NO_X86=1', 'OPT_NO_SHAREDFX=1') -Wait -PassThru ; `
if ($process.ExitCode -ne 0) { `
exit $process.ExitCode; `
} `
Remove-Item -Force C:\dotnet-hosting-win.exe; `
Remove-Item -Force -Recurse $Env:Temp\*;`
`
Import-Module -Name WebAdministration;`
Set-ItemProperty -Path 'IIS:\Sites\Default Web Site' -Name logfile.logTargetW3C -Value 'File,ETW';
#Install LogMonitor
WORKDIR /LogMonitor
RUN powershell -Command `
Invoke-WebRequest -OutFile LogMonitor.exe -Uri https://github.com/microsoft/windows-container-tools/releases/download/v1.1/LogMonitor.exe;
COPY LogMonitorConfig.json .
WORKDIR /inetpub/wwwroot
COPY --from=build /app ./
EXPOSE 80
SHELL ["C:\\LogMonitor\\LogMonitor.exe", "powershell.exe"]
CMD ["C:\\LogMonitor\\LogMonitor.exe", "powershell.exe","C:\\ServiceMonitor.exe", "w3svc"]
LogMonitorを導入しているのは、以下の部分です
#Install LogMonitor
WORKDIR /LogMonitor
RUN powershell -Command `
Invoke-WebRequest -OutFile LogMonitor.exe -Uri https://github.com/microsoft/windows-container-tools/releases/download/v1.1/LogMonitor.exe;
COPY LogMonitorConfig.json .
実行ファイルをダウンロードしてきて、設定ファイルであるLogMonitorConfig.jsonを配置しています。
設定ファイルは、C:\LogMonitor\LogMonitorConfig.json
に置かれる事が想定されているようなので、
C:\LogMonitor
|- LogMonitor.exe
|- LogMonitorConfig.json
という配置にしています。設定ファイルであるLogMonitorConfig.jsonは以下の様な内容で定義してみました。
Windows Container on Fargate でどの様なログが確認できるかを試したかったので、幅広に取得する様にしています。
IISの設定的には、アクセスログは、ファイル出力、ETWどちらも可能ですが、アクセスログをファイル出力すると、若干バッファリングされて出力されるので、アクセス直後にはログが出ないんですよね。
ETWの方が出力されるタイミングが早い様なので、今回はあえて両方取得してみました。
IIS側の設定もFile,ETWの両方を指定してあります(Set-ItemProperty
あたりの部分)。
EventLogをソースとする場合、"startAtOldestRecord": false
としておくと、コンテナ実行後に出力されたEventLogからログを出力してくれます。
{
"LogConfig": {
"sources": [
{
"type": "EventLog",
"startAtOldestRecord": false,
"eventFormatMultiLine": false,
"channels": [
{
"name": "system",
"level": "Information"
},
{
"name": "application",
"level": "Error"
}
]
},
{
"type": "File",
"directory": "c:\\inetpub\\logs",
"filter": "*.log",
"includeSubdirectories": true
},
{
"type": "ETW",
"eventFormatMultiLine": false,
"providers": [
{
"providerName": "IIS: WWW Server",
"providerGuid": "3A2A4E84-4C21-4981-AE10-3FDA0D9B0F83",
"level": "Information"
},
{
"providerName": "Microsoft-Windows-IIS-Logging",
"providerGuid": "7E8AD27F-B271-4EA2-A783-A47BDE29143B",
"level": "Information"
}
]
}
]
}
}
IISを起動する部分は以下の様な記載になりました。ここで突然ServiceMonitor.exe
が出てきました。 これはWindowsコンテナの中でIISを利用するときのツールです。ServiceMonitor.exe
をラップする様なイメージでLogMonitor.exe
を使います。
SHELL ["C:\\LogMonitor\\LogMonitor.exe", "powershell.exe"]
CMD ["C:\\LogMonitor\\LogMonitor.exe", "powershell.exe","C:\\ServiceMonitor.exe", "w3svc"]
起動してみました
CloudWatch Logsにもログが流れ、いい感じになりました。不要なログがあれば、設定を見直していけばよさそうですね
<Source>EtwEvent</Source>
となっているところがETW経由のアクセスログです。ちなみに<Source>EventLog</Source>
であれば、
EventLogがソースとなっているログエントリです。
Container Insightsでもメトリクスが取れてますね。
さあ、これから色々試すぞ!