轉載請注明原作者(think8848)和出處(http://think8848.cnblogs.com)
寫在前面的話
不知不覺在cnblogs上注冊已經10多年了,看我的園齡就直接暴露了我實際年齡,很多時候看到時間概念時,我總覺得一陣慚愧...自12年開始,我都不知道在忙什么,反正是挺忙的,忙到經常下班就天黑了,以至於偶爾看到傍晚的天空時居然會產生一種莫名的感動。也是從12年開始就很少上cnblogs了,到后來居然莫名奇妙的連用戶名和密碼都被改了,費了老大勁才又找到,可惜還是改不回我以前那6位的密碼了。最近因工作的關系,對這些年一直在做的項目進行了一些反思,發覺一個事實:一個技術性公司或者一名技術人員,輕視技術的話就很容易變成無源之水、無本之木了,因此,是時候好好的學習了,種一顆樹最好的時間是十年前,其次就是現在。
寫本文的初衷是在CentOS生產環境中部署ASP.NET Core應用程序,為了避免以后又忘記各種步驟,所以還是做點筆記比較好。在此我不打算談個人對.NET Core技術前景的理解,不管其他人會不會選這個路線,反正我計划是走這個技術路線了。也不打算說明ASP.NET Core項目結構,甚至對於本文涉及的步驟也不解釋為什么要這么做(本文涉及的內容比較多,如果全都去說明,篇幅將非常之大,所以我會在相關章節放參考資料鏈接,希望對您有所幫助)如果您想詳細了解本文中每個步驟的含義,請參閱這里,本文將主要介紹在CentOS7.2的最小安裝環境里,部署ASP.NET Core應用程序的方法。為了達到照着這篇文章能真正將Web網站真正部署成功的目的,每一個環節我都反復做了驗證,如果您照着這個步驟做但卻被卡在某步,額..我除了建議您檢查操作步驟外,只能希望您面向運氣的編程經驗能足夠豐富。通常而言,這種部署工作,環境的影響非常大,一定要多試、多想、多折騰,沒有別的好辦法,很多時候別人在遠程是幫你解決不了問題的,Good luck!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~我是分割線~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一、 CentOS環境准備(yum源)
本文使用的CentOS版本
CentOS7.2下載地址:http://iso.mirrors.ustc.edu.cn/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1511.iso
CentOS7.2最小安裝虛擬機文件(本文實驗環境,278M)下載地址: http://pan.baidu.com/s/1pLxWuvT 提取碼:sqxn,root密碼111111
虛擬機安裝包:https://download3.vmware.com/software/wkst/file/VMware-workstation-full-12.1.1-3770994.exe
虛擬機你懂的:5A02H-AU243-TZJ49-GTC7K-3C61N
1. 安裝wget
sudo yum install wget -y
2. 備份默認yum源
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
3. 下載阿里雲yum源
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
4. 清除並重建yum緩存
sudo yum clean all
sudo yum makecache
5. 安裝EPEL源
sudo yum install epel-release -y
二、安裝.NET Core SDK
1. 安裝.NET Core SDK
sudo yum install libunwind -y
sudo yum install libicu -y
curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809131
sudo mkdir -p /opt/dotnet
sudo tar zxf dotnet.tar.gz -C /opt/dotnet
sudo ln -s /opt/dotnet/dotnet /usr/local/bin
使用 dotnet --info 查看.NET Core安裝信息
2. 創建Hello World
cd ~
mkdir projects
cd projects
mkdir hwapp
cd hwapp
dotnet new
dotnet restore
dotnet run
(友情提醒1,不要使用 sudo mkdir hwapp 這種方法創建文件夾,不然...
友情提醒2,如果出現“libunwind.so.8: cannot open shared object file: No such file or directory”錯誤,請嘗試使用 sudo yum install icu -y 修復,很奇怪的是我在實體機安裝的版本里遇到這個問題了,但是在虛擬機中沒有遇到這個問題,解決問題的辦法來自這里,感謝ModestMT.Zou兄)
三、安裝Nginx或Apache
3.1 安裝Nginx
sudo yum install nginx -y
3.1.1 將Nginx設置為開機啟動
sudo systemctl enable nginx.service
3.1.2 啟動Nginx
service nginx start
a. 查看進程
ps -ef | grep nginx
b. 查看http head
curl --head localhost
3.1.4 設置反向代理
先將nginx配置文件/etc/nginx/nginx.conf中的默認代理的location節注釋掉,免得維護起來不方便(當然如果不嫌那些無關配置看着礙眼,也可以直接在這里配置)
然后在/etc/nginx/default.d目錄下新建配置文件
cd /etc/nginx/default.d
sudo vi aspnetcoreapp.conf
文件內容如下(也可以不用建這個配置文件,直接在/etc/nginx/nginx.conf的location節點中輸入這些proxy***內容即可)
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; }
3.1.5 重啟nginx
service nginx restart
3.2 安裝Apache
sudo yum install httpd -y
3.2.1 設置Apache開機啟動
sudo systemctl enable httpd.service
3.2.2 然后啟動Apache服務
service httpd start
3.2.3 查看Apache是否安裝並啟動成功的方法參見上面3.1.3內容
3.2.4 設置反向代理,在/etc/httpd/conf.d目錄下創建reverse_proxy.conf文件
cd /etc/httpd/conf.d
sudo vi reverse_proxy.conf
文件內容如下:
<VirtualHost *: 80>
ServerAdmin think8848.cnblogs.com
ServerName think8848
ProxyRequests Off
<Proxy *> Order Deny,Allow Allow from all </Proxy> ProxyPass / http://localhost:5000/ ProxyPassReverse / http://localhost:5000/ </VirtualHost>
(友情提示:在上面這個配置里面,ServerAdmin和ServerName中間不要包含空格,另外,Order Deny,Allow中的逗號兩邊也不要帶空格,不要問我為什么,等我哭會兒再告訴你)
3.2.5 重啟Apache
service httpd restart
四、設置防火牆例外
4.1 備份防火牆配置文件
sudo cp /etc/firewalld/zones/public.xml /etc/firewalld/zones/public.xml.bak
4.2 編輯防火牆配置文件,開放80端口
sudo vi /etc/firewalld/zones/public.xml
<rule family="ipv4"> <port protocal="tcp" port="80"/> <accept /> </rule>
4.3 重啟防火牆
service firewalld restart
4.4 在瀏覽器中輸入虛擬機ip,看看http服務是否可用,不出意外應該能看到這個頁面了
(友情提示 ,如果您不知道虛擬機ip是多少,可以使用ifconfig,如果您發現ifconfig居然是無效命令,那么可能需要先安裝一下net-tools包,如下: sudo yum install net-tools -y )
a. Nginx
b. Apache
五、新建ASP.NET Core項目
建一個Asp.Net Core項目 ,使用dotnet命令參數請參閱這里
cd ~/projects
mkdir aspnetcoreapp
cd aspnetcoreapp
dotnet new -t web dotnet restore dotnet run
應該可以看到ASP.NET Core項目已經可以運行了
但此時使用在其他終端上嘗試訪問http://CentOS地址,是打不開網站的,主要是因為SELinux限制了訪問,你可以先將SELinux臨時關閉,看看能不能訪問
sudo setenforce 0
可以使用命令查看SELinux是否生效,permissive說明已經關閉了
sestatus
此時訪問http://CentOS地址,應該就能看見這個界面了
六、新建SELinux策略
現在我們為SELinux創建策略,使其允許Nginx訪問
6.1 創建SELinux策略,首先安裝semanage命令包
sudo yum install policycoreutils-python -y
(友情提示,如果在執行 sudo cat ... audit2allow -M httpd_allow 命令過程中發生 could not write output file: [Errno 13] Permission denied: 'httpd_allow.te' )錯誤,則進入到用戶根目錄 cd ~ 重試,點擊這里查看SELinux和audit2allow相關內容)
6.2 創建並應用SELinux策略
6.2.1 創建Nginx策略
cd ~
sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M nginx_allow
sudo semodule -i nginx_allow.pp
6.2.2 創建Apache策略
cd ~
sudo cat /var/log/audit/audit.log | grep httpd | grep denied | audit2allow -M httpd_allow sudo semodule -i httpd_allow.pp
七、安裝Supervisor
sudo yum install python-setuptools -y
sudo easy_install supervisor
7.1 生成配置文件
如果用root用戶,則直接使用下列語句
echo_supervisord_conf > /etc/supervisord.conf
如果非root用戶,則使用下列命令
cd ~ echo_supervisord_conf > supervisord.conf sudo mv supervisord.conf /etc
修改/etc/supervisord.conf配置文件,將最后兩行修改為:
然后再創建一個supervisor的配置目錄
sudo mkdir supervisor.d
在這個目錄里面新建一個文件aspnetcoreapp.conf,內空如下
[program:aspnetcoreapp] command=dotnet aspnetcoreapp.dll directory=/var/websites/aspnetcoreapp autostart=true autorestart=true stderr_logfile=/var/log/aspnetcoreapp.d/error.log stdout_logfile=/var/log/aspnetcoreapp.d/output.log environment=ASPNETCORE_ENVIRONMENT=Production user=root stopsignal=INT
順便再創建一下日志文件夾
sudo mkdir /var/log/aspnetcoreapp.d
設置supervisor開機啟動
sudo wget -O /usr/lib/systemd/system/supervisord.service https://raw.githubusercontent.com/Supervisor/initscripts/master/centos-systemd-etcs
systemctl enable supervisord.service
(友情提示,如果supervisor有問題搞不定,請參考這里,有關supervisor開機啟動腳本,請參考這里)
八、發布ASP.NET Core網站
8.1 發布ASP.NET Core網站前,一些依賴的包要安裝一下
sudo yum install npm -y sudo npm install -g bower sudo npm install -g gulp
8.2 發布網站
cd ~/projects/aspnetcoreapp
dotnet publish -o ~/publish
將網站移動到/var/websites目錄中
sudo mkdir /var/websites
sudo mv ~/publish /var/websites/aspnetcoreapp
8.3 啟動網站
systemctl start supervisord
稍等片刻,應該就可以打開網站了。使用 reboot 命令重啟電腦看看網站能不能訪問。
(友情提示:如果第一次在使用dotnet publish命令發布網站過程中網絡或是其他原因中斷了發布,那么就有可能在以后發布時報“Error: Cannot find module '***'”錯誤,在這種情況下嘗試刪除項目根目錄下的node_modules文件夾,應該就可以解決問題了)
九、使用systemd實現ASP.NET Core開機自動啟動
有關systemd的詳細資料,請參閱這里和這里,在使用systemd實現.NET Core程序開機啟動前,請先關閉Supervisor服務,方法如下:
sudo systemctl disable supervisord.service
9.1 創建aspnetcoreapp.service文件
cd /usr/lib/systemd/system
sudo vi aspnetcoreapp.service
9.2 輸入配置文件內容
[Unit] Description=ASP.NET Core systemd demo Wants=network.target After=network.target [Service] ExecStart=/usr/local/bin/dotnet /var/websites/aspnetcoreapp/aspnetcoreapp.dll [Install] WantedBy=multi-user.target
9.3 設置開機啟動
sudo systemctl enable aspnetcoreapp.service
通常使用dotnet命令運行一個*.dll時,基本上都是在dll所在目錄中進行,如果不在dll所在目錄,想要運行dll行不行呢?答案是可以的,如: dotnet ~/project/hwapp/bin/hwapp.dll ,這完全沒有問題,然而,ASP.NET Core項目直接這么運行則會有問題,如下圖所示:
請注意Content root path的值,這對於一個web應用而言,意味着wwwroot等之類的目錄全都找不到了,使用curl驗證一下,果然發生500錯誤了
那要怎么解決這個問題呢?so easy,只需要將Program.cs中改一下就可以了
首先引入 using System.Reflection; 命名空間,然后將 .UseContentRoot(Directory.GetCurrentDirecotry()) 行注釋掉,在下面加上 .UseContentRoot(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)) ,這行代碼對於.NETer不用多解釋吧,如下圖所示
接下來發布Web網站,然后替換/var/websites下原來的網站,接下來重啟電腦
重啟后進程里面有aspnetcoreapp.dll,說明網站啟動成功了
十、使用Monit監控ASP.NET Core網站服務
到現在貌似一切都看起來還不錯,但是還有一個問題,如果使用systemd啟動網站,而網站應用掛了,如何能自動恢復服務呢?,這里再引入一個監控工具Monit,關於Monit的更多信息請參閱這里
10.1 安裝monit
sudo yum install monit -y
10.2 創建網站監控配置文件
sudo vi /etc/monit.d/aspnetcoreapp.conf
配置內容如下:
check host aspnetcoreapp with address localhost start program "/usr/bin/systemctl start aspnetcoreapp.service" stop program "/usr/bin/systemctl stop aspnetcoreapp.service" if failed host localhost port 5000 protocol http then restart if 3 restarts within 3 cycles then timeout
可以使用 sudo monit -t 來測試配置文件是否合法
10.3 配置Monit開機啟動
sudo systemctl enable monit.service
重啟電腦,應該就能看到啟動效果了
10.4 為了展示Monit的監控效果,我們殺死ASP.NET Core網站進程,方法如下:
sudo pkill -9 -f 'aspnetcoreapp.dll'
多刷新幾次進程,就會發現過了一小會,網站又被啟動了
最后一個問題,那干脆不要使用systemd,直接用monit來自動啟動ASP.NET Core網站行不行呢?額...這個問題不好說,我嘗試了一下將aspnetcoreapp.conf修改成如下:
check host aspnetcoreapp with address localhost start program "/usr/local/bin/dotnet /var/websites/aspnetcoreapp/aspnetcoreapp.dll" stop program "pkill -9 -f 'aspnetcoreapp.dll'" if failed host localhost port 5000 protocol http then restart if 3 restarts within 3 cycles then timeout
也可以啟動Web網站,但是過不了多久就會重啟,但是重啟時網站也跟着重啟,這就尷尬了...這個原因我猜想應該是在monit中啟動的dotnet命令,在它的一次check周期結束后monit的check進程就關閉了,而使用這個進程打開的dotnet程序也跟着關了,不知道monit是否有systemd的類似foking的設置,有知道的兄弟吱一聲吧。
最最后,才開始接觸.NET Core,通過這兩天一個簡單的學習,個人感覺Nginx+Supervisor的方式效果更好點,ASP.NET Core官方也使用此組合。