インドカレーファンクラブ

パソコン、カメラ

【.NET5】【ASP.NET】フルスタックWebアプリケーションテンプレートwithコンテナ

github.com

.NET CORE3.1, NET5でフルスタックなWebアプリケーションを作る時のテンプレート的なものを作りたかった
MacOS

実務の学びを活かしているけど、実務そのままとかではないし、このまま実運用した実績があるわけではない
ということで実際運用していったら微妙なところがあるかも
という予防線を張って.NET Frameworkをゼロから利用するときの参考になるかも... ならないかも...

.NET4.8以下(いわゆるIISの上でのみ動くCoreより前のASP.NET)を使っている人たち的にはコンテナとか隔世の感があるだろうし、そういうところをまるっとまとめて導入するような内容を目指したかった
そうはいってもコンテナ間疎通をとって終わりじゃなくて、大規模開発に耐えられるような設計を目指して設計構築したような感じ(その結果内容が肥大化して大変なことになった)

後述するけど基本的にコンテナでそれぞれWebAP, DBを立てて...という内容
いまのところスコープはローカル開発止まり
ステージング環境とかに乗せるならリバースプロキシとして利用するNginxに繋げる設定もしていかないとね(いつかやる)

キーワード:
.NET5, MySQL, Docker, docker-compose, DI, Dapper(EntityFrameworkは使わない), xUnit, Moq

全体の方針

ローカル開発環境

開発には偉大なるVisualStudioを利用することを前提に色々ファイルを作っている
.NET Coreとか5の開発にVSCodeを使う人が多いけど、あそびで試すんじゃなくてガッツリ作り込むなら最初から全部入りの方が楽だし...と僕は思う

WebAPとDBはDocker-composeによってコンテナで立てる
VisualStudioのソリューションにはWebAP, DB(任意。今回は含めた), docker-compose(!)の3つのプロジェクトを持たせることになる
※ docker-compose用のプロジェクトはよく見知った.csprojと異なり.dcprojという名前になる(あなたが素直ならファイル名はdocker-compose.dcprojになるだろう)

ここらへん読んだほうがいいかも

https://docs.microsoft.com/ja-jp/visualstudio/containers/docker-compose-properties?view=vs-2019

コンテナ利用

GUI操作でのコンテナを起動する

デバッガも効く
ただ、普通に動かすなら正直CLIに越したことはない

※ VS for Macはそれそのものがそこそこ怪しい

スタートアッププロジェクトにdocker-composeのプロジェクトを指定してビルドすることでWebAP, DBのコンテナが立ち上がり、デバッグも非コンテナ利用時のようにスムーズに!といった形になる

テスト

ユニットテスト(xUnit)の実行もコマンドじゃなくて素直にVisualStudioから叩ける

Mac独自の問題?たまにxUnitがバグってテストを見つけられなくなる。根本的に解決したいけど難しいという時はコマンドから叩けば素直にいく(dotnet test web.test)
根本解決したいけど、VS for Macそのものの問題な気もして面倒くさいから調べてない

ステージング/本番環境を見据えて

ステージング/本番環境ではDBはきっと固定のものを使うことになると思う
AWSならAuroraとかEC2にMySQL立ててとか

で上述の通りリバースプロキシとしてNginxも入れることになると思う
AWSならIPフィルタリングとかはALBあたりでかけられるからいいとして、コンテンツのキャッシュとかそういうののため(もしかしたら...CloudFrontでできるのかも...)

WebAPの方針

アーキテクチャ

MVVMの構成でつくる
クリーンアーキテクチャぽくしようか迷ったけどこっちにした(また別途そっちにしたい)

DB接続は上述の通りDapperを利用してSQLは手書き
手書きSQLの温かみを感じる開発を心がける。RailsのARとか怖いし...˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚

DB周りらへんには明確にRepository Pattern, DAO Patternを導入しておく
後者の採用でDBを切り替えやすく(MySQL->PostgreSQLとか)したかった
書いてる途中でDAOはアンチパターンという意見も見かけたけど今回は強い心で気にしないことにした

.NETそのものの機能とか色々

.NET 5でつくる
Dapperを使うのでEntityFrameworkは使わない

エラーハンドリングは標準のミドルウェアを利用
.NET4.8以前にあった属性でハンドリングする手法とかミドルウェアの拡張とかはしていない

.NET COREから使えるフロントのValidationは使わない
動きが不安だったしフロントではjQueryに依存してたから...

フロントエンド

jQueryを使わない
bootstrapも使わない

CSSフレームワークにはSkeletonを使いお茶を濁す

本当はReactとか入れたかった

Configとか

appsettings.json, appsettings.Development.jsonは使わない
設定値は環境変数で渡す
接続文字列も然り

ロギング

nlog
コンテナ運用前提ということでログは全部標準出力に吐く

テスト(xUnit)

元々のコードでDIしている部分のモック化にはMoqを利用
.NET CoreからフレームワークレベルでDIがサポートされるようになっているのでこの辺やりやすい

DB接続部分もといDAOのテストはこの悩みがあって結局まだ書いていない(書かなきゃ)
Repository層は単純すぎてテスト書くほどでもないなと思ってサボってしまった

【C#】【Dapper】DB接続の単体テストを考える(考えるだけ) - インドカレーファンクラブ

簡単なフォルダ構成

DotNetWebAppTemplate

├── mvctemplate.sln
│
├── docker-compose : (微妙なフォルダ名だと思う)
│   ├── docker-compose.dcproj : docker-compose用プロジェクトファイル
│   ├── docker-compose.yml : メインのやつ
│   ├── docker-compose.override.yml : ローカルデバッグ用?(VSの自動生成)
│   ├── docker-compose.vs.debug.yml : MacOSでのローカルデバッグ用(後述)
│   └── wait-for-it.sh : web起動がdb起動を待つようにするためのスクリプト
│
├── db
│   ├── db.mdproj
│   ├── data : DBデータの永続化用ディレクトリ(dockerのvolume) ※ 任意
│   ├── initdb.d/init.sql : DBデータ初期化用SQL ※ 任意
│   └── my.cnf : MySQLの設定
│
├── web
│   ├── web.csproj
│   ├── appsettings.json : WebAP用設定ファイル(使わない)
│   ├── Dockerfile : WebAP用Dockerfile
│   └── 他いろいろ
│
└── web.test
    └── web.test.csproj

docker-compose.vs.debug.ymlについて

【.NET】.NETなアプリケーションをVisualStudioからdocker-compose upしようとすると暗黙的にentrypointがoverrideされるせいでwait-for-itが無視される問題 - インドカレーファンクラブ

残課題

もう疲れたから一旦ここまでにしていつかなおす(他のことしたい)