【.NET】.NETなアプリケーションをVisualStudioからdocker-compose upしようとすると暗黙的にentrypointがoverrideされるせいでwait-for-itが無視される問題
いつかこの辺のつくりが便利になっていることを願って(執筆時2021/02/23)
概要
単純にコマンドでdocker-compose build
, docker-compose up
するなら問題ないんだけど、
VisualStudioのDocker連携によって追加したdocker-composeプロジェクト(素直に作った場合docker-compose.dcprojになるかな)をスタートアッププロジェクトに指定し、起動した場合はentrypointもといdocker-compose.ymlそのものが暗黙的に上書きされることになる
※ GUIをもってWebAPをDocker連携を行うようにしていくと、Dokcerfile, docker-compose.ymlだけでなくdocker-compose.override.ymlも自動生成されるんだけど、それとはまた別
その暗黙的な上書きを、更に明示的に上書きする場合の手順のまとめというかサンプルというかを書いた記事
上書きで困る具体的な例(表題のやつ):
WebAPの起動の前にDBの疎通を待つためにwait-for-it.shのcallをWebAPのentrypointとして指定する
(VisualStudioのGUIからdocker-composeを起動する場合、)そのentrypointが上書きされて無視されてしまう
※ wait-for-it自体はDocker的に推奨される方法 https://docs.docker.jp/compose/startup-order.html
ローカルでGUI操作の時だけの問題というかVisualStudioのローカルでバッグの問題なんだから無視でいいじゃん。とも(後から)思ったけど、そこを考えずに必死に調べて結論まで出してしまった...
方法
you could add the following code only in docker-compose.vs.debug.yml
If you omit the docker-compose.vs.release.yml or docker-compose.vs.debug.yml then Visual Studio generates one based on default settings.
この通りdocker-compose.vs.debug.yml
を上書きすればいい
さもないとdefault settingが利用される
※ そのdefault settingを記述しているファイル自体は自動生成されるが、ソリューションに包含されない(なので分かりにくい)
If you want to take a peek at all the drudgery, take a look at the file:
{root solution folder}\obj\Docker\docker-compose.vs.debug.g.yml
実装
wait-for-itを利用する例で説明
せっかくなのでgithubにあげた
VisualStudio For MacでやっているのでWindowsだとパス変えなきゃだめかも(いつか自分で確認する)
https://github.com/0mmadawn/VsDebugDockerContainerOverrideSample
まずはwait-for-itを準備する
https://github.com/0mmadawn/VsDebugDockerContainerOverrideSample/blob/main/web/Dockerfile#L8-L9
(本筋から逸れるけど、)CLIからdocker-compose up
する場合は以下の通り普通にdocker-compose.ymlにentrypointを書けばOK
本題のVisualStudioからGUI操作でdocker-composeプロジェクトを起動する場合のために、docker-compose.vs.debug.yml
ファイルを明示的に用意する
でこんな感じ
version: '3.4' services: web: # 省略 # entrypointはそのままでOK entrypoint: tail -f /dev/null labels: # これを #com.microsoft.visualstudio.debuggee.program: "dotnet" #com.microsoft.visualstudio.debuggee.arguments: " --additionalProbingPath /root/.nuget/packages \"/app/bin/Debug/net5.0/web.dll\"" # こうする com.microsoft.visualstudio.debuggee.program: "/wait-for-it.sh" com.microsoft.visualstudio.debuggee.arguments: "db:3306 -t 60 -- dotnet --additionalProbingPath /root/.nuget/packages \"/app/bin/Debug/net5.0/web.dll\"" # 省略
entrypointはそのままにlabelsのよくわからんところを変更するのがポイント
偉大なる参考: https://github.com/microsoft/DockerTools/issues/9#issuecomment-613042120
で、動かすとこんな感じに確認できる
Starting: "docker" exec -i fcda4d199535 /bin/sh -c "ID=.; if [ -e /etc/os-release ]; then . /etc/os-release; fi; if [ $ID = alpine ] && [ -e /remote_debugger/linux-musl-x64/vsdbg ]; then VSDBGPATH=/remote_debugger/linux-musl-x64; else VSDBGPATH=/remote_debugger; fi; $VSDBGPATH/vsdbg --interpreter=vscode --interpreter=vscode" ------------------------------------------------------------------- You may only use the Microsoft .NET Core Debugger (vsdbg) with Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you develop and test your applications. ------------------------------------------------------------------- wait-for-it.sh: waiting 60 seconds for db:3306 ★呼ばれてる! wait-for-it.sh: db:3306 is available after 22 seconds ★ Loaded '/usr/share/dotnet/shared/Microsoft.NETCore.App/5.0.2/System.Private.CoreLib.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. ...
補足
docker-compose.vs.debug.yml
ファイルで自分のローカルなファイル参照させてるし、
なんならこっちの方法のようにプログラム内で制御したほうがマシな気がしてきている
https://stackoverflow.com/a/53238408