Try   HackMD
tags: Docker, .NET Core 3.1, Synology, MVC

在 Synology NAS 的 Docker 環境中部署 .NET Core 3.1 應用程式

本文由 Grok AI 協助編輯

本文介紹如何在 Synology NAS 的 Docker 環境中部署 .NET Core 3.1 應用程式,並以 Visual Studio 產生的簡單範例網頁為例,展示從專案建立、開發到最終部署的完整流程。本文旨在幫助讀者理解基本的 ASP.NET Core 應用程式部署流程,無需涉及複雜的自訂功能。



實驗環境

  • NAS: RS3614RPxs, DS720P
  • DSM: 6.2.4-25556 Update 2
  • Windows 開發環境: .NET Core 3.1 SDK, Visual Studio 2019

第一部分:建立新專案

步驟 1:安裝必要工具

  1. 下載並安裝 Visual Studio 2019:從 官方網站 下載 Community、Professional 或 Enterprise 版本。
  2. 選擇工作負載:在安裝過程中,勾選「ASP.NET 和 Web 開發」工作負載,確保包含 .NET Core 3.1 的支援。
  3. 驗證 .NET Core 3.1 SDK:安裝完成後,打開命令提示字元,輸入以下命令確認 SDK 已安裝:
    ​​​dotnet --list-sdks
    
    應顯示 3.1.xxx 的版本號。若未顯示,請從 官方網站 下載並安裝。

步驟 2:建立新專案

  1. 打開 Visual Studio 2019,點擊「建立新專案」。
  2. 在搜尋框中輸入「ASP.NET Core Web」,選擇「ASP.NET Core Web 應用程式」,然後點擊「下一步」。
  3. 配置專案:
    • 專案名稱:輸入 SimpleWeb
    • 位置:選擇儲存路徑,例如 D:\NewProjects\
    • 解決方案名稱:保持預設或自訂。
  4. 在下一個畫面中:
    • 框架:選擇 .NET Core 3.1
    • 專案類型:選擇「Web 應用程式(模型-視圖-控制器)」,這將建立一個基於 MVC 架構的應用程式。
    • 取消勾選「啟用 Docker 支援」(因為我們將在後續步驟手動配置 Docker)。
  5. 點擊「建立」,Visual Studio 將生成一個基本的 MVC 專案。

步驟 3:專案初始結構

建立完成後,專案結構如下:

SimpleWeb/
├── Controllers/
│   └── HomeController.cs
├── Models/
│   └── ErrorViewModel.cs
├── Views/
│   ├── Home/
│   │   ├── Index.cshtml
│   │   ├── Privacy.cshtml
│   ├── Shared/
│   │   ├── _Layout.cshtml
│   │   ├── Error.cshtml
├── wwwroot/
│   ├── css/
│   │   └── site.css
│   ├── js/
│   │   └── site.js
│   ├── lib/
│   │   ├── bootstrap/
│   │   ├── jquery/
│   │   ├── jquery-validation/
├── appsettings.json
├── Program.cs
├── Startup.cs
├── SimpleWeb.csproj

這是 ASP.NET Core MVC 的標準結構,提供了一個簡單的首頁(Index)和隱私頁面(Privacy),由 HomeController 控制。此結構是 ASP.NET Core MVC 的預設模板,後續將用於展示基本的部署流程。


第二部分:MVC 架構介紹

ASP.NET Core 使用 MVC(Model-View-Controller) 架構,這是一種常見的設計模式,用於分離應用程式的業務邏輯、資料處理和使用者介面。以下是 MVC 的核心組成部分:

  1. 模型(Model)

    • 負責資料的定義與處理,例如資料庫實體或業務物件。
    • 在此範例中,ErrorViewModel.cs 是預設模型,用於處理錯誤頁面資料。
  2. 視圖(View)

    • 負責顯示資料給使用者,通常是 HTML 與 Razor 語法的結合。
    • 例如,Views/Home/Index.cshtml 是首頁,Views/Home/Privacy.cshtml 是隱私頁面。
  3. 控制器(Controller)

    • 負責處理使用者請求,與模型交互,並返回適當的視圖。
    • 例如,HomeController.cs 處理對 //Privacy 的請求。

MVC 工作流程

  • 使用者發送請求(例如訪問 /)。
  • 控制器(HomeController)接收請求,調用對應動作(Index)。
  • 動作返回視圖(Index.cshtml),視圖渲染成 HTML 返回給使用者。

這種分層設計提高了代碼的可維護性和可測試性,是 ASP.NET Core 的核心特性之一。在此範例中,MVC 實現了基本的頁面導航功能。


第三部分:應用程式概述

此範例應用程式是 Visual Studio 自動生成的預設 MVC 專案,包含以下功能:

  • 首頁:由 HomeControllerIndex 動作提供,顯示歡迎訊息。
  • 隱私頁面:由 HomeControllerPrivacy 動作提供,展示簡單的隱私聲明。
  • 錯誤頁面:由 ErrorViewModelError.cshtml 支援,用於顯示異常資訊。

此應用程式不涉及資料庫或其他複雜邏輯,僅作為展示部署流程的基礎範例。

檔案結構

以下是應用程式的核心檔案結構:

SimpleWeb/
├── Controllers/
│   ├── HomeController.cs         // 首頁與隱私頁控制器
├── Models/
│   ├── ErrorViewModel.cs         // 錯誤頁面模型
├── Views/
│   ├── Home/
│   │   ├── Index.cshtml          // 首頁
│   │   ├── Privacy.cshtml        // 隱私頁面
│   ├── Shared/
│   │   ├── _Layout.cshtml        // 共用佈局
│   │   ├── Error.cshtml          // 錯誤頁面
├── wwwroot/
│   ├── css/
│   │   └── site.css              // 自訂樣式
│   ├── js/
│   │   └── site.js               // 自訂腳本
│   ├── lib/
│   │   ├── bootstrap/            // Bootstrap 框架
│   │   ├── jquery/               // jQuery 庫
│   │   ├── jquery-validation/    // 表單驗證
├── appsettings.json              // 應用程式配置
├── Program.cs                    // 程式進入點
├── Startup.cs                    // 服務與中介軟體配置
├── SimpleWeb.csproj              // 專案檔案

此結構展示了預設應用程式如何利用 MVC 提供簡單的網頁功能。


第四部分:Dockerfile 建構

為了在 Synology NAS 的 Docker 環境中運行此應用程式,我們需要創建一個適配 .NET Core 3.1 的 Docker 映像。以下是範例的 Dockerfile

FROM  FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80

# 設置時區
ENV TZ=Asia/Taipei
RUN apt-get update && apt-get install -y tzdata
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# (選用) 安裝 Oracle 客戶端依賴
RUN apt-get install -y libaio1

# (選用) 設置 Oracle 語言環境
ENV NLS_LANG=AMERICAN_AMERICA.AL32UTF8

# 預設命令(啟動時等待外部應用程式檔案)
ENTRYPOINT ["dotnet"]

Dockerfile 說明

  1. 基礎映像:使用 mcr.microsoft.com/dotnet/aspnet:3.1,包含 .NET Core 3.1 運行時。
  2. 工作目錄:設置為 /app,應用程式檔案將被複製到此目錄。
  3. 端口暴露:暴露 80 端口作為預設監聽端口。
  4. 時區配置:設置為 Asia/Taipei,確保容器時間與本地一致。
  5. (選用) 安裝 Oracle Client:若後續需連接 Oracle 資料庫,則需安裝此項目。
  6. 進入點:使用 dotnet 命令啟動應用程式,具體 DLL 檔案在部署時指定。

建構映像

我們將透過 Windows 建立建構腳本,並在 Synology NAS 上使用 DSM 工作排程器執行映像建構。

步驟 1:編寫建構腳本

  1. 在 Windows 上使用文字編輯器(例如記事本或 VS Code)建立一個名為 build.sh 的檔案,內容如下:
    ​​​#!/bin/bash
    ​​​cd /volume1/docker/dotnet-runtime/
    ​​​docker build -t dotnet-runtime:3.1 .
    
  2. 儲存檔案後,將其上傳至 Synology NAS 的路徑 /volume1/docker/dotnet-runtime/。您可以使用 DSM 的「檔案站」或 FTP 工具完成上傳。
  3. 確保 build.shDockerfile 皆存在 /volume1/docker/dotnet-runtime/ 目錄下。

步驟 2:配置 Task Scheduler

  1. 打開 Synology DSM,進入「控制面板 > 工作排程器」。
  2. 點擊「新增 > 觸發任務 > 使用者定義指令碼」。
  3. 設定以下參數:
    • 一般 > 任務名稱Build Dotnet Runtime
    • 一般 > 使用者帳號root
    • 一般 > 事件開機(此設定僅為範例,實際可根據需求調整為其他觸發條件)
    • 一般 > 已啟動不勾選
    • 任務設定 > 執行命令sh /volume1/docker/dotnet-runtime/build.sh
  4. 點擊「確定」保存任務。
  5. 在任務列表中,找到 Build Dotnet Runtime,右鍵點擊並選擇「執行」以立即建構映像。
  6. 執行成功後,任務即可刪除;或保留但請取消勾選「已啟動」以避免開機自動執行。

步驟 3:驗證映像

建構完成後,進入 DSM 的「Docker」套件,在「映像」標籤中檢查是否出現 dotnet-runtime:3.1。若成功,則映像已準備好用於部署。


第五部分:部署流程

步驟 1:發佈應用程式

在 Visual Studio 中:

  1. 右鍵點擊 SimpleWeb 專案,選擇「發佈」。
  2. 選擇「資料夾」作為目標,設置輸出路徑為 ./publish
  3. 點擊「發佈」,生成應用程式檔案。

或者,使用以下命令直接將應用程式發佈到 NAS 的共享路徑(假設已映射網路磁碟機):

dotnet publish -c Release -r linux-x64 -f netcoreapp3.1 --self-contained false -o "\\172.19.48.55\docker\SimpleWeb"

指令說明

  • -c Release:以 Release 配置編譯,優化性能。
  • -r linux-x64:指定運行時為 Linux 64 位,適配 Synology NAS 的 Docker 環境。
  • -f netcoreapp3.1:指定框架為 .NET Core 3.1。
  • --self-contained false:不包含 .NET Core 運行時,依賴容器中的運行時。
  • -o "\\172.19.48.55\docker\SimpleWeb":將發佈檔案直接輸出到 NAS 的共享資料夾(IP 為 172.19.48.55)。

步驟 2:將發佈檔案傳輸到 NAS

若未使用上述命令直接發佈,則需手動將 ./publish 目錄中的檔案複製到 NAS 的卷冊路徑,例如 /volume1/docker/mywebapp/。若 NAS 未設置共享路徑映射,請使用 DSM 的「檔案站」手動上傳。若已使用 dotnet publish 命令,則無需手動傳輸,因為檔案已直接發佈至 NAS 的共享路徑 \\172.19.48.55\docker\SimpleWeb,對應 NAS 的 /volume1/docker/mywebapp/(假設共享路徑已正確映射)。

步驟 3:使用 Synology NAS GUI 啟動容器

  1. 打開 Synology DSM,進入「Docker」套件。
  2. 在「映像」標籤中,若映像已在 NAS 上建構完成,可直接選擇 dotnet-runtime:3.1;否則點擊「新增」 > 「從檔案新增」,選擇本機的 dotnet-runtime:3.1 映像。
  3. 在「容器」標籤中,點擊「建立」:
    • 映像:選擇 dotnet-runtime:3.1
    • 容器名稱:自訂,例如 simpleweb-container
    • 進階設定
      • 端口設定:本地端口設為 62005,容器端口設為 5000
      • 卷冊:本地路徑設為 /volume1/docker/mywebapp/,容器路徑設為 /app
      • 命令:在「執行命令」中輸入 dotnet /app/SimpleWeb.dll
  4. 點擊「套用」啟動容器。

步驟 4:驗證部署

在瀏覽器中輸入 http://<NAS_IP>:62005,確認應用程式正常運行並顯示預設的 ASP.NET Core 首頁。若需測試隱私頁面,可導航至 /Privacy


第六部分:修復常見問題

在部署過程中,可能遇到靜態檔案(如 CSS)無法載入的問題。以下是解決方案:

  1. 修改內容根路徑

    • 編輯 Program.cs,修改如下:
      ​​​​​public static IHostBuilder CreateHostBuilder(string[] args) =>
      ​​​​​    Host.CreateDefaultBuilder(args)
      ​​​​​        .ConfigureWebHostDefaults(webBuilder =>
      ​​​​​        {
      ​​​​​            webBuilder.UseContentRoot("/app"); // 明確指定內容根
      ​​​​​            webBuilder.UseStartup<Startup>();
      ​​​​​        });
      
    • Startup.csConfigure 方法中確認:
      ​​​​​public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      ​​​​​{
      ​​​​​    app.UseStaticFiles();
      ​​​​​    app.UseRouting();
      ​​​​​    app.UseEndpoints(endpoints =>
      ​​​​​    {
      ​​​​​        endpoints.MapControllerRoute(
      ​​​​​            name: "default",
      ​​​​​            pattern: "{controller=Home}/{action=Index}/{id?}");
      ​​​​​    });
      ​​​​​}
      
  2. 重新發佈與部署

    • 重新執行:
      ​​​​​dotnet publish -c Release -r linux-x64 -f netcoreapp3.1 --self-contained false -o "./publish"
      
    • 上傳到 /volume1/docker/mywebapp/,重啟容器。

注意事項

  1. 連線字串配置:此範例不涉及資料庫,因此無需配置連線字串。若需擴展功能,請參閱後續文章。
  2. 網路設定:確保 NAS 的防火牆和 Docker 網路允許 62005 端口的外部訪問。
  3. 端口衝突:Dockerfile 暴露 80 端口,但映射到 5000。若應用程式監聽端口不符,請在 Program.csappsettings.json 中調整,例如設置 ASPNETCORE_URLS=http://+:5000

結論

這篇文章展示了一個簡單的 .NET Core 3.1 MVC 應用程式從建立到部署至 Synology NAS Docker 環境的完整流程。讀者可基於此範例,進一步擴展應用程式功能,例如加入資料庫支援(將在下一篇文章中介紹)。