きなこもち.net

.NET Framework × UiPath,Orchestrator × Azure × AWS × Angularなどの忘備録

ubuntu × .NET 5 × 初めてのアプリケーションのデプロイ

目的

Ubuntuで本番稼働を想定したASP.NET coreアプリケーションの実行環境を構築する。

参考

Nginx搭載のlINUXでASP.NET Coreをホストする

本題

アプリケーションの作成と、動作確認

アプリケーションの中身にはこだわらないので、テンプレートで作成したものをPublishしていく。 実行コマンド。
> mkdir helloworld
> cd helloworld/
> dotnet new webapi
> dotnet run

ここまでで、アプリの作成と起動ができた。https://localhost:5001/swagger/index.htmlにアクセスし、動作を確認する。Swaggerの画面が開けば、OK。

デプロイ対象のDLLの作成とデプロイ

前のステップで作成、実行されたDLLは、Debug用のDLLとなる。そのため、Release用のDLLの作成は別途行う。このとき、一般的にwEBアプリが配置されるとされるディレクトリ(/var/www/)配下に、アプリケーション用のディレクトhelloworldを作成する。dotnet publishコマンド実行時には、作成下ディレクトリ配下に出力されるように-oオプションを設定する。

> sudo mkdir -p /var/www/helloworld
> sudo dotnet publish -o /var/www/helloworld

出来上がったファイルたちの確認。
> ls /var/www/helloworld

total 3792
-rw-rw-r-- 1 root root     162  4月 24 17:34 appsettings.Development.json
-rw-rw-r-- 1 root root     192  4月 24 17:34 appsettings.json
-rwxr-xr-x 1 root root  138528  4月 24 17:59 helloworld
-rw-rw-r-- 1 root root  107626  4月 24 17:59 helloworld.deps.json
-rw-rw-r-- 1 root root   10752  4月 24 17:59 helloworld.dll
-rw-rw-r-- 1 root root   20380  4月 24 17:59 helloworld.pdb
-rw-rw-r-- 1 root root     292  4月 24 17:59 helloworld.runtimeconfig.json
-rwxr--r-- 1 root root  173960  8月 29  2020 Microsoft.OpenApi.dll
-rwxr--r-- 1 root root   15872  9月 23  2020 Swashbuckle.AspNetCore.Swagger.dll
-rwxr--r-- 1 root root   80384  9月 23  2020 Swashbuckle.AspNetCore.SwaggerGen.dll
-rwxr--r-- 1 root root 3308544  9月 23  2020 Swashbuckle.AspNetCore.SwaggerUI.dll
-rw-r--r-- 1 root root     486  4月 24 17:59 web.config

アプリを実行し、Swaggerにアクセスしてみる。
> cd /var/www/helloworld > dotnet run

・・・が、https://localhost:5001/swagger/index.htmlにアクセスしても表示されない。生成されたアプリのStartup.csを見てみると、Swaggerが利用されるのは、実行環境がDevelopmentのときだけになっていた。SwaggerのオプションをIf文のスコープから外し、Releaseモードのときも利用できるようにしたら期待通りの動作になった。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "KestrelSample v1"));

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

サービスの起動

前のステップでは、DOTNETコマンドを利用してkestrelプロセスを起動した。次は、SYSTEMDを利用し、サービスとしてHelloworldアプリを登録し、SYSTEMDによって、サービスの起動・停止・監視を行うように設定を進める。
参考) - なぜsystemdなのか? - DOCUMENT

サービスファイルの作成

[Unit]
Description=Example .NET Web API App running on Ubuntu

[Service]
WorkingDirectory=/var/www/helloworld
ExecStart=/usr/bin/dotnet /var/www/helloworld/helloworld.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-helloworld
User=kinakomotitti
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

登録と起動

以下のコマンドで、サービスを有効化&起動。
> sudo systemctl enable helloworld
> sudo systemctl start helloworld
サービスの状態を確認する。
> sudo systemctl status helloworld

● helloworld.service - Example .NET Web API App running on Ubuntu
     Loaded: loaded (/etc/systemd/system/helloworld.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-04-24 19:30:46 JST; 9s ago
   Main PID: 211090 (dotnet)
      Tasks: 20 (limit: 9113)
     Memory: 27.9M
     CGroup: /system.slice/helloworld.service
             └─211090 /usr/bin/dotnet /var/www/helloworld/helloworld.dll

ここまでで、アプリケーションサーバーの起動ができた。あとは、Webサーバーとしてより高機能なものを利用してアクセスできるようにする。

リバースプロキシサーバーの設定

dotnet coreでは、kestrelという規定のクロスプラットフォームHTTPサーバーがある。これを利用してWebアプリケーションを実行することは可能だが、リバースプロキシ(IIS,Nginx,Apacheなど)を利用することで、以下のメリットを享受することができる。このときの処理の流れは、
Client -> リバースプロキシ -> Kestrel -> アプリケーション本体
となる。

  • ホストするアプリの公開されるパブリック サーフェス領域を制限することができます。
  • 構成および防御の層を追加します。
  • 既存のインフラストラクチャとより適切に統合できる場合があります。
  • 負荷分散とセキュリティで保護された通信 (HTTPS) の構成を簡略化します。
  • リバース プロキシ サーバーのみで X.509 証明書が必要です。
  • このサーバーでは、プレーンな HTTP を使用して内部ネットワーク上のアプリのサーバーと通信することができます。

Nginxのインストール

Official Debian/Ubuntu packagesに従い、インストールする。
> sudo apt-get update
> sudo apt-get install nginx
> sudo systemctl status nginx

もし起動していなかったら、systemctl start nginxで起動させる。

Nginxの構成を修正する

/etc/nginx/sites-available.defaultテキストエディターで開き、修正する。今回は、localhostに対するリクエストをkestrelに転送してほしかったため、規定で作成されたdefaultファイルを以下のとおりに変更した。

# もともとコメントアウトされていた箇所は省略。
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        #root /var/www/html;
        server_name _;
        location / {
                # 追加↓
                proxy_pass         http://127.0.0.1:5000;
                # コメントアウト↓
                # try_files $uri $uri/ =404;
        }
}

sudo nginx -s reloadコマンドで上記変更を矯正適用すると、http:/localhost/swaggerでHelloworldアプリのSwaggerにアクセスすることができた。

Logの確認

Nginxのアクセスログについては、> tail -f /var/log/nginx/access.logで確認することができる。 Kestrelで実行されているHelloworldアプリの標準出力は、> sudo journalctl -fu hellowold で確認することができる。ただし、いまはログ出力の処理を実装していないため、何も表示されない。