---
# System prepended metadata

title: 在 Synology NAS 的 Docker 環境中部署 .NET Core 3.1 應用程式
tags: [C#, Synology, MVC, .NET Core 3.1, Docker]

---

###### 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 應用程式部署流程，無需涉及複雜的自訂功能。

---

[toc]

---

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

---

# 第一部分：建立新專案

## 步驟 1：安裝必要工具
1. **下載並安裝 Visual Studio 2019**：從 [官方網站](https://visualstudio.microsoft.com/vs/older-downloads/) 下載 Community、Professional 或 Enterprise 版本。
2. **選擇工作負載**：在安裝過程中，勾選「ASP.NET 和 Web 開發」工作負載，確保包含 .NET Core 3.1 的支援。
3. **驗證 .NET Core 3.1 SDK**：安裝完成後，打開命令提示字元，輸入以下命令確認 SDK 已安裝：
   ```bash
   dotnet --list-sdks
   ```
   應顯示 `3.1.xxx` 的版本號。若未顯示，請從 [官方網站](https://dotnet.microsoft.com/download/dotnet/3.1) 下載並安裝。

## 步驟 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 專案，包含以下功能：
- **首頁**：由 `HomeController` 的 `Index` 動作提供，顯示歡迎訊息。
- **隱私頁面**：由 `HomeController` 的 `Privacy` 動作提供，展示簡單的隱私聲明。
- **錯誤頁面**：由 `ErrorViewModel` 和 `Error.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`：

```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` 的檔案，內容如下：
   ```bash
   #!/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.sh` 與 `Dockerfile` 皆存在 `/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 的共享路徑（假設已映射網路磁碟機）：
```bash
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`，修改如下：
     ```csharp
     public static IHostBuilder CreateHostBuilder(string[] args) =>
         Host.CreateDefaultBuilder(args)
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseContentRoot("/app"); // 明確指定內容根
                 webBuilder.UseStartup<Startup>();
             });
     ```
   - 在 `Startup.cs` 的 `Configure` 方法中確認：
     ```csharp
     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. **重新發佈與部署**：
   - 重新執行：
     ```bash
     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.cs` 或 `appsettings.json` 中調整，例如設置 `ASPNETCORE_URLS=http://+:5000`。

---

# 結論

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

