空いていたので予定を早めて Visual Studio Advent Calendar 12日目のエントリを書きます。
Windows上のdockerやAzure Container ServicesであればVisual Studio Tools for Dockerを使えばVisual StudioからASP.NET Coreのアプリにリモートデバッグできます。Microsoft謹製のサービスしか接続できないので、なにか闇の技術でも使われているかと思われるかもしれないですが、そんなことはなくてGitHubで公開されているMIEngineというデバッグエンジンが利用されています。
この当たりの話は、Visual StudioからSSHを使えば、Linux上の.NET Coreプロセスにリモートデバッグできるというネタで何度かセッションでデモをしてきました。
というわけで、Visual StudioをインストールしているWindowsマシンからdockerにリモートでコマンドを実行できれば、他のdocker containerであってもリモートデバッグができます。今回は、OpenShift Container Platform上で動くASP.NET Coreアプリにリモート接続してみます。
前提条件
OpenShift で試していますが、以下の条件を満たせば他のdocker container as a service なプラットフォームでも同じ方法が使えるはずです*1。
- docker exec コマンドなどでVS Codeを動かしているマシンからリモートでコンテナ上のコマンドを実行できる
- docker上で動いているASP.NET Core のバイナリはデバッグビルドである
手順
前提条件を満たしたdockerが動ている前提からスタートします。OpenShiftの場合は、gitのコードリポジトリにあるソースコードからビルドしてdocker containerを作って動かすs2iという仕組みがあるので、それが使えます。今回テストしたアプリも下のexampleアプリをそのまま動かしただけの状態です。
GitHub - openshift-s2i/s2i-aspnet-example: Example projects for the ASP.NET builder image
Visual Studioを動かすマシンにソースコードをセットアップします。上のコードを使う場合はcloneしてappフォルダ以下をルートとして開けばOKです。
実行しているdocker container内にclrdbgをインストールします。インストール先などは適当に。あらかじめclrdbgをインストールしたdockerイメージを用意してもいいでしょう。OpenShiftの場合はoc exec [pod] -- [command]
でコマンドを実行できます*2。docker exec
の場合はコマンドの前の--
が不要です。
> oc exec <POD_NAME> -- curl -sSL https://raw.githubusercontent.com/Microsoft/MIEngine/getclrdbg-release/scripts/GetClrDbg.sh -o GetClrDbg.sh > oc exec <POD_NAME> -- bash ./GetClrDbg.sh latest ./clrdbg Info: Using clrdbg version '15.0.25904-preview-3404276' Info: Creating install directory Info: Determinig Runtime ID Info: Using Runtime ID 'rhel.7.2-x64' Info: Generating project.json Info: Generating NuGet.config Info: Executing dotnet restore Info: Executing dotnet publish Successfully installed clrdbg at './clrdbg'
次にプロセスにアタッチするので、コンテナ上で動いているASP.NET Core のPIDを確認します。OpenShiftの場合はこんな結果になりますが、PIDは62になります。
> oc exec <POD_NAME> -- ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND default 1 0.5 0.4 3048552 37016 ? SLsl 22:08 0:05 dotnet run default 62 1.0 1.9 12134016 153332 ? SLl 22:08 0:09 /opt/rh/rh-dotnetcore10/root/usr/lib64/dotnetcore/dotnet exec --additionalprobingpath /opt/app-root/src/.nuget/packages /opt/app-root/src/bin/Debug/netcoreapp1.0/src.dll default 381 0.0 0.0 13352 1868 ? Ss+ 22:16 0:00 /bin/sh default 676 0.0 0.0 48996 1692 ? Rs 22:23 0:00 ps aux
接続先のコンテナ名(POD名)とPIDがわかれば次のようなXMLファイルを作成します。これはVisual Studioのプロジェクト内でも外でもどちらに保存しても構いません。<POD_NAME>と--
を除いたコマンド引数を指定すれば大丈夫なはずです。
<PipeLaunchOptions xmlns="http://schemas.microsoft.com/vstudio/MDDDebuggerOptions/2014" PipePath="C:\Tools\oc.exe" PipeArguments="exec -i <POD_NAME> -- /opt/app-root/src/clrdbg/clrdbg --interpreter=mi" TargetArchitecture="x64" MIMode="clrdbg"> <CustomLaunchSetupCommands> <Command>-target-attach <PID></Command> </CustomLaunchSetupCommands> <LaunchCompleteCommand>None</LaunchCompleteCommand> </PipeLaunchOptions>
あとは、Visual StudioのCommand Windowを開いて、
> Debug.MIDebugLaunch /Executable:dotnet /OptionsFile:<保存したxmlファイルのパス>
を実行します。あとは自動でデバッグが始まってプロセスにアタッチできるはずです。もちろん、ブレークポイントをしかけるとブレークします。
なかなか面倒な手順ですが、Visual Studio Tools for Docker はOpen Sourceになるらしいので、公開されたらそれをいじればVS拡張として作ることも簡単そうです。
ちなみにVisual Studio Codeからも同じことができますが、それは今週末のAdvent Calendarに書きます。