让我们来聊聊把DotNetCore应用部署到Linux系统时可能会遇到的那些坑,以及如何优雅地跨过这些坑。虽然微软和Linux现在关系不错,但毕竟来自不同世界,难免有些水土不服的情况。

一、环境配置那些事儿

首先得把环境准备好,就像做饭前要先备好食材一样。最常见的问题就是运行时版本不匹配,比如你在Windows上用.NET Core 3.1开发,结果服务器上装的是2.2。

安装运行时其实很简单,以Ubuntu为例:

# 添加微软包仓库
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

# 安装运行时(这里以.NET 5为例)
sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo apt-get update
sudo apt-get install -y dotnet-runtime-5.0

但是要注意,不同Linux发行版的包管理方式不一样。比如在CentOS上就得用yum而不是apt-get。我曾经遇到过有人在CentOS上照着Ubuntu的教程操作,结果浪费了半天时间。

二、文件权限的坑

Linux的权限系统可比Windows严格多了。最常见的就是应用没权限写日志文件或者访问某些目录。

假设你的应用需要写日志到/var/log/myapp目录,你得这样设置:

# 创建日志目录
sudo mkdir -p /var/log/myapp

# 设置正确的用户和权限
sudo chown -R www-data:www-data /var/log/myapp
sudo chmod -R 755 /var/log/myapp

这里有个小技巧,你可以用下面的命令找出你的应用是以什么用户运行的:

ps aux | grep dotnet

有时候Nginx反向代理也会带来权限问题。比如Nginx默认用户是www-data,而你的应用可能以另一个用户运行,这时候要确保Nginx有权限访问你的应用。

三、反向代理配置

说到Nginx,这是最常用的反向代理方案。配置不当会导致502 Bad Gateway错误,让人头大。

一个典型的Nginx配置应该是这样的:

server {
    listen 80;
    server_name 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;
    }
}

这里最容易忽略的是proxy_set_header这些配置。特别是X-Forwarded-Proto,如果你的应用需要知道原始请求是http还是https,这个就很重要。

Kestrel作为DotNetCore的内置服务器,默认只监听localhost。如果你想让它监听所有网络接口,得这样修改Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>()
                .UseUrls("http://*:5000");  // 注意这里的*号
        });

四、系统服务化部署

让应用在后台运行并开机自启是个好主意。Systemd是目前最常用的方案。

创建一个/etc/systemd/system/myapp.service文件:

[Unit]
Description=My .NET Core App

[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/dotnet /var/www/myapp/MyApp.dll
Restart=always
# 如果以非root用户运行
User=www-data
Group=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

然后执行:

sudo systemctl enable myapp
sudo systemctl start myapp

常见问题包括:

  1. WorkingDirectory设置错误
  2. 忘记设置Environment变量
  3. 用户权限不正确

五、数据库连接问题

如果你的应用使用SQL Server,虽然微软官方支持Linux版的SQL Server,但还是有些坑。

连接字符串可能需要这样写:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=myDb;User Id=sa;Password=你的密码;TrustServerCertificate=true"
  }
}

注意最后的TrustServerCertificate=true,这在Linux连接SQL Server时经常需要。

对于MySQL,别忘了安装对应的驱动:

sudo apt-get install mysql-client
sudo apt-get install libmysqlclient-dev

然后在项目中添加MySql.Data.EntityFrameworkCore包。

六、日志和排错

当应用崩溃时,如何快速定位问题?Linux自带的日志系统很有用。

查看应用日志:

journalctl -u myapp -f  # 实时查看
journalctl -u myapp --since "2023-01-01" --until "2023-01-02"  # 按时间范围查看

你也可以配置Serilog等日志框架,把日志写入文件或Elasticsearch。比如:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console()
    .WriteTo.File("/var/log/myapp/log-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

七、资源限制

Linux默认的资源限制可能不够用,特别是文件描述符数量。对于高并发应用,你可能需要调整:

# 查看当前限制
ulimit -n

# 临时设置
ulimit -n 65536

# 永久设置,编辑/etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

八、部署自动化

手动部署太容易出错了,建议使用脚本或CI/CD工具。一个简单的部署脚本示例:

#!/bin/bash
# 部署脚本示例

# 停止服务
sudo systemctl stop myapp

# 备份旧版本
tar -czvf /backup/myapp_$(date +%Y%m%d).tar.gz /var/www/myapp

# 清理旧文件
rm -rf /var/www/myapp/*

# 复制新文件
cp -r ./publish/* /var/www/myapp/

# 设置权限
chown -R www-data:www-data /var/www/myapp
chmod -R 755 /var/www/myapp

# 启动服务
sudo systemctl start myapp

应用场景分析

这种部署方式特别适合:

  • 中小型Web应用
  • 微服务架构中的单个服务
  • 需要利用Linux服务器性价比的场景

技术优缺点

优点:

  • 跨平台支持良好
  • 性能表现优秀
  • 开源免费

缺点:

  • 部分Windows特有功能不可用
  • 排错需要Linux知识
  • 某些第三方库兼容性可能有问题

注意事项

  1. 始终在Linux上测试你的应用,不要假设在Windows上能跑在Linux上就一定能跑
  2. 注意文件路径大小写敏感问题
  3. 环境变量设置要正确
  4. 考虑使用Docker容器化部署简化环境配置

总结

把DotNetCore应用部署到Linux其实并不复杂,只要你注意几个关键点:环境配置、权限管理、反向代理设置、服务化部署和日志收集。遇到问题时,善用Linux自带的工具进行排错。随着.NET对Linux支持越来越好,这种部署方式会变得越来越主流。