结合Nginx将asp net core部署在Linux(ubuntu)上[基于微软官方文档翻译并补充]

以下为微软官方说明文档原地址,先贴出
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.2

本指南介绍如何在Ubuntu 16.04服务器上部署asp.net core环境。以下指南应该也适用于更新的Ubuntu版本,但我们并没有进行测试。

NOTE
对于Ubuntu14.04版本,建议使用守护进程 supervisord 命令去监听Kestrel进程,因为 systemd 命令在Ubuntu上是不可用的,关于更多的Ubuntu14.04说明,参见此处

\color{#0094ff}{\large{本指南包含内容:}}
  • 将现有的asp net core应用程序部署在反向代理服务器上(Nginx)
  • 设置反向代理服务器将请求转发到Kestrel Web服务上
  • 确保Web应用程序启动运行在守护进程下
  • 配置进程管理工具以帮助重新启动Web应用程序
\color{#0094ff}{\large{必要条件:}}
  • 在Ubuntu16.04服务器上有一个拥有sudo权限的标准账户,
  • 在服务器上安装了.NET Core Runtime 安装教程参考
  • 一个已经开发完成的ASP.NET Core应用程序

发布和拷贝整个ASP.NET Core应用程序

如果应用程序在本地运行且未配置为进行安全连接https,请采用以下任一方法:

  • 配置安全链接,详情参见 HTTPS configuration
  • Properties/launchSettings.json文件中,移除 applicationUrlhttps://localhost:5001的属性参数

在开发环境下运行dotnet publish命令将应用程序打包到publish目录下

dotnet publish --configuration Release

如果你不希望部署到服务器上,而是让应用程序独立运行那么参见此处

将打包好的应用程序,例如publish/helloapp,那么将helloapp文件夹通过SCP或者SFTP或者其他FTP工具拷贝到服务器上,一般网站app放在var/www目录下,若不存在www目录请自行建立,最终目录结构为var/www/helloapp

测试你的应用程序:
1.从命令行运行你的应用:dotnet <你的程序集名称>
2.打开浏览器中,在地址栏输入http://<ubuntu服务器IP地址>:<端口>,查看浏览器是否看到正常内容

\color{red}{踩坑记录}
如果出现无法方问此网站,请检查代理服务器和防火墙,那么

  • 查看服务器的安全组策略,确保防火墙允许访问对应的<端口>
  • 可能是应用程序使用了默认的配置,那么默认部署在服务器上的配置监听是http://localhost:5000,此处的localhost会导致无法方问,需要改成http://127.0.0.1:5000或者http://0.0.0.0:5000
    可以在应用程序开发时在Program.cs文件中在启动StartUp前,调用
    UseUrls("http://*:5000")或者UseUrls("http://127.0.0.1:5000")

注意:如果确认使用Nginx反向代理,那么此处使用http://localhost:5000即使无法访问也不影响,通过后续配置nginx代理即可访问了

public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://*:5000")
                .UseStartup<Startup>();
    }

配置反向代理服务器

反向代理是是一个很常用的设置对于动态Web应用来说。反向代理会终止HTTP请求并将其转发到ASP.NET Core应用程序。

使用反向代理服务

Kestrel非常适合为来自ASP.NET核心的动态内容提供服务。但是,Web服务功能并不像IIS、Apache或nginx等服务器那样功能丰富。反向代理服务器可以从HTTP服务器卸载服务静态内容、缓存请求、压缩请求和HTTPS终止等工作。反向代理服务器可以驻留在专用计算机上,也可以与HTTP服务器一起部署。

在本指南中,只使用一个nginx实例。它与HTTP服务器一起运行在同一个服务器上。根据需要,可以选择不同的设置。

因为请求是由反向代理转发的,所以请使用来自microsoft.aspnetcore.httpoverrides包的转发头中间件。中间件使用x-forwarded-proto头更新request.scheme,以便重定向URI和其他安全策略正常工作。

任何依赖于方案的组件,如身份验证、链接生成、重定向和地理位置,都必须在调用转发头中间件之后配置。一般情况下,除了诊断和错误处理中间件之外,转发头中间件都应该先于其他中间件运行。这种排序确保依赖转发头信息的中间件可以使用header values进行处理。

在Startup.cs文件的Configure()方法中调用useForwardedHeaders方法,且必须在调用useAuthentication或类似的身份验证方案中间件之前进行配置。配置中间件来转发x-forwarded-forx-forwarded-proto头:

//这里很重要,由于通过nginx转发给.netcore处理,所以如果不配置此项,那么想在netcore中获取访问端的IP的话,导致无法获取
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

#下方权限不启用可以不填
app.UseAuthentication();

如果没有为中间件指定ForwardedHeadersOptions,则默认要转发的头为none。

默认情况下,回送地址(127.0.0.0/8,[::1])上运行的代理(包括标准本地主机地址(127.0.0.1))是受信任的。如果组织内的其他受信任代理或网络处理Internet和Web服务器之间的请求,请将它们添加到具有ForwardedHeaders选项的KnownProxiesKnownNetworks列表中。下面的示例将IP地址为10.0.0.100的受信任代理服务器添加到Startup.cs文件的ConfigureServices()方法中的转发头中间件KnownProxies中:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

更多反向代理和负载均衡配置,请参见

安装 Nginx

使用apt-get安装nginx。安装程序创建一个systemd init脚本,在系统启动时将nginx作为守护进程运行。按照nginx上Ubuntu的安装说明:官方debian/Ubuntu软件包。

Note
如果需要可选的nginx模块,则可能需要从源代码构建nginx。

PS:如果是CentOS系统,那么请使用sudo yum install nginx来安装nginx

由于nginx是第一次安装的,请通过运行以下命令来显式启动:

sudo service nginx start

##如果需要开机自启动,请执行
systemctl enable nginx.service

要将nginx配置为将请求转发到ASP.NET核心应用程序的反向代理,请修改/etc/nginx/sites-available/default 在文本编辑器中打开它,并用以下内容替换对应的server节点部分:

配置Nginx

server {
    listen        80;
    server_name   example.com *.example.com;
    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   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}
PS:如果是CentOS系统,那么请修改/etc/nginx/nginx.conf文件

当没有server_name服务器名称匹配时,nginx使用默认服务器。如果未定义默认服务器,则配置文件中的第一个服务器是默认服务器。作为最佳实践,添加一个特定的默认服务器,该服务器在配置文件中返回状态代码404。默认服务器配置示例为:

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   404;
}

对于前面的配置文件和默认服务器,nginx接受主机头example.com或*.example.com的端口80上的公共流量。与这些主机不匹配的请求将不会转发到kestrel。nginx将匹配的请求转发到kestrel,网址为http://localhost:5000。有关更多信息,请参阅nginx如何处理请求。要更改Kestrel的IP/端口,请参阅Kestrel:端点配置。

一旦建立了nginx配置,运行sudo nginx -t来验证配置文件的语法。如果配置文件测试成功,则通过运行
sudo nginx -s reload强制nginx接受更改。

要在服务器上直接运行应用程序,请执行以下操作:
1.定位到app所在目录
2.执行命令dotnet <你的启动应用程序集名称>.dll

如果应用程序在服务器上运行,但无法通过Internet响应,请检查服务器的防火墙并确认端口80已打开。如果使用Azure Ubuntu VM,请添加启用入站端口80流量的网络安全组(NSG)规则。不需要启用出站端口80规则,因为在启用入站规则时会自动授予出站流量。

监控应用程序

服务器设置为将向http://<serverAddress>:80的请求,转发给http://127.0.0.1:5000上的Kestrel ASP.NET核心应用程序处理,http://<serverAddress>:80。但是,nginx并没有被设置为管理Kestrel进程。systemd 可用于创建服务文件以启动和监视基础Web应用程序。systemd是一个init系统,它为启动、停止和管理进程提供了许多强大的功能。

创建服务文件

创建一个服务定义文件

sudo nano /etc/systemd/system/kestrel-myapp.service

以下为试列文件:

[Unit]
Description=WebAPI On Linux                                                               #此处表示描述

[Service]
WorkingDirectory=/var/www/myapp                                                     #工作目录
ExecStart=/usr/bin/dotnet /var/www/myapp/myapp.dll                         #通过命令执行指定的文件
Restart=always                                                                                      #是否重启
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10                                                                                      #监听时间
KillSignal=SIGINT                                                                                 #Kill信号
SyslogIdentifier=dotnet-example                                                          #系统日志表击
User=root                                                                                              #用户
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

Note
Linux有一个区分大小写的文件系统。将ASPNETCORE_ENVIRONMENT=Production将导致搜索配置文件appsettings.Production.json,而不是appsettings.production.json。

保存文件然后启用服务:

sudo systemctl enable kestrel-myapp.service

启动服务并验证它是否正在运行。

sudo systemctl start kestrel-myapp.service
sudo systemctl status kestrel-myapp.service

配置反向代理并通过systemd管理kestrel后,Web应用程序已完全配置,可以从本地计算机上的浏览器(http://localhost)访问。也可以从远程机器访问,除非被防火墙阻挡。检查响应头时,服务器头会显示由Kestrel提供服务的ASP.NET核心应用程序。

访问日志

由于使用kestrel的Web应用程序是使用systemd管理的,因此所有事件和进程都会记录到一个集中的日志中。但是,此日志包含由systemd管理的所有服务和流程的所有条目。要查看kestrel-helloapp.service特定项,请使用以下命令:

sudo journalctl -fu kestrel-myapp.service

For further filtering, time options such as --since today, --until 1 hour ago or a combination of these can reduce the amount of entries returned.

sudo journalctl -fu kestrel-myapp.service --since "2016-10-18" --until "2016-10-18 04:00"

补充:CentOS7下使用supervisor守护进程

通过yum安装supervisor,注意,如果使用python pip安装,那么最好确保是python2的版本,python3现在可以使用supervisor,但是通过pip安装的可能会出现异常

yum install supervisor

配置守护进程信息

切换到supervisord.d目录,该目录下的ini文件都会在supervisor服务启动时被守护执行
cd /etc/supervisord.d

#在此新建一个supervisor的.ini配置文件
touch myappserver.ini

vim myappserver.ini

#下面所有注释的内容都要删除,包括这一句
[program:myappserver]                          #配置当前守护进程服务的名称,supervisord可直接通过名称启动服务
directory=/var/www/myapp                     #工作目录,即应用程序集所在目录
command=dotnet 我的应用程序集.dll     #执行的命令
environment=ASPNETCORE__ENVIRONMENT=Production
user=root
stopsignal=INT
autostart=true
autorestart=true
startsecs=10                                             #进程持续运行多久才认为是启动成功
stderr_logfile=/var/log/myappserver.err.log    
stdout_logfile=/var/log/myappserver.out.log

启动supervisord 守护程序,启动后会执行supervisord.d目录下的ini文件

supervisord -c /etc/supervisord.conf

设置开机启动守护程序supervisord

systemctl enable supervisord.service

重启supervisord

supervisorctl reload