【ASP.NET Core Web】Windowsで開発したアプリをUnuntuで公開する
Windowsで開発したASP.NET Core WebのアプリをUnuntuで公開したい!
概要
今回の記事では、Windowsで開発したASP.NET Core WebのアプリをUnuntuで公開する手順を掲載する。
仕様書
環境
- Ubuntu 20.04 LTS
- Apache 2.4.41-4ubuntu3.14
- .NET 7.0
手順書
開発(Windows)側と公開(Ubuntu)側で分けて説明する。
開発(Windows)側
-
Program.cs
に使用するポート番号を設定する。DEBUG時はWindowsでIISサーバーを起動したいのでRELEASE時のみポート番号の設定が行われるようプリプロセッサーで設定する。public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => { ... }) .ConfigureWebHostDefaults(webBuilder => { #if DEBUG // デバッグ時の処理 #else // ここで使用するポート番号を設定する webBuilder.UseKestrel(options => { options.Listen(IPAddress.Loopback, 5000); }); // UseUrlsでも設定できる //webBuilder.UseUrls("http://127.0.0.1:5000"); #endif webBuilder.UseStartup<Startup>(); }); }
UseKestrel
とUseUrls
を設定した場合はUseKestrel
が優先される。
1.「発行」で「ターゲット ランタイム」を「linux-x64」に設定して発行する。デフォルトだと<ProjectDir>\bin\Release\net7.0\publish
に必要なファイルが発行されるのでpublish
の中身を全部、WinSCPなどを使って公開サーバーにアップロードする。この記事では例としてvar/www/dotnetapp
にアップロードしたとして話を進める。
公開(Ubuntu)側
aspnetcore-runtime-7.0
が必要となるので無ければインストールする。wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb
sudo apt-get install -y apt-transport-https
sudo apt-get install -y aspnetcore-runtime-7.0
公開のみであればSDKは必要ないがSDKも欲しい場合はインストールする。
```bash
sudo apt-get install -y dotnet-sdk-7.0</code></pre>
<ol>
<li>今回はApacheからリバースプロキシで5000番のポートに接続する。Apacheの設定は下記のような感じ。例として<code>app.example.com</code>にアプリを公開する設定。
<pre><code class="language-text">
<VirtualHost *:*>
ServerName app.example.com
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost></code></pre></li>
</ol>
<p><IfModule mod_ssl.c>
<VirtualHost *:443></p>
<p>ProxyPreserveHost On
ProxyPass / <a href="http://127.0.0.1:5000/">http://127.0.0.1:5000/</a>
ProxyPassReverse / <a href="http://127.0.0.1:5000/">http://127.0.0.1:5000/</a>
ServerName app.example.com</p>
<h1>SSLやログの設定</h1>
<p>...</p>
<p></VirtualHost>
</IfModule></p>
<pre><code>1. アプリは<code>var/www/dotnetapp</code>に移動して<code>dotnet dotnetapp.dll</code>で実行できるんだけども、これだと使いにくいのでサービスとして起動できるようにする。
<code>/etc/systemd/system/dotnetapp.service</code>を作って、下記のような感じにする。
```text
[Unit]
Description=dotnetapp version 0.0.1
[Service]
ExecStart=/usr/bin/dotnet /var/www/dotnetapp/dotnetapp.dll
Restart=always
RestartSec=10
SyslogIdentifier=dotnetapp
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
WorkingDirectory=/var/www/dotnetapp
[Install]
WantedBy=multi-user.target
- ファイルを保存したら、下記のコマンドでサービスの設定ファイルを読み込み直す。
sudo systemctl daemon-reload
- アプリを起動する。
sudo systemctl dotnetapp
- Apacheを再起動する。
sudo systemctl restart apache2
- ブラウザで
app.example.com
にアクセスしてみてアプリの画面が表示されるか確認する。
アプリが起動しない場合
指定したポート番号が既に他のサービスなどで使われてる場合はアプリが起動しない。
下記のコマンドでサービスのエラーログを確認する。
sudo journalctl -fu dotnetapp
ログの内容は下記のような感じ。(長いので一部抜粋)
Unhandled exception. System.IO.IOException: Failed to bind to address http://127.0.0.1:5000: address already in use.
---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use
---> System.Net.Sockets.SocketException (98): Address already in use
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
...
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
...
指定したポート番号が既に他のサービスなどで使われてるとリバースプロキシに失敗する。
下記のコマンドで5000
が何に使われてるか確認できる。
sudo lsof -i:5000
使われないポートを使うようにアプリとApacheの設定を変更する。下記は5001
番を使う例。
webBuilder.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 5001);
});
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5001/
ProxyPassReverse / http://127.0.0.1:5001/
503
になった場合
ブラウザでアプリの画面にアクセスしても503
になってしまう場合はApacheの設定ファイルが間違ってて、リバースプロキシが失敗してる可能性が高い。
Apacheのエラーログで下記のように出力される。
[<datetime>] [proxy:error] [pid xxxxxxx] (111)Connection refused: AH00957: HTTPS: attempt to connect to 127.0.0.1:5000 (127.0.0.1) failed
[<datetime>] [proxy_http:error] [pid xxxxxxx] [client <ipaddress>] AH01114: HTTP: failed to make connection to backend: 127.0.0.1, referer: https://app.example.com/
下記のようにProxyPass
とProxyPassReverse
の項目でhttps
を設定してる場合
ProxyPreserveHost On
ProxyPass / https://127.0.0.1:5000/
ProxyPassReverse / https://127.0.0.1:5000/
...
アプリ側でSSL証明書の設定が必要になるんだけども、この設定がされてないとリバースプロキシに失敗してる。
Apacheまでが`https`通信してればセキュリティ的には問題ないので下記のように`http`通信になるように設定し直す。
```text
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
...
## まとめ(感想文)
Windowsで作ったアプリがほとんどそのままUbuntuで動くって凄い!