OITA: Oika's Information Technological Activities

@oika 情報技術的活動日誌。

CentOSにASP.NET Core 2.2でWeb API構築

AWS Lightsail のやっすいやつで CentOS 7 のインスタンスを立てたので、ASP.NET Core 2.2でWebサービスを作ってみる。

環境等

  • CentOS 7.6
  • VisualStudio Community 2019
    • 開発はローカルのWindowsマシンで行う
    • 「ASP.NET と Web 開発」ワークロードがインストールされていること
  • Apache 2.4.6
    • ASP.NET Core には Kestrel っていうデフォルトの Web サーバがついてくる
      • これだけでも動かせるはずだが、あんまりみんな使ってなさそう
    • Apache をリバースプロキシとして、リクエストを Kestrel に流すようにする

CentOS に ASP.NET Core 2.2をインストール

サーバ上でコンパイルとかするなら SDK を入れる必要があるが、今回は runtime だけ入れることにする。

なお .NET Core アプリは self-contained でビルドしてruntimeごと配布アプリに含めることもできるんだけど、 ASP.NET Core でも同じことできるんかな。
とりま今回はそれはやらず、サーバにあらかじめインストールしておきます。

参考)

$ sudo yum update
$ sudo yum install aspnetcore-runtime-2.1

サービスアプリ作成

チュートリアル: ASP.NET Core で Web API を作成するのとおりにやっていきます。

と Todo タスクの登録・参照 API ができあがる。

Apache インストールと設定

参考)

サーバに Apache をインストールし、とりあえず雑に全部 http://localhost:5000/ に受け流す。

$ sudo yum -y install httpd
$ sudo vi /etc/httpd/conf/httpd.conf
### ここからコメントアウト ###
# <Directory />
#     AllowOverride none
#     Require all denied
# </Directory>
### ここまでコメントアウト ###

### ここから追加
ProxyPreserveHost On
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
### ここまで追加

起動。

$ sudo systemctl start httpd

サーバへのデプロイ

VisualStudio から「発行」で FolderProfile を選択し、適当なローカルのフォルダを指定して実行。

吐き出されたファイル一式を、とりあえず手作業でサーバの適当な場所にコピーする。

ターミナルでサーバにログインし、作成したアプリの dll(仮に todoapp.dll )を置いたディレクトリに移動してアプリ起動。

$ dotnet todoapp.dll
Hosting environment: Production
Content root path: /path/to/todoapp
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

listening on: http://localhost:5000 とのことなので、これで 80 ポートで受け付けたリクエストが 5000 ポートで起動中のアプリに渡るようになったはず。

ブラウザから GET メソッドの URL にアクセスすれば、チュートリアルで作った todo の JSON が返ってくるはず。

SSL化

https での接続を有効にします。

参考) ApacheでLinux上でASP.NETコアをホストする - アプリをセキュリティで保護する

最初にファイアウォールに HTTPS 用のポート(443)を開けておく。
AWS Lightsail の場合は、コンソール画面の「ネットワーキング」タブから。

つづいて Apache の設定。

mod_ssl をインストール。

$ sudo yum -y install mod_ssl

参照先ページでは mod_rewrite を使って http → https の URL 書き換えをやっているが、ここでは割愛。

httpd.conf で、先ほど追加したリバースプロキシ設定の下に SSL の設定を追記する。

$ sudo vi /etc/httpd/conf/httpd.conf
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

この例だとローカルの証明書を使ってるので、このままだとブラウザで警告が表示される。
本来はちゃんと署名されたやつを使いましょう。

サービス再起動。

$ sudo systemctl restart httpd

これで、https の URL で GET できるようになり、http の URL だと 400 Bad Request が返るようになっているはず。

データ永続化

チュートリアルの TODO アプリのままだと、サーバを落としたタイミングでそれまでの登録データが全部リセットされてしまうので、データベースに値を保持するように変えてみる。

サーバに DB たてるぞって時点で、一旦めんどくせぇなーってなっちゃうんだよな。インフラ筋が足りない。
てわけで、簡単に SQLite でやることにします。

このへんは前にもちょっと書いた。

ASP.NET Core × Entity Framework × SQLite - OITA: Oika's Information Technological Activities

NuGet から以下2つインストール。

  • Microsoft.EntityFrameworkCore.Tools
  • Microsoft.EntityFrameworkCore.Sqlite

チュートリアルの中ですでに DbContext クラスとかは作ってるので、変える必要があるのは Startup.cs 内、 UseInMemoryDatabase とやっていたところだけ。

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
    services.AddDbContext<TodoContext>(opt => opt.UseSqlite(@"Data Source='data.db'"));

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

VS のパッケージマネージャーコンソールから下記コマンドで DB ファイル(data.db)を生成しておく。

PM> Add-Migration InitTable
PM> Update-Database  

デプロイの際に、生成された data.db も忘れずに配備する。上記の書き方だと dll と同じ場所に配置。
VSで「発行」したときに出力される SQLite 系の dll も同じように全部配備する。

以上

とりあえずこんなところか。以下積み残し(当分やらないと思うけど)

  • リバースプロキシの真面目な設定
  • SSL の真面目な設定
  • DB の真面目な構築
  • アプリのサービス化と監視
  • CI/CD の構築