位元詩人 技術雜談:.NET on GNU/Linux

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

在從前,要在 GNU/Linux 下寫 .NET 程式,會使用 Mono 平台。然而,使用 Mono 平台,程式設計師要和大大小小的不相容奮戰,有時候會想乾脆去寫 Java 好了。不過,隨著 .Net 平台開始支援非 Windows 的作業系統,以及 Microsoft 開始協助 Mono 專案,上述的情形應該會逐漸改觀;對於喜歡 C# 的朋友來說,應該也是樂見其成。

註:目前 GNU/Linux 平台上的 .NET 開發環境,已加強了對數個主流發行版的原生環境支援,本文使用 Docker 的方法,僅供參考。

目前 Microsoft 對 .NET 在 GNU/Linux 上的支援有以下數項:

  • .NET Core:終端應用程式
  • ASP.NET Core:網頁應用程式
  • Visual Studio Code:跨平台的程式編輯器

而透過 Mono 在 GNU/Linux 上的支援有以下數項:

  • 終端應用程式
  • GTK#:圖形應用程式
  • ASP.NET:網頁應用程式
  • 函式庫開發
  • MonoDevelop:整合式開發環境

本文會介紹 Microsoft 提供的 .NET 平台。

其中 .Net Core 目前支援終端應用程式,而且,也支援 native binary,也就昰說,我們又多了一個可以開發命令列工具的語言 (灑花)。但是,目前 .Net Core 在 GNU/Linux 安裝不甚方便,只有提供給 Ubuntu 使用的 repo,其他的 GNU/Linux 發行版則要使用 Docker。使用 Docker 的好處是不用處理軟體相依性問題,不過, 透過 Docker container 操作命令列軟體相對較不方便。我們希望 Microsoft 能夠將 .Net 平台像 Java 平台一般,提供方便安裝的 repo,這對於推廣 .NET 平台會更有助益。

而 ASP.NET Core 則是用來執行網頁應用程式。目前可在 Ubuntu、Debian、CentOS 等發行版安裝,然而,安裝過程仍然相對繁複,希望 Microsoft 早日提供懶人包,造福大家。另外,目前 Microsoft 暫時將 .NET Core 和 ASP.NET Core 的開發環境分開,可視需要開發的程式種類自行選擇。不過,筆者倒是覺得使用 Docker 開發 ASP.NET 程式是一個不錯的選擇,因為網頁應用程式是在背景執行,而不太需要在命令列進行互動式操作,Docker 應用程式剛好也可以用背景執行的方式運行。等日後開發完成後,還可以自行撰寫 Dockerfile 將整個程式包裝成 Docker image 的形式。

Visual Studio Code 則是 Microsoft 提供的程式編輯器,功能比較偏向 editor,不過,提供部分類似 IDE 的功能,剛好可以用來撰寫 C# 程式。另外,MonoDevelop 目前不支援新形態的 .NET 和 ASP.NET 專案,可能還是需要用到 VSCode。如果自己有其他習慣的編輯器,也可以搭配 Omnisharp,加強對這些編譯器對 C# 的支援。

安裝 Docker

在開始開發 .NET Core 和 ASP.NET Core 程式前,要先安裝 Docker;安裝 Docker 相當簡單,只要以下列命令列操作即可:

# curl -fsSL https://get.docker.com/ | sh

這個 script 會偵測幾個主流的 GNU/Linux 發行版,並自動呼叫相關的套件管理程式以安裝 Docker。如果使用這個 script 出問題,請參考此處進行手動安裝。

由於 Docker 需要設定權限才能使用,除了使用 root 帳號外,比較好的方式昰將一般使用者加入 docker 群組:

# usermod -aG docker your-user

註:將 your-user 代換成真正的使用者帳號。

.NET Core 環境

安裝完 Docker 後,即可啟動 Docker container,Microsoft 已經幫我們配置好 Docker image,可直接使用。參考以下指令啟動一個 Docker container:

$ docker run -v /path/to/host/dir:/path/to/container/dir -w /path/to/container/dir --rm -it microsoft/dotnet:latest

其中 -v 設置 volume。由於 Docker container 是小型的虛擬機器,如果要和 host 的檔案溝通,要設置 volume,透過設置 volume,我們可以用 host 的軟體編輯 volume 內的專案,再由 container 內的 .NET 環境編譯軟體。-w 是指自動移動到指定的工作目錄。--rm 是指在離開 container 後,自動將 container 清除。-i 是指開啟互動性操作環境,-t 則是配置 TTY,通常 -it 會一起設定。

透過以上指令,Docker 會自動下載 .NET Core 的 image,以及啟動 container;我們就會進入 .NET 環境。會看到類似命令列提示:

root@2309a7144ab8:~#

在 Docker 中,預設都是使用 root 帳號。不過,這個虛擬機器只是給自己使用,也不太需要另創帳號。

Microsoft 指供了一個 dotnet 指令,可用來管理 .NET Core 專案。首先,先建立一個專案:

$ mkdir hello_world
$ cd hello_world
$ dotnet new

然後,安裝相關套件,這會花一些些時間:

$ dotnet restore

然後,執行該專案,會一併編譯及執行程式:

$ dotnet run

也可以編譯成執行檔:

$ dotnet build --native

要注意的是,由於在 container 內是使用 root 帳號,會導致檔案權限不足,無法開啟,要修改權限:

$ chown -R 1000:1000 .

註:根據你原來 host 上實際的使用者帳號的 uid 修改權限。

這裡另外提示一個小技巧,我們可以幫 dotnet 指令新增子命令。建立一個新的 Bash 命令稿,內容如下:

#!/bin/bash

chown -R $1:$1 .

將檔案存成 dotnet-chown,再將檔案轉為系統指令:

$ chmod +x dotnet-chown
$ mv dotnet-chown /usr/local/bin

以後,我們就可以直接呼叫該命令:

$ dotnet chown 1000

還可以新增一個 dotnet-clean 指令。建立 Bash 命令稿,內容如下:

#!/bin/bash

rm -rf bin/ obj/

同樣地,將命令稿轉為系統指令:

$ chmod +x dotnet-clean
$ mv dotnet-clean /usr/local/bin

以後,我們就可以呼叫該命令,清除編譯的檔案:

$ dotnet clean

最後,別忘了將更動過的環境存起來,下次可以直接呼叫。可參考以下指令:

$ docker ps
$ docker commit 2e94c8ef28e2 dotnet

註:請將版本號依實際情形替換。

原來的 microsoft/dotnet image 可以刪除,以節省空間:

$ docker rmi -f microsoft/dotnet

ASP.NET Core 環境

除了用 .NET Core 開發終端機程式,另一個亮點就是 ASP.NET Core,之後,也可以在 GNU/Linux 上開發 ASP 應用程式了。不過,ASP.NET Core 內沒有內建 ASP.NET 專案的工具,Microsoft 另外發布以 Yeoman 為基礎的專案產生工具,這套工具不需使用 Docker,只要支援 Node.js 的環境就可以使用。

請先安裝 Node.js,然後,安裝相關套件:

$ npm install -g yo
$ npm install -g generator-aspnet

之後,使用 Yeoman 產生 ASP.NET 專案:

$ yo aspnet

這是一個互動式的工具,會詢問使用者幾個問題,之後就會建立一個 ASP.NET 專案。

要開發 ASP.NET 程式時,利用 Docker 建立 ASP.NET 的開發環境:

$ docker run -v /path/to/host/dir:/path/to/container/dir -p 5000:5000 -w /path/to/container/dir -it microsoft/aspnet:latest

要注意的是,使用 -p 設定要開放的 port,之後才能從 host 呼叫。同樣地,也要設定 volume,才能從 host 端編輯。

移動到專案所在資料夾:

$ cd /path/to/project/dir

dnu 指令安裝相關套件:

$ dnu restore

要注意的是,由於 Docker container 是一個隔離的環境,要設定非 localhost 的 IP,才能從 host 端開啟。在該專案中建立 hosting.json 檔案,並加入以下內容:

{
    "server.urls": "http://0.0.0.0:5000"
}

然後,用 dnx 指令啟動該 ASP.NET 專案:

$ dnx web

在 host 端,開啟 http://localhost:5000/ ,如果可以看到網頁,即表示成功開啟 ASP.NET 專案。另外,也是可以將更動後的 image 存起來,下次就不用重新調整環境。

待開發完成後,要將程式上線時,可將這些步驟寫成 Dockerfile,將啟動程式的過程自動化。例如,以 ASP.NET 內附的 Dockerfile 為例:

FROM microsoft/aspnet:1.0.0-rc1-update1

RUN printf "deb http://ftp.us.debian.org/debian jessie main\n" >> /etc/apt/sources.list
RUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*

COPY . /app
WORKDIR /app
RUN ["dnu", "restore"]

EXPOSE 5000/tcp
ENTRYPOINT ["dnx", "-p", "project.json", "web"]

然後,再用 Apache 或 Nginx 等網頁伺服器,透過 reverse proxy 的方式呼叫該網頁應用程式即可。

後記

經由 .NET Core 和 ASP.NET Core 等專案,開發者可在 Mac 或 GNU/Linux 上以 C# 開發不同類型的應用程式。目前這些專案仍在早期狀態,能開發的項目相對有限;我們期待 Microsoft 能夠持續耕耘這些專案,讓 C# 能夠像 Java 一樣,成為實質的跨平台程式語言。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。