當前位置:
首頁 > 知識 > Linux 小白的 .NET Core 部署之路

Linux 小白的 .NET Core 部署之路

一、前言

最近一段時間自己主要的學習計劃還是按照畢業後設定的計劃,自己一步步的搭建一個前後端分離的 ASP.NET Core 項目,目前也還在繼續學習 Vue 中,雖然中間斷了很長時間,好歹還是堅持下來了,嗯,看了看時間,原本決定的半年完成肯定是完不成了。這兩周重新拾起來學習 Vue,文章也在慢慢的更新中,這一篇文章主要是想提前試試水將 ASP.NET Core 部署到 Linux Server 上,原本的打算是把畢業設計就部署到 Linux 上,最終也未能成行,究其原因,還是自己太懶太拖了吧,哈哈哈,拖到最後,畢業設計差點都沒寫完。

因為目前自己的前後端分離的項目還沒開始寫,所以這裡採用的還是自己原來寫的 .NET Core 項目,這篇文章的主要目的是操作下如何將我們 ASP.NET Core 項目部署到我們的 Linux 伺服器上,如果對你有任何的幫助的話,不勝榮幸。當然,如果有不對的地方,歡迎大家提出。

二、準備工作

1、一台 Linux 操作系統的電腦,嗯,這裡採用的是騰訊雲學生套餐,伺服器版本為 CnetOS 7.5 。

2、終端軟體,這裡我使用的是putty,用來幫助我們遠程連接到我們的伺服器。

下載鏈接:https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

3、文件上傳軟體,這裡我使用的是 WinSC,上傳文件的,同時,如何你和我一樣對於使用命令行編輯文件不習慣的話,用這個還可以編輯下伺服器上需要更改的配置文件,逃~~~。

下載鏈接:https://winscp.net/eng/download.php

三、Step by Step

1、安裝 .NET Core Runtime

因為這裡並不需要在 Linux 伺服器上進行開發工作,所以只需要安裝好 dotnet core runtime 就可以了,如果你需要在 Linux 上進行開發,就需要安裝 .NET Core SDK了,當然,如果安裝過了 SDK,也就不需要安裝 Runtime 了。

我們打開微軟的官方網站,使用 putty 連接到我們的伺服器。 官網地址:https://www.microsoft.com/net/download/linux-package-manager/centos/runtime-current

a)在伺服器上註冊 Microsoft 秘鑰,這裡我使用的是 Centos ,這裡你需要按照你自己的伺服器版本進行選擇下載。

sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm

b)更新可供安裝的版本,當控制台出現 Complete 時,則代表我們更新完成。

sudo yum update

c)安裝 .NET Core,同樣的,當控制台出現 Complete 時,則代表我們安裝完成。

sudo yum install aspnetcore-runtime-2.1 ##這裡如果你要在 Linux 上開發,這裡就安裝 dotnet-sdk-2.1

這時,如何判斷我們的 .NET Core 安裝成功了呢?我們可以在控制台上輸入下面的命令,如果已經安裝成功的話,就可以把我們安裝的 dotnet 版本信息顯示出來,反之,你就需要重新執行了。

dotnet --info


Linux 小白的 .NET Core 部署之路

打開今日頭條,查看更多精彩圖片


這裡我們可以看到,我們只是安裝了 .NET Core Runtime,並沒有安裝 SDK,我們的 Host 版本是2.1.5。

2、安裝 MySQL

a)添加 MySQL 源

首先打開 MySQL 的官網,需要根據自己的伺服器信息選擇合適的源信息,我的伺服器操作系統是 CentOS,這裡我選擇的是 yum 源(yum 源地址:https://dev.mysql.com/downloads/repo/yum/)。

當我們點擊 Download 按鈕後發現,要登錄。。。如果你和我一樣不想又註冊一個賬戶,我們可以獲取到下面的下載地址,然後通過 rpm -Ivh 的方式安裝。我安裝的是最新的 MySQL 8.0 版本,當然,你也可以通過修改版本號下載不同的 MySQL 版本。

wget https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
rpm -ivh mysql80-community-release-el7-1.noarch.rpm

b)校驗 md5 與官網上的是一致

md5sum mysql80-community-release-el7-1.noarch.rpm

c)安裝 MySQL Server

sudo yum install mysql-server


Linux 小白的 .NET Core 部署之路


d)啟動 MySQL Server

當我們完成安裝之後,就可以啟動 MySQL Server 服務了。我們可以使用下面的命令啟動 MySQL 守護程序。

sudo systemctl start mysqld

可是上面的命令執行之後,不會有任何的反應,我們可能會疑問我們執行成功了嗎?所以為了確保我們執行成功,我們可以使用下面的命令來查看是否啟用了 MySQL 服務。此時,如果我們的 MySQL 服務已經啟動了,則會輸出我們的執行信息。

sudo systemctl status mysqld


Linux 小白的 .NET Core 部署之路


當我們啟動後可能會疑問,我們並沒有設置管理員密碼啊?原來,我們在安裝的過程中,會自動的為 MySQL root 用戶生成一個臨時的密碼,我們可以通過下面的命令中找到這個默認的密碼。

sudo grep "temporary password" /var/log/mysqld.log

我們可以使用下面的命令來修改我們的 root 密碼,系統會提示我們輸入默認密碼,默認密碼輸入正確後就可以自己設置新的密碼了。

sudo mysql_secure_installation

注意:重新設置的密碼至少包含一個大寫字母,一個小寫字母,一個數字和一個特殊字元的12個字元!!!在整個設置密碼的過程中,總共有五步:設置 root 密碼;是否禁止 root 賬號遠程登錄;是否禁止匿名賬號(anonymous)登錄;是否刪除測試庫;是否確認修改。按照你自己的需求後,設置完成後即可。

Linux 小白的 .NET Core 部署之路


e)設置允許遠程登錄、

在上面的設置完成後,我們用自己本地的 Workbench 連接伺服器上的資料庫,發現無法進行連接,如果你之前使用過遠程連接 MySQL Server 你應該會知道,我們需要在 user 表中設置 root 用戶允許訪問的地址。

mysql -h localhost -u root -p ##登錄資料庫,輸入密碼後完成登錄
use mysql; ##選擇 mysql 表
select user,host from user; ##查詢當前的用戶
update user set host="%" where user="root"; ##允許使用 root 賬戶進行遠程登錄
flush privileges; ##刷新設置


Linux 小白的 .NET Core 部署之路


這時,我們就可以遠程連接到我們的 MySQL Server 上了。

3、發布部署程序

本次部署的項目,採用的還是之前的畢業設計的項目(ASP.NET Core 2.0 MVC 項目實戰),在這裡發布測試的時候遇到了一個問題,因為當時項目採用的 MySQL 版本為5.7,伺服器中所安裝的 MySQL 版本為8.0,而 Oracle 在最新的 MySQL 中將默認的版本身份驗證從 mysql_native_password 改為了 caching_sha2_password,這裡在進行數據操作時就會出現問題。如果你和我遇到同樣的問題,你需要將 MySQL 官方的 EFCore 組件替換成 Pomelo.EntityFrameworkCore.MySql,嗯,替換,而不是升級,因為升級後又會出現新的問題(小聲BB:MySQL 的這個 EFCore 的驅動事不是一般的多)。如果你不想升級的話,可以參考這個做法,鏈接地址送上:mysql8 :客戶端連接caching-sha2-password問題。

當我們把項目丟到伺服器上後,我們進去到放置的路徑下,執行 dotnet 命令就可以運行我們的項目了。這裡要特別注意,Linux 中對於大小寫是區分的,這裡輸入的路徑以及項目的名稱都要確保和實際相同。

cd /usr/local/wwwroot/psu/ ##注意:最後一定要加上這個 / !!!!!
dotnet PSU.Site.dll

這裡會有個問題,不管你是使用的虛擬機還是雲伺服器,因為 5000 埠並沒有開放給外部訪問,所以外部的機器採用 ip:port 的方式,是無法訪問到的,所以我們接下來需要安裝反向代理的伺服器來達到訪問的目的。

在部署 .NET Core 項目的時候,我們應該保持我們的程序的 .NET Core 版本與伺服器上的環境版本保持一致,這樣才可以避免因為環境的因素而導致的某些問題,所以這裡我部署 .NET Core 2.0 版本的程序其實不是很好的選擇。

4、安裝 Nginx 伺服器

在 Windows 伺服器上,如果我們要部署 .NET 項目,肯定會選擇部署到 IIS 中,同樣的,雖然 .NET Core 可以實現自託管,內置的 Kestrel 也非常適合從 ASP.NET Core 提供動態內容。 但是,Kestrel 的 Web 服務功能不像專門的伺服器(如 IIS、Apache 或 Nginx)那樣功能豐富。 而反向代理伺服器可以從 HTTP 伺服器卸載服務靜態內容、緩存請求、壓縮請求和 SSL 終端等工作。 反向代理伺服器可能駐留在專用計算機上,也可能與 HTTP 伺服器一起部署可是為了能使用更多的功能,所以這裡我們還是會配合一個反向代理伺服器進行使用,在這裡,我採用的是 Nginx。

a)安裝 Nginx

從官網上下載 nginx 包並解壓,這裡採用的是使用源碼編譯安裝的形式。

wget -c http://nginx.org/download/nginx-1.9.9.tar.gz
tar -zxvf nginx-1.9.9.tar.gz

解壓完成後我們就可以進入到 nginx 目錄,在這裡我們創建默認的配置文件。在我們創建配置文件之前,我們需要安裝 gcc 環境。

cd nginx-1.9.9
yum install gcc gcc-c++
./configure

上面的步驟完成後,我們需要添加幾個插件去完善 Nginx 的功能。

Nginx 的 http 模塊使用 pcre 來解析正則表達式,PCRE(Perl Compatible Regular Expressions) 是一個Perl庫,包括 perl 兼容的正則表達式庫。

yum install -y pcre pcre-devel

zlib 庫提供了很多種壓縮和解壓縮的方式,Nginx 使用 zlib 對 http 包的內容進行 gzip ,所以我們也需要在伺服器上安裝 zlib 庫。

yum install -y zlib zlib-devel

Nginx 不僅支持 http 協議,還支持 https 協議,而 OpenSSL 是一個強大的安全套接字層密碼庫,囊括主要的密碼演算法、常用的密鑰和證書封裝管理功能及 SSL 協議,並提供豐富的應用程序供測試或其它目的使用,所以我們也會在 Nginx 上面添加。

yum install -y openssl openssl-devel

至此,我們對於 Nginx 插件的安裝就完成了,現在我們就可以重新執行配置命令,再編譯安裝了。

./configure
make install

編譯安裝完成後,Nginx 就安裝到了我們的伺服器上,可是安裝到哪裡去了呢?這裡我們可以使用下面的命令去找到我們安裝的 Nginx。知道了安裝路徑後,我們就可以進入 Nginx 的目錄中執行進一步的操作。至此 Nginx 的安裝就完成了。

whereis Nginx
cd /usr/local/nginx/sbin/

安裝完成後,我們一般會將 Nginx 設置為開機自啟動以及自動重啟,從而預防特殊情況導致的網站掛了。我們先創建一個軟連接用來指向 Nginx 的安裝目錄。

ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

現在創建一個自啟動的腳本。

vim /etc/init.d/nginx

在腳本中,輸入下面的內容。

Linux 小白的 .NET Core 部署之路

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig: - 85 15
# description: NGINX is an HTTP(S) server, HTTP(S) reverse
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /usr/local/nginx/conf/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /usr/local/nginx/logs/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
make_dirs() {
# make required directories
user=`$nginx -V 2>&1 | grep "configure arguments:" | sed "s/[^*]*--user=([^ ]*).*/1/g" -`
if [ -z "`grep $user /etc/passwd`" ]; then
useradd -M -s /bin/nologin $user
fi
options=`$nginx -V 2>&1 | grep "configure arguments:"`
for opt in $options; do
if [ `echo $opt | grep ".*-temp-path"` ]; then
value=`echo $opt | cut -d "=" -f 2`
if [ ! -d "$value" ]; then
# echo "creating" $value
mkdir -p $value && chown -R $user $value
fi
fi
done
}
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
make_dirs
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
configtest || return $?
stop
sleep 1
start
}
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac

Linux 小白的 .NET Core 部署之路

現在我們將自啟動的腳本賦予腳本可執行許可權,並將 Nginx 服務加入 chkconfig 管理列表中。

chmod a+x /etc/init.d/nginx

chkconfig --add /etc/init.d/nginx
chkconfig nginx on

當上面的設置都完成後,啟動我們的 Nginx 守護服務就可以了。

systemctl start nginx

同樣的,我們也可以使用下面的命令來查看 Nginx 服務的狀態。

systemctl status nginx

一些常用的命令(需要你處於 Nginx 的安裝目錄下時執行,例如,這裡我的 Nginx 安裝目錄為 /usr/local/nginx/sbin/,如果在不在安裝目錄下需要使用全路徑)

啟動 Nginx 服務

./nginx

停止 Nginx 服務

./nginx -s stop
./nginx -s quit

停止 Nginx 服務有兩種方式,第一種:-s stop:先查出 nginx 的進程 id ,再使用 kill 命令強制殺掉進程;第二種:-s quit:等待 Nginx 的進程處理完成後再進行停止。

重新載入 Nginx 配置

./nginx -s reload

5、配置守護程序以及自啟動

在上面我們已經使用 dotnet 命令將我們的項目在伺服器上運行了,而我們目前通過 ip:port 的形式沒有辦法進行訪問,這時我們安裝的 Nginx 伺服器就可以為我們提供幫助了。

在安裝 Nginx 的時候我們創建了一個配置文件,現在我們就可以通過編輯這個配置文件,將我們的項目使用 Nginx 進行代理。首先我們進入 Nginx 的配置文件所在的路徑,打開這個配置文件。

cd /usr/local/nginx/conf/
vim nginx.conf

打開 conf 文件後,我們找到 Server 節點,會看到以下的配置項。

Linux 小白的 .NET Core 部署之路

server {
  listen 80;
  server_name localhost;
  location / {
root html;
index index.html index.htm;
  }
}

Linux 小白的 .NET Core 部署之路

當使用 Nginx 時,會根據 server_name 匹配伺服器,例如當我們運行 Nginx 成功後,通過瀏覽器瀏覽本機的 ip 時,默認會顯示 Nginx 的默認頁面。而當沒有匹配的 server_name 時,Nginx 則會使用默認伺服器。 如果沒有定義默認伺服器,則配置文件中的第一台伺服器則成為默認伺服器。

這裡進行修改配置信息,將80埠的請求轉發到我們使用 Kestrel 監聽的5000埠上的應用上。

Linux 小白的 .NET Core 部署之路

server {
  listen 80;
  server_name localhost;
  location / {
    # Kestrel
    proxy_pass http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Host $http_host;
    proxy_cache_bypass $http_upgrade;
}
}

Linux 小白的 .NET Core 部署之路

我們可以使用命令去驗證下修改的配置格式是否正確,配置正確後就可以執行 reload 命令使配置生效。

./nginx -t ##測試格式是否正確
./nginx -s reload ##重新載入配置

當我們完成上面的步驟後,通過瀏覽器打開我們的頁面,毫無意外的 Nginx 的錯誤頁面出現在了我們的面前。仔細梳理下我們的流程,用戶通過瀏覽器請求 ip,Nginx 將默認的 80 埠的請求反向代理轉接到我們應用程序的 5000 埠上,而現在我們並沒有使用 dotnet 命令來運行我們的程序,伺服器上的 5000 埠也就沒有程序在監聽。因此當我們在使用 Nginx 進行反向代理我們的 .NET Core 程序時,我們同樣需要使用 dotnet 命令將我們的程序運行起來。

現在,將我們的程序重新使用 dotnet 命令運行起來,打開我們的瀏覽器訪問就會發現我們的網站已經部署成功了。而且瀏覽器的插件也已經識別出我們使用的 Web 伺服器為 Nginx 的 1.9.9 版本。

Linux 小白的 .NET Core 部署之路


所以這裡會引出一個問題,萬一 dotnet 進程意外掛了,整個網站不就徹底掛了嗎,難道還要我們手動連接到伺服器再次創建?所以我們需要能夠讓 dotnet 進程能夠自動重啟,從而避免這種情況。

微軟官方則建議我們使用 supervisor 守護程序的方式實現我們守護我們的 .NET Core 程序,確保應用服務即使閃退也會自動重啟。同時,Supervisor 也包含一個 web 管理頁面,從而方面我們的管理。

在 linux 或者 unix 操作系統中,守護進程(Daemon)是一種運行在後台的特殊進程,它獨立於控制終端並且周期性的執行某種任務或等待處理某些發生的事件。由於在linux中,每個系統與用戶進行交流的界面稱為終端,每一個從此終端開始運行的進程都會依附於這個終端,這個終端被稱為這些進程的控制終端,當控制終端被關閉的時候,相應的進程都會自動關閉。但是守護進程卻能突破這種限制,它脫離於終端並且在後台運行,並且它脫離終端的目的是為了避免進程在運行的過程中的信息在任何終端中顯示並且進程也不會被任何終端所產生的終端信息所打斷。它從被執行的時候開始運轉,直到整個系統關閉才退出。

輸入下面的命令安裝 Supervisor 程序。

sudo yum install supervisor

安裝完成後我們就可以配置我們的 Supervisor 程序。

首先,我們在 etc 目錄下創建存儲我們配置文件的目錄。

mkdir -m 700 -p /etc/supervisor

目錄創建完成後,我們創建 supervisor 的配置文件,這裡採用的是將默認的配置文件複製一份到我們的目錄下面。

echo_supervisord_conf > /etc/supervisor/supervisord.conf

在 /etc/supervisor 目錄下我們創建一個存放我們 dotnet core 進程文件的存放目錄 conf.d。

mkdir -m 700 /etc/supervisor/conf.d

修改我們的配置文件,在配置文件的最後,將路徑指向我們創建的 conf.d 文件夾。注意注意,這裡一定要把前面的 ; 去掉,否則的話這個 include 節點還是被注釋無法被應用的!!!

[include]
files=/etc/supervisor/conf.d/*.conf

現在我們就創建一個 PSU.conf 配置文件來管理我們這個項目的 dotnet 進程。嗯,這裡我還是採用 WinSCP 的方式進行編輯,同時,我們需要將注釋的信息刪除。

cd /etc/supervisor/conf.d/
touch PSU.conf

Linux 小白的 .NET Core 部署之路

[program:PSU.Site]
command=dotnet PSU.Site.dll #要執行的命令
directory=/usr/local/wwwroot/psu/ #命令執行的目錄
environment=ASPNETCORE__ENVIRONMENT=Production #環境變數
user=root #進程執行的用戶身份
stopsignal=INT
autostart=true #是否自動啟動
autorestart=true #是否自動重啟
startsecs=3 #自動重啟間隔
stderr_logfile=/usr/local/wwwroot/logs/psu.err.log #標準錯誤日誌
stdout_logfile=/usr/local/wwwroot/logs/psu.log #標準輸出日誌

Linux 小白的 .NET Core 部署之路

這裡我們指明的日誌輸出的文件,我們實現創建好。

配置完成後我們就可以創建 Supervisor 的自啟動服務。

vim /etc/systemd/system/supervisor.service

編輯我們的自啟動腳本。

Linux 小白的 .NET Core 部署之路

[Unit]
Description=supervisor
[Service]
Type=forking
ExecStart=/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
ExecStop=/usr/bin/supervisorctl shutdown
ExecReload=/usr/bin/supervisorctl reload
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target

Linux 小白的 .NET Core 部署之路

重新載入我們的設置。

systemctl daemon-reload

設置 supervisor.service 服務開機啟動。

systemctl enable supervisor.service

啟動我們的服務

systemctl start supervisor.service

現在我們就使用命令查看我們的程序是否運行,最後的 PSU.Site 則是你設置的配置文件里的 program 名稱。

[root@VM_0_3_centos ~]# ps -ef | grep PSU.Site
root 1382 545 4 19:45 ? 00:00:05 dotnet PSU.Site.dll
root 1648 1606 0 19:47 pts/0 00:00:00 grep --color=auto PSU.Site

如果這裡你無法看到兩個進程的話,則說明你的程序沒有啟動成功,你可以去之前設置的程序的錯誤日誌文件處查看因為什麼原因導致的程序無法啟動。同時,當你對配置文件做了任何的改變後,你都需要將 Supervisor 進行重啟。

四、總結

這次的文章應該是目前寫過時間最長也是字數最多的一篇了,就像標題寫的一樣, Linux 小白,整個過程持續了很多天,中間在重裝系統的過程中碰巧還遇到了 aspnetcore 的一個 bug(Missing package dotnet-runtime 2.1.6 for CentOS),看到 bug 關閉後,周六又弄了四五個小時按照步驟一步步走下來才完成了整個的部署。網上有很多將 .NET Core 程序部署到 Linux 伺服器的文章,可是,看再多遍,當你嘗試的時候,還是會發生很多的問題,如果你有將 .NET Core 程序部署到 Linux 伺服器上的計劃時,希望你可以實際嘗試嘗試,畢竟,踩的坑多了,稍微也能避開一點坑了,哈哈哈。

五、參考

1、如何在CentOS 7上安裝MySQL

2、CentOS 7 下 Nginx安裝以及配置

3、CentOS 7 源碼編譯安裝 Nginx

4、ASP.NET Core Linux下為 dotnet 創建守護進程(必備知識)

5、Centos 7 .Net core後台守護進程Supervisor配置

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

Spring MVC之DispatcherServlet初始化詳解
介面測試總結分享(http與rpc)

TAG:程序員小新人學習 |