はじめに
MariaDB(MySQL)を使った.NETCore3.1+IdentityのDocumentが少ないので作成。
ゼロから構築していくエントリーとしますので、最初から全部書いていきます。
KestrelからNginxに橋渡ししてますが、Webサーバは本稿のキモとは関係がないでしょう。
構成
Architecture | Name |
---|---|
Machine | Azure |
OS | CentOS 8 |
Web Server | Nginx |
Framework | .NETCore 3.1 |
DB | Azure Database for MariaDB |
手順
.NETCore 3.1 の導入
sudo su
yum update -y
yum install -y libunwind libicu lsof
yum list | grep dotnet
yum install -y dotnet-sdk-3.1.x86_64
dotnet --version
Projectの作成
mkdir /var/www/html -p
cd /var/www/html
dotnet new mvc --auth Individual -o TestProject
今回はMVCで立てます。
MariaDB用のPackageを導入
cd TestProject
dotnet add package Pomelo.EntityFrameworkCore.MySql
エディタでのSSH接続
以降に出てくるコマンド以外の編集作業はVisual Studio CodeあたりでSSH接続すれば非常に快適。
ググればエントリーは無限に出てきますので、ここでは割愛します。
Kestrelの構築
Program.cs
webBuilder.UseUrls("http://0.0.0.0:5000/"); //追記
webBuilder.UseStartup<Startup>();
/etc/systemd/system/kestrel-test.service
(新規作成)
[Unit]
Description=Example .NET Web API App running on CentOS
[Service]
WorkingDirectory=/var/www/html/TestProject
ExecStart=/usr/bin/dotnet /var/www/html/TestProject/published/TestProject.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
#Environment=ConnectionStrings__DefaultConnection={Connection String}
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target
コマンド実行
systemctl daemon-reload
systemctl enable kestrel-test.service
systemctl restart kestrel-test.service
nginxの構築
/etc/nginx/nginx.conf
server_name write.your.ip.address;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
nginx -s reload
SELinuxによるアクセス制御設定
setsebool -P httpd_can_network_connect 1
HTTPS Redirectionの一時停止(省略可)
Startup.cs
//app.UseHttpsRedirection(); //コメントアウト
MariaDBの構築
yum install mariadb -y
mysql -h write.mariadb.ip.address -u username -p
create database dbname;
exit
.NETCoreとMariaDBとの接続
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=write.mariadb.ip.address;userid=username;password=yourpassword;database=dbname;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Startup.cs
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(
Configuration.GetConnectionString("DefaultConnection")));
.NETCore Identityによる認証の実装
Identity関連TableのMigration File修正
MariaDB(MySql)の環境下においては、IdentityがDefaultで持っているMigation Fileを無修正で実行できない。
⇒nvarchar(MAX)やDateTimeOffset型がないため。
Data/Migrations/00000000000000_CreateIdentitySchema.cs
・DateTimeOffsetをひとまず<string>
に書き換え。
たとえばこんなかんじ
// LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnd = table.Column<string>(nullable: true),
Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs
・nvarchar(MAX)
をひとまずnvarchar(1024)
で置換(そんなにいらないかもしれない)。
・DateTimeOffset
をひとまず<string>
のnvarchar(64)
に書き換え。
※DateTimeOffsetカラムについては、Defaultの設定だと何のデータもInsertされてこないのでErrorにはならない。
たとえばこんなかんじ
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(1024)");
Migrationの実行
準備ができたらMigrationを実行する。
dotnet ef database update
Migrationの実行でエラーが出てしまった場合は、DB側に出来てしまったTable群を削除し、再実行する。
⇒Foreign制約がかかっているため、綺麗に同時消しができなかったりする。Tableを消すときの順番に注意。
なお、成功した場合は以下のようになる。
$ dotnet ef database update
Build started...
Build succeeded.
Done.
Migrationに成功した場合であっても、やり直したいと思うことがあるかもしれない。
その場合は、Migration Fileの編集+Table群のDropで再度Migrationを実行することもできる。
ただし、Migrationが一度完了となった旨の情報が__efmigrationshistory
Tableに格納されているので、
Migrationの再実行をする前に、DB側で以下コマンドの実行が必要となる。
truncate table __efmigrationshistory;
⇒上記Truncateを実行しないと、いくらdotnet ef database update
しようとも、何も実行しないMigrationがDoneになるだけとなる。
Identity関連のスキャフォールディング
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet aspnet-codegenerator identity -dc TestProject.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout"
最後の行にはProject名が刺さっているので、適宜変更されたい。
実行
恒久的な実行
既にNginxとKestrelを常時立ち上げるように設定していますので、あとはコンパイルするだけ。
dotnet publish -o published -r centos.8-x64 && systemctl restart kestrel-test.service
コンパイル中にブラウザからアクセスしてしまう等の原因により、Processがバインドされ、上記コマンドがエラーとなることがまれに良くある。
この問題はreboot
すれば解決するが、いちいち再起動は地獄。
そんな時は、先にsystemctl restart kestrel-test.service
を実行してやると回復する。
というか、なんなら最初から以下のコマンドをおすすめしておく。
systemctl restart kestrel-test.service && dotnet publish -o published -r centos.8-x64 && systemctl restart kestrel-test.service
ズボラ極まりないコマンドだが、こうかはばつぐんだ。
開発中の実行
開発中のデバッグ作業であれば、Visual Studio Codeのターミナルからdotnet run
すれば非常に便利。
デバッグ用のConsole.WriteLineの出力も同じくターミナルのところに出力されるようになるので、開発ではどんどん使っていきましょう。
ただ、既に kestrel-test.service
を走らせてしまっているので、これを一旦止める必要がある。
systemctl stop kestrel-test.service
dotnet run
おわり
これでブラウザ上のRegisterからユーザ登録ができると思います。
とっつきにくさ天元突破のMicrosoft公式Documentに頼らざるを得ない部分も多いので、辛みが深いですね。