2017年7月18日星期二

ASP.NET Core + CentOS 7 + Apache安裝攻略

作為一個經歷過ASP.NET初代到4.5版本的人,見到ASP.NET終於能夠誇平台是值得興奮的事。
雖然Mono早在好幾年前已經很成熟,而且相容度亦滿足一般使用,但始終不是官方支持,商業上實在很難說服團隊使用。
現在周圍的人都在應用Azure/AWS,甚至是Docker技術把虛擬機和程式封裝運作,ASP.NET MVC/Webforms只能在IIS上執行的確是很尷尬的局面。
Microsoft此舉絕對是明智決定,由一直面對著主流的PHP,Java/Spring,到近年在Start-up廣泛使用的Ruby on Rails或Python/Django,都是Cross-platform的。
所以DotNET Core的出現使ASP.NET不再邊緣化,終於名正言順在Linux/Mac上運行了。
我都來湊下熱鬧,嘗試設置一下DotNET Ready的Linux平台,過程中固然不會一直都順利,自己都是LINUX外行人,我使用CentOS的時候已經是大約6年前的CentOS 5,很多Command都忘記了。
所以我就把每一步Command的輸出,和自己遭遇到的問題解決辦法都寫下來,給自己和大家參考一下。


事前準備
我所採用的軟件版本如下:
  • CentOS Linux release 7.3.1611 (Core) 64Bit
  • Apache 2.4.6 (httpd.x86_64 0:2.4.6-45.el7.centos.4)
  • .NET Core 1.0.4

有幾個官方連結會用上的:
  1. CentOS Linux release 7.3.1611 (Core) 64Bit
  2. Set up a hosting environment for ASP.NET Core on Linux with Apache, and deploy to it
  3. .NET Core command-line interface (CLI) tools

頭兩個是必須的,第三個頁面讓你了解一下Linux下的DotNET CLI工作的命令。

首先我們依照第一個頁面的指示先把DotNET Core核心檔案安裝至Linux。
頁面上沒有提的事,就是我們安裝CentOS後,有兩件事我認為要做的。
1. 做一次系統軟件更新
2. 安裝VNC Server,畢竟我是來自Windows世界,有GUI操作資料夾或檔案,用GUI文字編輯軟件(GEdit)去編輯Apache Config檔會更容易,沒必要扮Geek用vi Editor吧...

Yum Update

***請確認是使用Root權限作SSH連線***

#確認CentOS版本
[root@localhost ~]# cat /etc/centos-release
#> CentOS Linux release 7.3.1611 (Core)
#更新一次系統軟件
[root@localhost ~]# yum update
#完成後,重啟系統
[root@localhost ~]# reboot

安裝VNC Server
#確認沒有安裝過VNCServer
[root@localhost ~]# which vncserver
#***Output***:
#> /usr/bin/which: no vncserver in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

#安裝Gnome Desktop
[root@localhost ~]# yum groupinstall "GNOME Desktop"

#完成後,安裝VNCServer
[root@localhost ~]# yum install tigervnc-server

#執行以下指令,檢查是否安裝完成
[root@localhost ~]# rpm -qa | grep tigervnc-server
#***Output***:
#> tigervnc-server-1.3.1-9.el7.x86_64
#> tigervnc-server-minimal-1.3.1-9.el7.x86_64

如果你只想用root的帳戶登入,就直接輸入指令 vncserver,系統就會要求你確認登入密碼,然後自動建立config檔案。
之後試試用VNC Viewer連接看看。
注意這叫是TigerVNC,是TightVNC的分支。
TigerVNC Binary Download
[root@localhost ~]# vncserver

安裝.NET Core
依著第一個連結安裝,應該沒有問題的。
#安裝所需dependencies
[root@localhost ~]# sudo yum install libunwind libicu
#下載.NET Core檔案至本機,在/Home資料夾可以找到dotnet.tar.gz
[root@localhost ~]# curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?linkid=848821
#解壓縮dotnet.tar.gz
[root@localhost ~]# sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet
#建立Symlink路徑
[root@localhost ~]# sudo ln -s /opt/dotnet/dotnet /usr/local/bin

驗證.NET Core安裝
來到這裡你已經成功安裝.NET Core,建立一個專案測試一下
#建立Console專案
[root@localhost ~]# dotnet new console -o hwapp
#移至目錄
[root@localhost ~]# cd hwapp
#restore dependencies,例如JSON.NET,EntityFramework,Bootstrap等Library
[root@localhost ~]# dotnet restore
#執行
[root@localhost ~]# dotnet run
#***Output***:
#> Hello World!

如果你想知道.NET Core的資訊可以輸入指令:
[root@localhost hwapp]# dotnet --info
.NET Command Line Tools (1.0.4)

Product Information:
 Version:            1.0.4
 Commit SHA-1 hash:  af1e6684fd

Runtime Environment:
 OS Name:     centos
 OS Version:  7
 OS Platform: Linux
 RID:         centos.7-x64
 Base Path:   /opt/dotnet/sdk/1.0.4

建立ASP.NET Core專案
建立一個ASP.NET Core Project,若你是VS2017,應該可以直接建立。
如是VS2015,在Microsoft網站下載並安裝-NET Core tools for Visual Studio 2015後就會出現Project Template。
Publish你的專案後應該會在Project Folder見到{Project Folder}\bin\Release\PublishOutput,先記住這個位置,之後會用到裡面的檔案。


返回CentOS,建立目錄-"/var/aspnetcore/{Your_Project_Name}",再把剛剛"PublishOutput"中的所有檔案上傳到目錄中。


設定Apache
直到目前為止,應該不會有特別問題,接下來就要到Apache部份,應該是較有難度的部份,同樣是上面第二條連結的內容,我的步驟會跟官方有點不同,請注意。
官方教學中會要求執行
[root@localhost hwapp]# sudo yum update -y
但其實我們早前已經執行過,所以再次執行應該不會有什麼更新,因為我認為這個指令應該在更早的時候做。

切換回根目錄,安裝Apache
[root@localhost hwapp]# cd ~
[root@localhost ~]# sudo yum -y install httpd mod_ssl

完成後,可以執行指令檢查Apache路徑
[root@localhost ~]# whereis httpd
#***Output***:
#> httpd: /usr/sbin/httpd /usr/lib64/httpd /etc/httpd /usr/share/httpd /usr/share/man/man8/httpd.8.gz

設定Apache reverse proxy
接下來大家務必要小心進行,留意大小寫,都是Case-sensitive。
而我跟官方教學不同,這部份都是用VNC進入GUI Desktop做的。

打開gedit,新建文字檔,依官網所示輸入conf內容,要注意的是"hellomvc"是官方範例名稱,而我則叫做"SkinCV",大家自行換掉名稱。

        ProxyPreserveHost On
        ProxyPass / http://127.0.0.1:5000/
        ProxyPassReverse / http://127.0.0.1:5000/
        ErrorLog /var/log/httpd/{YOUR_PROJECT_NAME}-error.log
        CustomLog /var/log/httpd/{YOUR_PROJECT_NAME}-access.log common
    


把檔案儲存至目錄 - "/etc/httpd/conf.modules.d"
或者你會問什麼是"reverse proxy",這個跟.NET Core內建的"kestrel server"和Forwarding有關,有點複雜,但可以暫時不理,

現在我們測試一下Config是否正確:
執行:
[root@localhost ~]# sudo service httpd configtest
#***Output***:
#AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' #directive globally to suppress this message
#Syntax OK
在我的情況雖然有Warning message,但只要Synxtax OK就可以了。

重新啟動Apache:
[root@localhost ~]# sudo systemctl restart httpd
[root@localhost ~]# sudo systemctl enable httpd

設定service file
這是最後一步,同樣是我預到最多問題的一步。
跟之前一樣,打開gedit,新建文字檔,同樣照官方所示輸入內容。
[Unit]
Description=Example .NET Web API Application running on CentOS 7

[Service]
WorkingDirectory=/var/aspnetcore/hellomvc
ExecStart=/usr/local/bin/dotnet /var/aspnetcore/hellomvc/hellomvc.dll
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production 

[Install]
WantedBy=multi-user.target

在這裡,你要特別要確定幾件事情。
1. 路徑是否存在? WorkingDirectory是你存放[PublishOutput]中檔案的位置,見過網上教學會在最後加上"/Bin"路徑,這其實是錯的。
2. ExecStart的數值中,要注意Project folder跟assemblies (*.dll)的名稱是Case-sensitive。
3. CentOS是否有"apache"的user? 沒有的話,而你又想快點完成設定,大可以跟我一樣使用"root",但緊記之後要轉回其他user。

確認後,儲存至"/etc/systemd/system/"。


執行指令,開始Service。
[root@localhost ~]# systemctl enable kestrel-{Your_Project_Name}.service
#***Output:***
#> Created symlink from /etc/systemd/system/multi-user.target.wants/kestrel-skincv.service to /etc/systemd/system/kestrel-skincv.service.
[root@localhost ~]# systemctl start kestrel-{Your_Project_Name}.service
[root@localhost ~]# systemctl status kestrel-{Your_Project_Name}.service
#***Output:***
#> ● kestrel-skincv.service - ASP.NET Core Application running on CentOS 7
#>    Loaded: loaded (/etc/systemd/system/kestrel-skincv.service; enabled; vendor preset: disabled)
#>    Active: active (running) since 一 2017-07-17 20:05:30 HKT; 20h ago
#>  Main PID: 19633 (dotnet)
#>    CGroup: /system.slice/kestrel-skincv.service
#>            └─19633 /usr/local/bin/dotnet /var/aspnetcore/skincv/SkinCV.dll

若出現Fail訊息,我估計有部份人會出現錯誤訊息。
[root@localhost ~]# systemctl status kestrel-hellomvc.service
#***Output:***
#localhost.localdomain systemd[1]: [/etc/systemd/system/kestrel-hellomvc.service:8]
#Failed to parse usec_t value, ignoring: 10 #Restart service after 10 seconds if dotnet service crashes
你可以試一試把"#Restart service after 10 seconds if dotnet service crashes"這行comment刪除,並完整清除空白字元再試試。

另外想要reload service,以下的command你應該會用到,次序不分先後,大家可自行上網查查用途。
systemctl reset-failed
systemctl daemon-reexec
systemctl daemon-reload
sudo systemctl restart httpd
sudo systemctl enable httpd
systemctl disable kestrel-hellomvc.service
systemctl enable kestrel-hellomvc.service
systemctl start kestrel-hellomvc.service
systemctl status kestrel-hellomvc.service
Reference:
systemctl status shows inactive dead
How to remove systemd services

最後這個感動人心的時候到了,在瀏覽器輸入Server IP或localhost應該就會出現ASP.NET Core頁面了,Yeah~!

沒有留言:

發佈留言