如何在Linux上运行 ASP.NET 核心Web应用程序作为服务,没有反向代理,没有NGINX或Apache

本文将引导我们使用 systemd 在 Linux (RHEL) 上运行 ASP.NET Core Web 应用程序。以下是我们将介绍的内容:

  1. 使用 systemd 运行 ASP.NET 核心
  2. 添加 Systemd 集成包
  3. 使 ASP.NET Core 可从外部访问(仅限 Kestrel,无反向代理)
  4. 通过端口 80 和 443 ASP.NET Core 提供服务(仅限 Kestrel,无反向代理)

最终目标是通过端口 80/443 通过内置的 Kestrel Web 服务器直接为 ASP.NET Core 提供服务。
没有反向代理,没有NGINX,也没有Apache。
反向代理很棒,仍然推荐,但已经有足够的文档。

要了解如何在 Linux 上运行 .NET Core 服务(非 Web 内容),请查看"如何在 Linux 上使用 Systemd 运行 .NET Core 即服务""

先决条件:

  • Red Hat Enterprise Linux(或兼容的基于 Unix 的操作系统)
  • 已安装 .NET Core 3.1(来自红帽的入门说明)
  • 苏多特权

本演练应该适用于大多数 .NET Core 支持的 Linux 发行版,而不仅仅是 RHEL。

使用 Systemd 运行 ASP.NET 核心#

让我们首先使用 Web 模板创建一个新的 ASP.NET 核心应用程序:

mkdir ~/AspNetSite
cd ~/AspNetSite
dotnet new web

我们将在整个演练中使用此应用程序。让我们验证 Web 应用程序是否正常工作:

dotnet run
# Output should looks like this:
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: https://localhost:5001
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: http://localhost:5000
#   info: Microsoft.Hosting.Lifetime[0]
#         Application started. Press Ctrl+C to shut down.
#   info: Microsoft.Hosting.Lifetime[0]
#         Hosting environment: Development
#   info: Microsoft.Hosting.Lifetime[0]
#         Content root path: /home/yourusername/AspNetSite

打开一个单独的 shell(让另一个 shell 保持运行),并使用 curl HTTP 客户端向应用程序发送 HTTP 请求:

# while 'dotnet run' is running, open a new shell to run this curl command
curl http://localhost:5000
# Output should be 'Hello World!'

如果应用程序工作正常,我们可以将其发布到逻辑上的位置,例如"/srv/AspNetSite":

sudo mkdir /srv/AspNetSite
sudo chown yourusername /srv/AspNetSite/
dotnet publish -c Release -o /srv/AspNetSite/

发布的结果包含一个名为"AspNetSite"的可执行文件,它将运行该应用程序。让我们验证一下我们也可以运行已发布的应用程序:

cd /srv/AspNetSite/
./AspNetSite
# Output should looks like this:
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: http://localhost:5000
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: https://localhost:5001
#   info: Microsoft.Hosting.Lifetime[0]
#         Application started. Press Ctrl+C to shut down.
#   info: Microsoft.Hosting.Lifetime[0]
#         Hosting environment: Production
#   info: Microsoft.Hosting.Lifetime[0]
#         Content root path: /srv/AspNetSite

确保通过运行""返回到原始目录。为了在 Linux 上运行服务,Systemd 使用"服务单元配置"文件来描述如何运行服务。让我们在项目中创建文件"AspNetSite.service",以便我们可以将其与代码一起存储在源代码管理中。将以下内容添加到"AspNetSite.service":cd ~/AspNetSite

[Unit]
Description=ASP.NET Core web template

[Service]
# will set the Current Working Directory (CWD)
WorkingDirectory=/srv/AspNetSite
# systemd will run this executable to start the service
ExecStart=/srv/AspNetSite/AspNetSite
# to query logs using journalctl, set a logical name here  
SyslogIdentifier=AspNetSite

# Use your username to keep things simple, for production scenario's I recommend a dedicated user/group.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app.
# To update permissions, use 'chown yourusername -R /srv/AspNetSite' to take ownership of the folder and files,
#       Use 'chmod +x /srv/AspNetSite/AspNetSite' to allow execution of the executable file.
User=yourusername

# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service              
RestartSec=5

# copied from dotnet documentation at
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1#code-try-7
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

# This environment variable is necessary when dotnet isn't loaded for the specified user.
# To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell.
Environment=DOTNET_ROOT=/opt/rh/rh-dotnet31/root/usr/lib64/dotnet

[Install]
WantedBy=multi-user.target

请务必将"用户"更新为用户名。有关指定选项的说明,请参阅注释。有关服务单元配置文件的更多信息,请阅读 freedesktop 手册页红帽文档

Systemd 希望所有配置文件都放在 "/etc/systemd/system/" 下。将服务配置文件复制到"/etc/systemd/system/AspNetSite.service",并告诉 systemd 重新加载配置文件。

sudo cp AspNetSite.service /etc/systemd/system/AspNetSite.service
sudo systemctl daemon-reload

现在,systemd 知道了新的"AspNetSite"服务。使用""我们可以启动服务。
使用''我们可以查询服务的状态。让我们启动该服务并检查其状态:systemctl start AspNetSitesystemctl status AspNetSite

sudo systemctl start AspNetSite
sudo systemctl status AspNetSite
# Output should be similar to below:
#   ● AspNetSite.service - ASP.NET Core web template
#      Loaded: loaded (/etc/systemd/system/AspNetSite.service; enabled; vendor preset: disabled)
#      Active: active (running) since Wed 2020-01-29 17:06:24 UTC; 13s ago
#    Main PID: 5187 (AspNetSite)
#      CGroup: /system.slice/AspNetSite.service
#              └─5187 /srv/AspNetSite/AspNetSite
#   
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: Now listening on: http://localhost:5000
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: Now listening on: https://localhost:5001
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: Application started. Press Ctrl+C to shut down.
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: Hosting environment: Production
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:06:25 rhtest AspNetSite[5187]: Content root path: /srv/AspNetSite

由于""选项,systemd将在服务崩溃时重新启动我们的服务。但它不会在计算机重新启动时自动启动服务。要启用自动启动,请使用以下命令:Restart=always

sudo systemctl enable AspNetSite

如果一切正常,我们应该能够通过localhost:5000卷曲应用程序:

curl http://localhost:5000
# Output should be 'Hello World!'

该网站现在作为 systemd 服务运行。微软提供了一个systemd软件包,以改善与systemd的集成。接下来让我们进行设置。

添加 Systemd 集成包#

微软最近添加了一个软件包,以更好地与systemd集成。安装集成后,应用程序将在准备就绪和停止时通知 systemd。此外,systemd 将了解应用程序记录的不同日志级别

使用 dotnet CLI,添加 "Microsoft.Extensions.Hosting.Systemd" (nuget) 包:

dotnet add package Microsoft.Extensions.Hosting.Systemd --version 3.1.1

接下来,我们需要在"程序.cs"中添加一行:.UseSystemd()

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSystemd()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

出于日志记录集成的演示目的,请使用以下内容更新"程序.cs"文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace AspNetSite
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    logger.LogInformation("Information - Hello World");
                    logger.LogWarning("Warning - Hello World");
                    logger.LogError("Error - Hello World");
                    logger.LogCritical("Critical - Hello World");
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}

最后,我们需要更新文件"AspNetSite.service"以指定"type=Notify":

[Unit]
Description=ASP.NET Core web template

[Service]
Type=notify
# will set the Current Working Directory (CWD)
WorkingDirectory=/srv/AspNetSite
# systemd will run this executable to start the service
ExecStart=/srv/AspNetSite/AspNetSite
# to query logs using journalctl, set a logical name here
SyslogIdentifier=AspNetSite

# Use your username to keep things simple, for production scenario's I recommend a dedicated user/group.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app.
# To update permissions, use 'chown yourusername -R /srv/AspNetSite' to take ownership of the folder and files,
#       Use 'chmod +x /srv/AspNetSite/AspNetSite' to allow execution of the executable file.
User=yourusername

# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service
RestartSec=5

# copied from dotnet documentation at
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1#code-try-7
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

# This environment variable is necessary when dotnet isn't loaded for the specified user.
# To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell.
Environment=DOTNET_ROOT=/opt/rh/rh-dotnet31/root/usr/lib64/dotnet

[Install]
WantedBy=multi-user.target

让我们部署所有更改。我们需要发布 .NET 应用并停止/重新加载/启动 systemd 服务:

sudo systemctl stop AspNetSite
dotnet publish -c Release -o /srv/AspNetSite/
sudo cp AspNetSite.service /etc/systemd/system/AspNetSite.service
sudo systemctl daemon-reload
sudo systemctl start AspNetSite

systemd 正在捕获应用程序日志。我们可以使用"journalctl"查询日志,以下是一些示例:

sudo journalctl -u AspNetSite #query all output, oldest to newest
sudo journalctl -u AspNetSite -f #query all output and follow live
sudo journalctl -u AspNetSite -r #query all output, newest to oldest
sudo journalctl -u AspNetSite --since="2020-01-17 11:00:00" --until="2020-01-17 11:15:00" #filter by time

单位标志(-u)允许我们按我们在"AspNetSite.service"中指定的"SyslogIdentifier"进行过滤。
我们可以通过使用"journalctl"上的优先级标志(-p)来验证.NET Core日志记录是否正确集成。这将根据以下日志级别筛选输出:

日志级别系统日志级别系统名称
跟踪/调试7调试
信息6信息
警告4警告
错误3犯 错
危急2克里特

例如,以下命令将仅打印日志级别为 4 及以下的输出,表示警告、错误和严重:

sudo journalctl -u AspNetSite -p 4
# Output should be empty

让我们首先使用 curl 向应用程序发出几个 HTTP 请求,然后运行 "journalctl" 查询:

curl http://localhost:5000
curl http://localhost:5000
curl http://localhost:5000
sudo journalctl -u AspNetSite -p 4

'journalctl' 命令现在应该返回我们编写了 3 次的不同日志语句。

在 systemd 服务外部运行时,"UseSystemd"函数不会执行任何操作。该实现检查操作系统是否是Unix系统,以及父进程是否为系统化。
否则,将跳过 systemd 集成。

现在,我们已经准备好了 systemd 集成,但应用程序仍然无法在机器外部访问。让我们使应用程序可在外部访问。

使 ASP.NET 核心可从外部访问#

如下所示,只能通过计算机上的本地主机访问应用程序,而不能通过计算机的 IP 地址访问应用程序。

curl http://localhost:5000
# Output should be 'Hello World!'

# try curl'ing using your machine's IP, to list IP's on RHEL use 'ip addr show'
curl http://10.0.0.4:5000
# Output should be 'curl: (7) Failed to connect to 10.0.0.4 port 5000: Connection refused'

开箱即用,应用程序配置为监听 http://localhost:5000 和 https://localhost:5001。这对于开发非常有用,但是我们希望将我们的应用程序公开给网络中的其他计算机,甚至向Internet公开。在 ASP.NET Core中,有很多方法可以配置URL。我们可以通过代码,appsettings.json,环境变量或命令行参数来配置它
让我们使用环境变量。将"ASPNETCORE_URLS"环境变量添加到"AspNetSite.service"文件中:

[Unit]
Description=ASP.NET Core web template

[Service]
Type=notify
# will set the Current Working Directory (CWD)
WorkingDirectory=/srv/AspNetSite
# systemd will run this executable to start the service
ExecStart=/srv/AspNetSite/AspNetSite
# to query logs using journalctl, set a logical name here  
SyslogIdentifier=AspNetSite

# Use your username to keep things simple, for production scenario's I recommend a dedicated user/group.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app.
# To update permissions, use 'chown yourusername -R /srv/AspNetSite' to take ownership of the folder and files,
#       Use 'chmod +x /srv/AspNetSite/AspNetSite' to allow execution of the executable file.
User=yourusername

# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service              
RestartSec=5

# copied from dotnet documentation at
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1#code-try-7
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

# This environment variable is necessary when dotnet isn't loaded for the specified user.
# To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell.
Environment=DOTNET_ROOT=/opt/rh/rh-dotnet31/root/usr/lib64/dotnet

# When using the out of the box ASP.NET Tempates, this environment variable will allow you to override 
# which IP & ports the Kestrel Web Server will listen to. 
# Using the * as a wildcard will listen to any IP, localhost and other IP's the machine may have
Environment=ASPNETCORE_URLS=http://*:5000;https://*:5001


[Install]
WantedBy=multi-user.target

星号 (*) 将充当通配符,而不是指定 localhost 或 IP 地址。应用程序现在将侦听本地主机和分配给计算机的所有 IP 地址。

让我们复制更新的配置文件并重新加载/重新启动 systemd 服务:

sudo cp AspNetSite.service /etc/systemd/system/AspNetSite.service
sudo systemctl daemon-reload
sudo systemctl restart AspNetSite
sudo systemctl status AspNetSite
# Output should be similar to below:
#   ● AspNetSite.service - ASP.NET Core web template
#      Loaded: loaded (/etc/systemd/system/AspNetSite.service; enabled; vendor preset: disabled)
#      Active: active (running) since Wed 2020-01-29 17:17:48 UTC; 5s ago
#    Main PID: 5937 (AspNetSite)
#      CGroup: /system.slice/AspNetSite.service
#              └─5937 /srv/AspNetSite/AspNetSite
#   
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Now listening on: http://[::]:5000
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Now listening on: https://[::]:5001
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Application started. Press Ctrl+C to shut down.
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Hosting environment: Production
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Content root path: /srv/AspNetSite

现在,我们可以看到 http://[::]:5000,而不是 http://localhost:5000。现在应用程序已绑定到计算机的 IP 地址,我们应该能够从计算机内部通过 IP 卷曲它:

# try curl'ing using your machine's IP, to list IP's on RHEL use 'ip addr show'
curl http://10.0.0.4:5000
# Output should be 'Hello World!'

这是否意味着现在可以从机器外部访问该网站?
几乎,红帽配备了一个内置的防火墙,可以阻止流量。使用"firewall-cmd"实用程序,我们可以更新防火墙配置以允许通过端口5000和5001的TCP流量:

sudo firewall-cmd --zone=public --add-port 5000/tcp --permanent
sudo firewall-cmd --zone=public --add-port 5001/tcp --permanent
sudo firewall-cmd --reload

现在,该网站将从网络中的其他计算机访问。
如果您在云中运行此RHEL机器,则还必须确保云提供的任何安全性也允许通过端口5000和5001进行TCP。
一旦完成,该网站应该可以访问互联网。

通过端口 80 和 443 ASP.NET 核心提供服务#

默认情况下,Linux 计算机不允许进程使用已知端口(低于 1024 的端口)。
如果我们尝试使用端口 80 和/或 443 运行应用程序,我们将收到权限错误:

/srv/AspNetSite/AspNetSite --urls "http://*:80;https://*:443"
# Output:
#   crit: Microsoft.AspNetCore.Server.Kestrel[0]
#         Unable to start Kestrel.
#   System.Net.Sockets.SocketException (13): Permission denied
#   ...

有许多方法可以解决此限制。

使用反向代理#

我们可以设置一个反向代理来侦听端口 80 和 443,并将其流量转发到 ASP.NET Core 应用程序。微软详细记录了这一过程:

由于许多原因,这是一个很好的选择,但我们不会这样做,因为本演练的目标是只使用内置的 Kestrel 服务器。

授予CAP_NET_BIND_SERVICE能力#

使用以下命令,我们可以为AspNetSite可执行文件提供"CAP_NET_BIND_SERVICE"功能。此功能将允许进程绑定到已知端口。

sudo setcap CAP_NET_BIND_SERVICE=+eip /srv/AspNetSite/AspNetSite
/srv/AspNetSite/AspNetSite --urls "http://*:80;https://*:443"
# Output:
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: http://[::]:80
#   info: Microsoft.Hosting.Lifetime[0]
#         Now listening on: https://[::]:443
#   info: Microsoft.Hosting.Lifetime[0]
#         Application started. Press Ctrl+C to shut down.
#   info: Microsoft.Hosting.Lifetime[0]
#         Hosting environment: Production
#   info: Microsoft.Hosting.Lifetime[0]
#         Content root path: /home/yourusername/AspNetSite

每次更新可执行文件时,"CAP_NET_BIND_SERVICE"功能都将丢失。我们可以将此命令作为部署脚本的一部分,但 systemd 服务单元配置文件有一个名为"AmbientCapabilities"的选项
将此选项配置为"CAP_NET_BIND_SERVICE"时,systemd 将为我们授予服务功能。让我们更新"AspNetSite.service"文件以更新端口并添加绑定到已知端口的功能。

[Unit]
Description=ASP.NET Core web template

[Service]
Type=notify
# will set the Current Working Directory (CWD)
WorkingDirectory=/srv/AspNetSite
# systemd will run this executable to start the service
ExecStart=/srv/AspNetSite/AspNetSite
# to query logs using journalctl, set a logical name here
SyslogIdentifier=AspNetSite

# Use your username to keep things simple, for production scenario's I recommend a dedicated user/group.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app.
# To update permissions, use 'chown yourusername -R /srv/AspNetSite' to take ownership of the folder and files,
#       Use 'chmod +x /srv/AspNetSite/AspNetSite' to allow execution of the executable file.
User=yourusername

# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service
RestartSec=5

# copied from dotnet documentation at
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1#code-try-7
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

# This environment variable is necessary when dotnet isn't loaded for the specified user.
# To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell.
Environment=DOTNET_ROOT=/opt/rh/rh-dotnet31/root/usr/lib64/dotnet

# When using the out of the box ASP.NET Tempates, this environment variable will allow you to override
# which IP & ports the Kestrel Web Server will listen to
Environment=ASPNETCORE_URLS=http://*:80;https://*:443

# give the executed process the CAP_NET_BIND_SERVICE capability. This capability allows the process to bind to well known ports.
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

最后一次,复制"AspNetSite.service"文件并重新加载/重新启动 AspNetSite 服务。

sudo cp AspNetSite.service /etc/systemd/system/AspNetSite.service
sudo systemctl daemon-reload
sudo systemctl restart AspNetSite
sudo systemctl status AspNetSite
# Output should be similar to below:
#   ● AspNetSite.service - ASP.NET Core web template
#      Loaded: loaded (/etc/systemd/system/AspNetSite.service; enabled; vendor preset: disabled)
#      Active: active (running) since Wed 2020-01-29 17:17:48 UTC; 5s ago
#    Main PID: 5937 (AspNetSite)
#      CGroup: /system.slice/AspNetSite.service
#              └─5937 /srv/AspNetSite/AspNetSite
#   
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Now listening on: http://[::]:80
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Now listening on: https://[::]:443
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Application started. Press Ctrl+C to shut down.
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Hosting environment: Production
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: info: Microsoft.Hosting.Lifetime[0]
#   Jan 29 17:17:48 rhtest AspNetSite[5937]: Content root path: /srv/AspNetSite

Web 应用程序现在正在侦听端口 80 和 443,但内置防火墙仍将阻止通过这些端口传入的流量。更新内置防火墙和任何其他网络安全,以允许通过端口 80 和 443 的流量:

sudo firewall-cmd --zone=public --add-port 80/tcp --permanent
sudo firewall-cmd --zone=public --add-port 443/tcp --permanent
sudo firewall-cmd --reload

使用浏览器通过端口80访问网站现在应该返回"Hello World!

总结#

我们现在有一个面向公众的 ASP.NET 核心应用程序,由内置的Kestrel Web服务器提供服务,通过采取以下步骤:

  • 将 ASP.NET Core 部署到 /srv/AspNetSite 下的 RHEL
  • 将 systemd 配置为将应用程序作为服务运行
  • 将 systemd .NET Core 集成添加到应用程序中
  • 使用环境变量将应用程序配置为侦听所有 IP 和不同端口
  • 更新内置防火墙以允许 TCP 流量超过 5000、5001、80 和 443
  • 向服务授予"CAP_NET_BIND_SERVICE"功能,以允许应用程序绑定到众所周知的端口,如 80 和 443
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值