ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

.NET API 从开发到生产:Ubuntu 服务器部署完整指南

.NET API 从开发到生产:Ubuntu 服务器部署完整指南 如果你是一位 .NET 开发者辛辛苦苦在本地开发、调试好了一个 API 项目满心欢喜准备上线却在部署到 Linux 服务器这一步卡住了——环境变量怎么配Nginx 反向代理怎么写进程守护怎么做看着满屏的命令行报错是不是感觉从熟悉的 Windows 世界瞬间掉进了“运维深坑”这不是你一个人的困境。从 Visual Studio 的一键发布到 Linux 服务器的稳定运行中间隔着一道名为“生产环境部署”的鸿沟。网上教程很多但往往只讲单一环节要么只讲 .NET Core 发布要么只讲 Ubuntu 基础命令缺乏一个从开发者视角出发、贯穿始终的“交钥匙”指南。本文将聚焦一个非常具体且高频的场景将一个使用 .NET 6/7/8 开发的 API 项目我们称之为 NET10 API从本地 Visual Studio 发布开始一步步部署到 Ubuntu 服务器上并配置为可靠的生产服务。这不是简单的dotnet run而是涵盖发布配置、文件传输、服务安装、反向代理、进程守护以及 HTTPS 配置的完整流水线。读完本文你将获得一套清晰、可复用的部署清单下次部署时直接按图索骥即可。1. 这篇文章真正要解决的问题从开发到生产的“最后一公里”很多 .NET 开发者擅长业务逻辑编写却在部署环节感到陌生。我们面临的核心问题不是技术多难而是流程的断裂和知识的碎片化。痛点1环境差异。本地是 Windows IIS Express生产是 Linux Nginx/Kestrel。运行方式、配置文件、权限体系完全不同。痛点2缺乏自动化。手动 FTP 上传、手动执行命令、手动配 Nginx步骤繁琐易错无法快速回滚。痛点3服务不可靠。简单的dotnet run启动SSH 一断开服务就停止服务器重启后需要人工干预。痛点4配置管理混乱。数据库连接字符串、API 密钥等敏感信息硬编码在appsettings.json中存在安全风险。本文的目标就是系统性地解决这些痛点。我们将把一个典型的 NET10 API 项目假设它是一个提供用户管理或数据查询接口的 Web API的部署拆解成七个清晰、可操作的阶段。无论你用的是腾讯云、阿里云还是自建服务器只要系统是 Ubuntu这套方法都适用。2. 基础概念与核心原理认识部署中的关键角色在开始动手之前理解每个组件的作用至关重要这能让你在出问题时快速定位。组件角色与职责在部署中的作用.NET Runtime / SDK.NET 应用程序的运行环境或开发工具包。服务器上需要安装 Runtime 来运行发布后的应用如果需要在服务器上编译则需要 SDK。Kestrel.NET 内置的跨平台 Web 服务器。作为应用的第一道门户直接执行你的 C# 代码处理 HTTP 请求。但它通常不直接对外暴露。Nginx高性能的反向代理服务器和 Web 服务器。1. 反向代理接收公网请求转发给内网的 Kestrel。2. 静态文件服务高效处理 CSS、JS、图片等。3. SSL 终止处理 HTTPS 加密解密减轻 Kestrel 负担。SystemdLinux 的系统和服务管理器。进程守护将你的 .NET 应用配置为系统服务实现开机自启、自动重启、日志集中管理。App Settings应用的配置文件如appsettings.json,appsettings.Production.json。管理环境相关的配置如数据库连接字符串、日志级别、功能开关。生产环境配置应与开发环境分离。发布输出通过dotnet publish生成的可执行文件集合。包含你的应用代码DLL、依赖库和运行时资产。这是上传到服务器的最终“产品”。核心工作流程用户通过域名访问 - Nginx 接收 HTTPS 请求 - Nginx 将请求转发给本地运行的 Kestrel 服务 - Kestrel 执行 .NET 应用逻辑并返回结果 - Nginx 将结果返回给用户。Systemd 确保 Kestrel 进程持续稳定运行。3. 环境准备与前置条件在开始部署之前请确保你拥有以下资源并完成基本配置。3.1 本地开发环境开发工具Visual Studio 2022 或 Visual Studio Code。项目类型ASP.NET Core Web API 项目.NET 6, 7, 8 或更高版本。本文以 .NET 8 为例。项目状态在本地可以正常编译、运行和调试。3.2 目标服务器环境操作系统Ubuntu Server 20.04 LTS 或 22.04 LTS长期支持版更稳定。本文以 Ubuntu 22.04 为例。服务器访问拥有一个可以通过 SSH 连接的 Ubuntu 服务器云服务器或物理机。权限拥有sudo权限的用户账号。网络服务器已开启 80HTTP和 443HTTPS端口入站规则在云服务器控制台的安全组/防火墙中配置。域名可选但推荐一个已解析到该服务器 IP 的域名。用于配置 HTTPS。3.3 本地与服务器检查清单本地在项目根目录打开终端运行dotnet --info确认 .NET SDK 版本。服务器通过 SSH 连接后运行lsb_release -a查看 Ubuntu 版本。服务器运行sudo apt update sudo apt upgrade -y更新系统包列表和已安装的包。4. 第一阶段优化项目配置与本地发布部署的第一步始于本地。正确的发布配置能避免很多服务器上的运行时问题。4.1 配置生产环境配置文件在项目中创建appsettings.Production.json文件。这个文件中的配置将在生产环境中覆盖appsettings.json的相同设置。// appsettings.Production.json { Logging: { LogLevel: { Default: Information, Microsoft.AspNetCore: Warning, // 生产环境减少Asp.NET核心日志 Microsoft.EntityFrameworkCore: Warning // 减少EF Core详细日志 }, File: { // 可选配置文件日志 Path: /var/log/net10api/app.log, FileSizeLimitBytes: 10485760, // 10MB RetainedFileCountLimit: 5 } }, AllowedHosts: *, ConnectionStrings: { // !!! 重要不要在此处写入真实密码。我们将使用环境变量或机密管理器。 DefaultConnection: Serverlocalhost;DatabaseNet10Db;User Idsa;Password{DB_PASSWORD}; }, Kestrel: { Endpoints: { Http: { Url: http://localhost:5000 // Kestrel 监听本地5000端口 } // 如果需要直接HTTPS可在此配置但通常由Nginx处理 } } }4.2 使用 Visual Studio 发布GUI 方式在解决方案资源管理器中右键单击你的 API 项目选择“发布”。选择发布目标为“文件夹”。在配置中选择“发布”配置目标运行时选择“linux-x64”。这是最关键的一步确保生成的是 Linux 可执行文件。部署模式选择“框架依赖”或“独立”。对于服务器环境“框架依赖”更推荐因为它体积小前提是服务器已安装对应 .NET Runtime。点击“发布”按钮。发布文件将生成在你指定的文件夹中例如bin\Release\net8.0\linux-x64\publish。4.3 使用 CLI 命令发布更灵活可控打开终端导航到项目文件.csproj所在目录。# 切换到项目目录 cd YourNet10ApiProject # 清理并发布目标运行时为 linux-x64配置为 Release dotnet publish -c Release -r linux-x64 --self-contained false -o ./publish-output-c Release: 使用 Release 配置进行编译优化。-r linux-x64: 指定目标运行时为 Linux 64 位。--self-contained false: 生成框架依赖的部署需要目标机器有 .NET Runtime。-o ./publish-output: 指定输出目录。发布完成后检查publish-output文件夹应包含你的应用 DLL如YourNet10ApiProject.dll、appsettings.json文件以及一系列依赖库。5. 第二阶段服务器环境初始化与 .NET 安装现在我们将工作重心转移到 Ubuntu 服务器上。5.1 通过 SSH 连接服务器使用你喜欢的 SSH 工具如 PowerShell、Terminal、PuTTY、MobaXterm连接服务器。ssh your_usernameyour_server_ip5.2 安装 .NET Runtime由于我们采用“框架依赖”部署服务器需要安装对应的 .NET Runtime。# 1. 添加 Microsoft 包仓库和签名密钥 wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb # 2. 更新包列表并安装 ASP.NET Core Runtime (包含.NET Runtime) # 根据你的项目版本选择例如 .NET 8 sudo apt update sudo apt install -y aspnetcore-runtime-8.0 # 3. 验证安装 dotnet --list-runtimes你应该能看到Microsoft.AspNetCore.App 8.0.x和Microsoft.NETCore.App 8.0.x已安装。6. 第三阶段文件传输与目录规划将本地发布好的文件上传到服务器并规划一个清晰的目录结构。6.1 在服务器上创建应用目录# 创建一个专属于你应用的目录通常放在 /var 下 sudo mkdir -p /var/www/net10api # 将目录所有权改为你的当前用户方便后续操作无需每次都sudo sudo chown -R $USER:$USER /var/www/net10api # 设置目录权限 sudo chmod -R 755 /var/www/net10api6.2 使用 SCP 传输文件从本地到服务器在本地电脑的终端中导航到发布输出目录publish-output然后执行# 将 publish-output 目录下的所有文件上传到服务器的 /var/www/net10api 目录 scp -r ./* your_usernameyour_server_ip:/var/www/net10api/或者使用图形化工具如 WinSCP、FileZilla 进行拖拽上传。6.3 服务器端目录结构确认上传后在服务器上检查目录内容cd /var/www/net10api ls -la你应该能看到YourNet10ApiProject.dll,appsettings.json,web.config如果有以及其他.dll文件。7. 第四阶段配置 Systemd 服务实现进程守护使用 Systemd 来管理你的 .NET 应用这是保证服务稳定性的核心。7.1 创建 Systemd 服务文件sudo nano /etc/systemd/system/net10api.service将以下内容粘贴到编辑器中请根据你的实际情况修改WorkingDirectory、ExecStart和User。[Unit] DescriptionNET10 API Service Afternetwork.target [Service] Typeexec # 这是你的应用文件所在目录 WorkingDirectory/var/www/net10api # 启动命令用 dotnet 执行你的主 DLL ExecStart/usr/bin/dotnet /var/www/net10api/YourNet10ApiProject.dll Restartalways # 如果应用崩溃10秒后重启 RestartSec10 KillSignalSIGINT SyslogIdentifiernet10api # 运行服务的用户和组出于安全考虑建议创建一个专用用户这里先用当前用户 Useryour_username Groupyour_username # 环境变量设置 ASP.NET Core 环境为 Production EnvironmentASPNETCORE_ENVIRONMENTProduction # 环境变量设置日志目录等可选 EnvironmentDOTNET_PRINT_TELEMETRY_MESSAGEfalse [Install] WantedBymulti-user.target关键参数解释ExecStart: 必须指向dotnet命令和你主项目的 DLL 文件。User/Group: 强烈建议为服务创建一个专用用户如www-data或net10api而非 root。这里为简化先用你的用户。EnvironmentASPNETCORE_ENVIRONMENTProduction: 这至关重要它告诉应用使用appsettings.Production.json配置。按CtrlX然后按Y再按Enter保存并退出 nano。7.2 启用并启动服务# 重新加载 systemd 配置使其识别新的服务文件 sudo systemctl daemon-reload # 设置服务开机自启 sudo systemctl enable net10api.service # 立即启动服务 sudo systemctl start net10api.service # 检查服务状态确认是否运行成功 sudo systemctl status net10api.service如果状态显示active (running)并且下面没有红色的错误日志说明服务已成功启动。7.3 查看应用日志Systemd 统一管理服务日志使用journalctl命令查看# 查看服务的全部日志 sudo journalctl -u net10api.service # 实时跟踪日志输出类似 tail -f sudo journalctl -u net10api.service -f # 查看最近50条日志 sudo journalctl -u net10api.service -n 50此时你的 API 已经在http://localhost:5000运行了但外部还无法访问。8. 第五阶段配置 Nginx 作为反向代理我们需要 Nginx 作为门户将外部请求转发给本地的 Kestrel 服务。8.1 安装 Nginxsudo apt install -y nginx8.2 为你的应用创建 Nginx 站点配置删除默认配置为你的 API 创建专属配置sudo rm /etc/nginx/sites-enabled/default sudo nano /etc/nginx/sites-available/net10api粘贴以下配置server { listen 80; # 将 your_domain.com 替换为你的域名如果没有域名可以用服务器IP但更推荐用域名 server_name your_domain.com www.your_domain.com; location / { # 将请求代理到 Kestrel 服务监听的地址 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_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; # 如果API响应较慢可适当增加超时时间 proxy_read_timeout 300s; proxy_connect_timeout 75s; } # 可选静态文件处理如果你的API也提供静态文件 # location /wwwroot/ { # root /var/www/net10api; # expires 1y; # add_header Cache-Control public, immutable; # } }8.3 启用站点并测试 Nginx 配置# 创建符号链接启用站点 sudo ln -s /etc/nginx/sites-available/net10api /etc/nginx/sites-enabled/ # 测试 Nginx 配置语法是否正确 sudo nginx -t # 如果显示 syntax is ok 和 test is successful则配置正确 # 重新加载 Nginx 使配置生效 sudo systemctl reload nginx8.4 验证访问现在你应该可以通过服务器的 IP 地址或你配置的域名在浏览器中访问http://your_server_ip或http://your_domain.com来访问你的 API 了。 你可以使用curl测试curl http://localhost或者访问你的 API 的某个端点例如http://your_domain.com/api/values假设你有这个端点。9. 第六阶段使用 Let‘s Encrypt 配置 HTTPSSSL/TLS为生产环境启用 HTTPS 是必须的Let‘s Encrypt 提供了免费的 SSL 证书。9.1 安装 CertbotCertbot 是获取和续订 Let‘s Encrypt 证书的官方工具。sudo apt install -y certbot python3-certbot-nginx9.2 获取并自动配置 SSL 证书运行以下命令Certbot 会自动读取你的 Nginx 配置并引导你完成证书申请和配置。sudo certbot --nginx -d your_domain.com -d www.your_domain.com按照提示操作输入你的邮箱用于接收安全通知。同意服务条款。选择是否接收邮件可选。Certbot 会自动验证域名所有权需要域名已正确解析到服务器然后修改你的 Nginx 配置添加 HTTPS 支持。9.3 验证自动续订Let‘s Encrypt 证书有效期为 90 天Certbot 会自动设置定时任务续订。测试自动续订是否正常工作sudo certbot renew --dry-run如果没有错误说明自动续订配置成功。现在你的 API 已经可以通过https://your_domain.com安全访问了。Nginx 会自动将 HTTP 请求重定向到 HTTPS。10. 第七阶段生产环境加固与最佳实践部署上线只是开始确保其稳定、安全、可维护才是关键。10.1 为服务创建专用系统用户之前我们用了自己的用户这有安全风险。创建一个仅用于运行此服务的用户。sudo adduser --system --no-create-home --group net10apiuser sudo chown -R net10apiuser:net10apiuser /var/www/net10api然后修改 Systemd 服务文件/etc/systemd/system/net10api.service将User和Group改为net10apiuser并重新加载和重启服务。sudo systemctl daemon-reload sudo systemctl restart net10api.service10.2 安全管理敏感配置如数据库密码绝对不要将密码直接写在appsettings.Production.json并提交到代码库。方法一使用环境变量推荐在 Systemd 服务文件中设置[Service] ... EnvironmentDB_PASSWORDYourSuperStrongPassword123!然后在appsettings.Production.json中使用占位符并在代码中通过Configuration.GetValuestring(ConnectionStrings:DefaultConnection)读取并在运行时用Environment.GetEnvironmentVariable(DB_PASSWORD)替换占位符。或者更优雅地直接在配置中使用环境变量引用部分配置提供程序支持。方法二使用 Linux 机密存储或Azure Key Vault/AWS Secrets Manager对于云环境。10.3 配置防火墙UFW确保只开放必要的端口。# 允许 SSH (22), HTTP (80), HTTPS (443) sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp # 启用防火墙 sudo ufw enable # 查看状态 sudo ufw status verbose10.4 设置日志轮转防止应用日志无限增长。为 Systemd 服务配置日志限制或使用logrotate工具管理文件日志如果你配置了文件日志。 编辑/etc/systemd/system/net10api.service在[Service]部分添加StandardOutputjournal StandardErrorjournal # 限制日志大小 LogRateLimitIntervalSec30s LogRateLimitBurst1000然后运行sudo systemctl daemon-reload和sudo systemctl restart net10api.service。10.5 健康检查端点在你的 API 中添加一个简单的健康检查端点如/health返回 200 OK。这便于监控和负载均衡器检查。// 在你的 Controller 中 [ApiController] [Route([controller])] public class HealthController : ControllerBase { [HttpGet] public IActionResult Get() Ok(Healthy); }然后你可以在 Nginx 或监控系统中使用这个端点。11. 常见问题与排查思路部署过程很少一帆风顺这里列出典型问题及解决方法。问题现象可能原因排查方式解决方案sudo systemctl status net10api显示failed1. 应用本身启动错误如数据库连不上。2.ExecStart路径或命令错误。3. 依赖缺失。1.sudo journalctl -u net10api.service -n 50 --no-pager查看详细错误日志。2. 检查服务文件语法。1. 根据日志修复代码或配置错误。2. 确保dotnet命令和 DLL 路径正确。3. 确保服务器安装了正确的 .NET Runtime。Nginx 返回502 Bad Gateway1. Kestrel 服务没运行。2. Nginxproxy_pass地址/端口错误。3. 应用进程崩溃。1.sudo systemctl status net10api检查服务状态。2.curl http://localhost:5000测试 Kestrel 是否可达。3. 查看应用日志。1. 启动或重启 Kestrel 服务。2. 修正 Nginx 配置中的proxy_passURL。3. 修复导致应用崩溃的 bug。访问 API 超时或无响应1. 防火墙阻止了端口。2. 应用处理请求太慢或死锁。3. 服务器资源CPU/内存耗尽。1.sudo ufw status检查防火墙。2.top或htop查看资源使用情况。3. 查看应用日志是否有异常或慢查询。1. 开放对应端口。2. 优化应用代码或数据库查询。3. 增加服务器资源或排查内存泄漏。HTTPS 无法访问或证书错误1. Certbot 配置未生效。2. 域名解析未生效或错误。3. 证书过期。1.sudo nginx -t检查配置。2.dig your_domain.com检查 DNS。3.sudo certbot certificates查看证书状态。1. 重新运行sudo certbot --nginx。2. 等待 DNS 生效或检查解析设置。3. 手动续订sudo certbot renew。上传文件后权限错误文件所有者是 root而服务用户无权访问。ls -la /var/www/net10api查看文件权限和所有者。sudo chown -R net10apiuser:net10apiuser /var/www/net10api更改所有者。12. 总结与后续学习方向至此你已经完成了一个 .NET API 项目从本地开发到 Ubuntu 生产服务器部署的完整闭环。我们系统性地解决了环境配置、服务守护、网络代理、安全加固等核心问题。这套流程发布 - 传输 - 安装运行时 - 配置 Systemd - 配置 Nginx - 配置 HTTPS是部署任何 .NET Core/ASP.NET Core 应用到 Linux 的通用范式。核心收获理解架构明确了 Kestrel、Nginx、Systemd 在部署中的分工与协作。掌握流程获得了一份可重复使用的详细部署清单。学会排错通过查看服务状态和日志具备了初步的问题定位能力。为了将部署提升到更高水平你可以继续探索以下方向容器化部署学习使用 Docker 和 Docker Compose。将应用及其环境打包成镜像实现更一致、更高效的部署和水平扩展。这是现代云原生部署的主流方式。CI/CD 流水线集成 GitHub Actions、GitLab CI 或 Azure DevOps。实现代码推送后自动测试、构建、部署彻底告别手动操作。配置中心在微服务架构下研究 Apollo、Consul 等配置中心实现配置的动态管理和实时更新。监控与告警集成 Prometheus 和 Grafana 来监控应用的性能指标CPU、内存、请求延迟、错误率并设置告警规则。负载均衡与高可用当单台服务器无法承受流量时学习如何使用 Nginx 或云服务商如 AWS ALB、Azure App Gateway的负载均衡器将流量分发到多台应用服务器。部署不是一次性的任务而是一项持续优化的工程。建议你将本文的步骤脚本化并纳入你的项目文档。下次部署时你将会更加从容自信。
返回列表