.NET5都来了,你还不知道怎么部署到linux?最全部署方案,总有一款适合你
隨著2020進入4季度,.NET5正式版也已經與大家見面了。不過,盡管 .NET Core發布已經有四五年的時間,但到目前為止,依舊有很多.NET開發者在堅守者.NET4,原因不盡相同,但最大的問題可能還是不熟悉Linux,更別說在Linux服務器中部署.NET服務了。
而 .NET Core在飛速發展的這四五年里,微服務、云原生等概念也在飛速發展。.NET Core在微服務和云原生的場景下,也已日趨穩定,生態也在逐步完善,相信.NET5正式發布后,對于我們苦逼多年了的.NET開發者絕對是個機遇。所以,你還有什么理由繼續堅守.NET4呢?筆者在開始使用 .NET Core時,在如何部署到Linux服務器上也是踩了挺多坑,順便也總結了一些經驗,在此分享給大家,如有更好方案,還望不吝賜教。
準備工作
操作系統。
操作系統可選擇你比較熟悉的Linux發行版,如果你是第一次接觸Linux,那我推薦使用CentOs,因為本文的內容都是在CentOs中進行演示的。
至于系統的安裝,你可以選擇云服務器,或者使用虛擬機安裝。虛擬機安裝CentOs的方式比較簡單,在此就不贅述了。
連接工具
筆者推薦使用XSHELL作為連接工具,下載地址:https://www.netsarang.com/zh/xshell-download/
安裝完成后,打開軟件,點擊左上角的新建回話按鈕,打開新建回話框,如下圖所示:
在【主機】中填寫服務器的ip地址,然后點擊【連接】按鈕,會依次提示輸入用戶名和密碼。連接成功的界面如下所示:
文件上傳工具
要想把服務部署到Linux服務器,那就必須把文件傳輸到服務器中(這是句廢話)。根據不同的使用場景,筆者推薦兩種方案,分別是XFTP工具上傳和git倉庫中轉。
使用XFTP上傳的方式需要在開發的機器上安裝此工具,下載地址:https://www.netsarang.com/zh/xftp-download/
安裝完成后,可以通過XSHELL一鍵打開XFTP,XFTP打開后,在軟件的右側可以切換要上傳文件的目標路徑,然后將文件拖到右側釋放后,就會自動上傳了,如下圖所示:
使用git倉庫進行中轉的方式是筆者比較推薦的方式,因為在頻繁的迭代更新中,如果通過現在本地編譯發布后,再將文件拷貝到服務器,這個操作流程稍顯繁瑣。而通過git倉庫周轉的方式則相對比較簡單,開發者僅需要將開發好的代碼推到git倉庫,然后在服務器中執行build,publish等操作,少了繁瑣的拷貝文件的過程,同時由于build和publish都是在服務器中執行,那么我們就可以通過編寫部署腳本的方式,可以最終實現一鍵快速部署。
使用git的方案需要在服務器安裝git客戶端,并配置ssh公鑰(配置公鑰的目的是拉取私有的倉庫,公共參考無需配置公鑰)。下面來看具體的操作步驟:
首先,執行如下命令,安裝git客戶端:
yum -y install gitgit安裝后,通過如下命令生成sshkey:
# 這里的xx@xxx.com只是生成的sshkey的名稱,并不約束貨要求具體命名為某個郵箱。ssh-keygen -t rsa -C "xx@xxx.com"按照提示,按三次回車,即可生成sshkey,如下圖所示:
,通過如下命令可查看公鑰:
cat ~/.ssh/id_rsa.pub復制生成后的sshkey,配置到代碼倉庫的公鑰中。下面簡單演示下gitee代碼托管平臺下如何配置公鑰(其他平臺大同小異)。
進入私有倉庫的【管理】頁面,找到【公鑰管理】,點擊【添加公鑰】,將剛剛生成的公鑰復制過去,如下圖所示:
添加后,在終端中輸入如下命令:
ssh -T git@gitee.com次使用需要確認并添加主機到本機SSH可信列表,如下圖所示:
輸入yes后,出現類似于Hi xxx的字樣,則表示git公鑰配置成功了。
.NET Core SDK和運行時
.NET運行時是.NET程序運行的先決條件,而SDK并不是必須的,但如果通過git方式進行文件中轉的話,就涉及到在服務器端進行編譯,所以SDK也需要安裝。(注:docker部署方式無需在服務器安裝SDK和運行時,下文回提到)
下面一起看看在CentOs中如何安裝SDK和運行時(其他環境可參考官方文檔:https://docs.microsoft.com/zh-cn/dotnet/core/install/linux)。
運行如下命令,將 Microsoft 包簽名密鑰添加到受信任密鑰列表,并添加 Microsoft 包存儲庫。
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm通過如下命令安裝SDK:
sudo yum install -y dotnet-sdk-3.1.NET Core SDK 使你可以通過 .NET Core 開發應用。如果安裝 .NET Core SDK,則無需安裝相應的運行時。
通過如下命令安裝運行時:
sudo yum install -y aspnetcore-runtime-3.1注:上述命令中的最后的3.1表示的是版本號,如果安裝其他版本,修改對應的版本號即可。參考資料:https://dotnet.microsoft.com/download/dotnet-core
發布程序到服務器
在準備工作中已經介紹了兩種將文件發布到服務器的方式,下面具體演示下步驟。
通過XFTP發布到服務器
首先,準備好要發布的程序,
下圖是我創建的一個.NET Core3.1的示例代碼:
打開vs的程序包管理器控制臺,執行如下命令:
dotnet publish -o ./publish執行結果如下圖所示:
在上圖可以看到,發布之后的文件的路徑為:D:\code\test\BuildTest\publish\
打開XFTP,將publish文件夾拖到右側窗口,即可完成上傳。
通過git中轉。
首先,將代碼推送到git倉庫中,復制SSH地址。如下圖所示:
然后再服務器中,執行克隆命令:
mkdir codecd codegit clone git@gitee.com:billsking/build-test.git執行結果如下圖所示:
此時項目代碼已經下載到服務器中,切換工作到解決方案所在的目錄
cd build-test然后我們需要執行dotnet publish命令對程序進行編譯發布。
dotnet publish -o /root/web/publish執行完畢后,編譯后的文件將被保存在/root/web/publish目錄中。將工作目錄切換到/root/web/publish,執行如下命令:
dotnet BuildTest.dll執行結果如下圖:
到這里為止,咱們的程序已經在linux服務器運行起來了。但直接通過dotnet命令僅適合臨時測試使用,并不能成為生產場景的解決方案。下面進來跟我一起了解下可用于生產環境的部署方式吧。
Supervisor+Nginx組合
Supervisor是用Python開發的一套通用的進程管理程序,能將一個普通的命令行進程變為后臺daemon,并監控進程狀態,異常退出時能自動重啟。下面是Supervisor安裝方法。
執行如下命令:
執行以上代碼如果提示:沒有可用軟件包 supervisor。則需要先安裝EPEL源后,再執行上面的命令。安裝EPEL源的命令如下:
yum install -y epel-release設置開機啟動:
systemctl enable supervisord啟動supervisord
systemctl start supervisord查看狀態
systemctl status supervisord通過vi命令或者XFTP修改配置文件開啟web界面訪問,如下圖所示,分別取消inet_http_server等四個配置的注釋:
執行如下命令,重新加載配置文件:
supervisorctl reload然后在瀏覽器打開http://你的ip:9001,輸入用戶名密碼后,如圖所示:
看到這個界面,就表示supervisor安裝完成了。
切換到/etc/supervisord.d目錄,在此目錄創建ini文件,內容如下:
[program:buildtest] ;表示程序名稱,用于在supervisor中顯示,無特殊意義。command=/bin/bash -c "dotnet BuildTest.dll"; 輸入執行命令,這里表示執行的是dotnet BuildTest.dlldirectory=/root/web/publish ; 應用程序根目錄autostart=true ; 是否自動啟動,當 supervisor 加載該配置文件的時候立即啟動它autorestart=true ; 是否自動重啟, 程序異常退出后自動重啟logfile_maxbytes=50MB ; 該配置文件輸出單個日志文件的大小,默認50Mlogfile_backups=10 ; 日志備份個數loglevel=info ; 記錄日志級別stdout_logfile=/root/data/logs/buildtest/buildtest.out.log ; 指定標準輸出日志文件environment=ASPNETCORE_ENVIRONMENT=Production;環境變量。user=root ;啟動服務的用戶redirect_stderr=true;把 stderr 重定向到 stdout,默認 false++注:stdout_logfile指向的文件夾一定要先創建,否則無法啟動。++
然后執行如下命令:
supervisorctl reload命令執行成功后, 刷新瀏覽器,可以看到如下界面:
當界面顯示running時,則表示我們我們剛剛配置的應用程序運行起來了。
但現在還存在一個問題,我們的應用程序默認是綁定的5000端口,如果要指定80端口或者配置域名該怎么處理呢?下面就該nginx登場了。
Nginx是一款輕量級的Web 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,在BSD-like 協議下發行。其特點是占有內存少,并發能力強,事實上nginx的并發能力在同類型的網頁服務器中表現較好,中國大陸使用nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等。(來源自百度百科)
安裝方式參考:http://nginx.org/en/linux_packages.html#RHEL-CentOS
安裝先決條件:
yum install -y yum-utils設置yum存儲庫,先創建一下內容的文件:/etc/yum.repos.d/nginx.repo
[nginx-stable]name=nginx stable repobaseurl=http://nginx.org/packages/centos/$releasever/$basearch/gpgcheck=1enabled=1gpgkey=https://nginx.org/keys/nginx_signing.keymodule_hotfixes=true[nginx-mainline]name=nginx mainline repobaseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/gpgcheck=1enabled=0gpgkey=https://nginx.org/keys/nginx_signing.keymodule_hotfixes=true默認情況下,使用穩定 nginx 包的存儲庫。如果要使用主線 nginx 包,請運行以下命令:
yum-config-manager --enable nginx-mainline運行如下命令安裝nginx:
yum install -y nginx設置開機啟動:
systemctl enable nginx啟動nginx:
systemctl start nginx此時,就可以在瀏覽器通過ip訪問了:http://你的ip,界面如下:
nginx安裝完成后,切換到/etc/nginx/conf.d目錄,修改default.conf文件內容,如下所示:
server {listen 80;server_name localhost;location / {proxy_pass http://0.0.0.0:5000;}error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}}保存后,執行如下命令,重新加載配置:
nginx -s reload然后再次訪問http://你的ip,幸運的話,你應該可以看到如下的界面,表示你的.NET Core程序已經完美運行在linux系統了。
如果你不幸的看到了如下界面:
不要著急,繼續往下看。
出現這個問題的原因是因為SeLinux的限制,執行如下命令之后,再刷新頁面:
setenforce 0如果還是看到的錯誤頁面,就需要去查看nginx的日志了,默認的日志路徑為:/var/log/nginx
通過setenforce 0命令,只是臨時實效,重啟后回失效的。一勞永逸的做法是,修改/etc/selinux/config 文件, 將SELINUX=enforcing改為SELINUX=disabled,然后重啟機器。
后面如果你需要更新你的應用程序,只需要將代碼提交到git倉庫,然后在服務器中執行git pull和dotnet publish就行了。
如果你對shell比較熟悉的話,還可以通過編寫shell命令一鍵執行應用程序的更新,下面是我寫的示例:
# !/bin/bashcd /root/code/build-testgit pulldotnet publish -o /root/web/publishsupervisorctl restart buildtest將上述的代碼保存問sh文件,上傳到服務器,并設置權限。如下圖所示:
代碼提交到git倉庫后,執行如下命令:
./build.sh執行結果如下圖所示:
總結一下,這種方式需要在服務端安裝兩個軟件,supervisor和nginx,supervisor一個作為守護線程,用于維護應用程序的生命周期的。nginx則是作為反向代理使用。維護起來相對麻煩,那么有沒有一個像IIS一樣,既可以維護應用程序的生命周期,又可以對外暴露服務呢?答案是肯定的,繼續往下看。
Jexus
Jexus是一款Linux平臺上的高性能WEB服務器和負載均衡網關服務器,以支持ASP.NET、ASP.NET CORE、PHP為特色,同時具備反向代理、入侵檢測等重要功能。可以這樣說,Jexus是.NET、.NET CORE跨平臺的最優秀的宿主服務器,如果我們認為它是Linux平臺的IIS,這并不為過,因為,Jexus不但非常快,而且擁有IIS和其它Web服務器所不具備的高度的安全性。同時,Jexus Web Server 是完全由中國人自主開發的的國產軟件,真正做到了“安全、可靠、可控”, 具備我國黨政機關和重要企事業單位信息化建設所需要的關鍵品質。
以上內容摘自jexus官網:https://www.jexus.org/
廢話不多說,直接進入正題,首先是安裝。
jexus的安裝非常簡單,執行如下命令:
curl https://jexus.org/release/x64/install.sh|sudo sh注:如果在這之前你已經安裝了nginx,需要先將nginx綁定的80端口釋放,或者卸載nginx。
安裝完成后,切換到/usr/jexus目錄,修改/usr/jexus/siteconf目錄下的default,內容如下所示:
port=80 #端口hosts=* #域名AppHost={cmd=dotnet BuildTest.dll; root=/root/web/publish; port=0}然后執行如下命令:
/usr/jexus/jws restart當你看到執行結果為OK時,即可認為應用程序已經啟動了。最后,執行如下命令,看下執行的結果:
ps -aux關于jexus更詳細的使用說明,請參考官方文檔。
Docker+Nginx或Jexus
上面講到的, 不管是通過supervisor+nginx還是jexus,都需要在服務器安裝 .NET Core的SDK或者運行時,假如咱們有好多個應用程序,有的用 .NET Core2.1,有的用 .NET Core3.1,有的用.NET5,那么上面的做法就需要咱們分別安裝對應的SDK或者運行時,對于維護還是比較麻煩的。Docker的出現,可以完美解決上述問題。
關于Docker的介紹,有興趣的可自行百度。下面來跟我一起來看下如何安裝并使用Docker。
執行如下命令:
curl -fsSL get.docker.com -o get-docker.shsudo sh get-docker.sh --mirror Aliyun執行這個命令后,腳本就會自動的將一切準備工作做好,并且把Docker的穩定版本安裝在系統中。
執行如下命令設置docker開機啟動:
systemctl enable docker執行如下命令啟動docker:
systemctl start docker安裝docker之后,我們需要在代碼里增加dockerfile文件。什么?不會docker?不要緊,萬能的Visual Studio可以幫你自動生成。在解決方案中,右擊項目名稱,依次選擇【添加】,【Docker支持】,如下圖所示:
生成的dockerfile文件如下所示:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS baseWORKDIR /appEXPOSE 80FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS buildWORKDIR /srcCOPY ["BuildTest/BuildTest.csproj", "BuildTest/"]RUN dotnet restore "BuildTest/BuildTest.csproj"COPY . .WORKDIR "/src/BuildTest"RUN dotnet build "BuildTest.csproj" -c Release -o /app/buildFROM build AS publishRUN dotnet publish "BuildTest.csproj" -c Release -o /app/publishFROM base AS finalWORKDIR /appCOPY --from=publish /app/publish .ENTRYPOINT ["dotnet", "BuildTest.dll"]將代碼推送到git倉庫,然后再linux服務器中拉取最新代碼。
切換到/root/code/build-test目錄,執行如下命令,拉取最新代碼:
git pull然后執行如下命令,將代碼打包為鏡像:
docker build -f ./BuildTest/Dockerfile -t buildtest .由于首次打包鏡像的時候涉及到拉取.NET Core的官方鏡像,拉取速度可能較慢,請耐心等待。打包完成后,執行如下命令,可查看當前服務器已存在的鏡像:
docker images鏡像打包完成后,我們就可以通過docker run運行下,命令如下:
docker run -p 82:80 -dit --restart=always --name buildtest buildtest執行結果如下:
通過瀏覽器訪問:http://ip:82。如無意外,你將看到你的應用程序已經成功運行了。
相同的道理,我們也是可以通過編寫shell腳本的方式,實現一鍵更新應用程序的。在/root目錄中,創建dockerbuild.sh文件,文件內容如下:
# !/bin/bashcd /root/code/build-testgit pullimtag=$(uuidgen |sed 's/-//g')docker build -f ./BuildTest/Dockerfile -t buildtest:${imtag} .docker stop buildtestdocker rm buildtestdocker run -dit --restart=always --name buildtest -p 82:80 buildtest:${imtag}給dockerbuild.sh文件設置執行權限,命令如下:
chmod 777 dockerbuild.sh當有新代碼推送到git倉庫時,進入服務器,執行dockerbuild.sh即可快速更新應用程序。
到這里,.NET Core部署到linux服務器的方案已“基本”介紹完畢了。
為什么說是“基本”呢?不知道大家有沒有發現,雖然目前的方案可以實現一鍵部署更新,但。。。。,我們還是需要登陸到linux服務器去執行這個命令,顯然,這不是最好的方法。有沒有更好的方案呢?如果當我們提交給git倉庫后,自動出發部署命令是不是就更方便了呢?
答案是肯定的,我們可以借助jenkins來實現。限于篇幅,本篇文章就不講解了,如有興趣,你也可以先自行研究,或者敬請期待下次的講解。
最后說明下,以上的方案還是存在很多的問題,對于小型團隊已經夠用,大型項目的終極解決方案應該是基于k8s實現的devops。其實k8s實現devops的原理和我上述介紹的方案基本一致。借助與gitlab的runner或者jenkins,監聽git倉庫的狀態,當發現指定的分支發生變化后,打包鏡像,然后通過替換k8s的deployment的鏡像來實現自動更新。同時,k8s實現了彈性伸縮、滾動更新等功能。
總結
以上是生活随笔為你收集整理的.NET5都来了,你还不知道怎么部署到linux?最全部署方案,总有一款适合你的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 我画着图,FluentAPI 她自己就生
 - 下一篇: 客户的一个紧急bug,我用了两种方式进行