让我们来聊聊把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
常见问题包括:
- WorkingDirectory设置错误
- 忘记设置Environment变量
- 用户权限不正确
五、数据库连接问题
如果你的应用使用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知识
- 某些第三方库兼容性可能有问题
注意事项
- 始终在Linux上测试你的应用,不要假设在Windows上能跑在Linux上就一定能跑
- 注意文件路径大小写敏感问题
- 环境变量设置要正确
- 考虑使用Docker容器化部署简化环境配置
总结
把DotNetCore应用部署到Linux其实并不复杂,只要你注意几个关键点:环境配置、权限管理、反向代理设置、服务化部署和日志收集。遇到问题时,善用Linux自带的工具进行排错。随着.NET对Linux支持越来越好,这种部署方式会变得越来越主流。
评论