# Deploy .NetCore in Docker on Synology NAS
###### tags: `Deploy` `Docker` `NAS`
:::info
本篇主要以執行 .NET 5(.NETCore 5)為主。
:::
先到NAS上的套件中心搜尋docker並安裝

安裝好後會多一個docker共享資料夾,稍後會使用到

## Deploy .NET 5 in Docker on NAS 方法1
倉庫伺服器預設已經有Docker Hub

但是搜尋aspnet dotnet netcore 等關鍵字找到的是舊版或是 .NET Framework用的

新版 .NET 5 (包含 .NET Core 2.1 and 3.1)的官方Runtime docker image應為(https://hub.docker.com/_/microsoft-dotnet-aspnet)
因搜尋不到,可使用指令抓下來
```
docker pull mcr.microsoft.com/dotnet/aspnet
```
先確定NAS有開啟SSH功能

SSH登入NAS(不需要中括號),enter後會要你輸入密碼(不會顯示)
```
ssh [username]@[192.168.1.X]
```

直接輸入上面指令抓docker image會出現以下錯誤

因為權限不夠,所以直接在前面加上`sudo`

成功後,回到NAS上Docker的介面可以看到剛剛pull下來的image

選取後按左上方"佈屬"按鈕建立Container。"佈屬"相當於`docker bulid`的指令
建Container前,先把專案編譯後的檔案放到`<NAS>/docker/dotnet-aspnet`資料夾下
"dotnet-aspnet"為自行命名,稍後我的Container也會使用此名稱

Container名稱可自行命名

進入進階設定
儲存空間頁籤部分點選新增資料夾,選擇剛剛放檔案的資料夾`<NAS>/docker/dotnet-aspnet`,掛載路徑直接寫`/home`(其他地方也可以)

連接埠設定是埠號對應
因為預設網頁是80,這邊先不改所以容器連接埠填上80,本機自行配置決定,等等連到網頁就是要使用本機連接埠

環境設定部分基本上不用改,~~下半部Entrypoint指令填上`dotnet home/[專案名稱].dll`
這是在Container啟動後會執行的指令~~
:::danger
此方法可以起Server但會造成Uri解析錯誤,這是dotnet問題,應該要`dotnet ShopifyAccess.dll`
~~但因為此docker image的WORKDIR不是我們設定的`/home`~~ **2021-05-25更新:此方法一已經設定WORKDIR為/app,所以上面掛載路徑直接設成/app就可,執行指令直接`dotnet [專案名稱].dll`即可。建議以Shell Script處理**,~~所以要用方法2的方式建立docker image~~ **2021-05-20更新:可使用Shell Script解決此問題,請接續參照下方綠框**
>建立檔名為"Dockerfile"且無副檔名的檔案,內容如下(此部分不需要`COPY . /app`):
>```dockerfile=
>FROM mcr.microsoft.com/dotnet/aspnet:latest
>WORKDIR /app
>
>ENV ASPNETCORE_URLS http://*:80
>EXPOSE 80
>
>ENTRYPOINT ["dotnet", "ShopifyAccess.dll"]
>```

套用後會出現檢視畫面,再按一次套用即完成

這時可以看到"容器"頁面多出來剛建的Container
選擇並點擊詳細資訊

在程式頁籤可以看到程式已經啟動了

日誌則有dotnet執行log

最後在網址列上輸入該台NAS ip:port就可以開啟網頁了
:::
:::success
**Shell Script啟動.NetCore專案** (此部分以專案名稱"dotnet-aspnet-BarcodeLabel"表示)
因為要使用Shell Script啟動,先準備好檔案。
```shell=
echo 'start to run Ivan7DB.dll'
cd ./home
dotnet Ivan7DB.dll
```
我將檔案存到`<NAS>/docker/entry/[dotnet-aspnet-BarcodeLabel]/entry.sh`,到時候可以找到就好。
接著在儲存空間設定,除了原先設定的專案資料夾之外,也需要把剛剛的entry.sh掛載進去

環境設定底下,指令輸入`bash /home/entry.sh`啟動時直接執行剛新增的shell script;以此方式避免直接以`dotnet /path/xxx.dll`的方式執行指令。

Shell Script 內容自行調整,因為執行entry.sh檔案時,路徑從最上層開始,所以需要先change directory(`cd`)到home資料夾(專案放置位置),再執行`dotnet xxx.dll`
:::
## Deploy .NET 5 in Docker on NAS 方法2
把專案編譯後的檔案放到`<NAS>/docker/ShopifyAccess`資料夾下
"ShopifyAccess"為自行命名,稍後我的Container也會使用此名稱
建立檔名為"Dockerfile"且無副檔名的檔案,內容如下:
```dockerfile=
FROM mcr.microsoft.com/dotnet/aspnet:latest
COPY . /app
WORKDIR /app
ENV ASPNETCORE_URLS http://*:80
EXPOSE 80
ENTRYPOINT ["dotnet", "ShopifyAccess.dll"]
```
其中FROM 使用到上面提到過的新版 .NET 5 (包含 .NET Core 2.1 and 3.1)的官方Runtime docker image
`COPY`複製資料夾檔案至`/app資料夾`
`WORKDIR`設定工作目錄為`/app`
`ENTRYPOINT` 直接設定 `["dotnet", "ShopifyAccess.dll"]`
:::info
`ENTRYPOINT ["dotnet", "ShopifyAccess.dll"]`與`ENTRYPOINT dotnet ShopifyAccess.dll`
寫法上的差異
- `ENTRYPOINT ["dotnet", "ShopifyAccess.dll"]`


- `ENTRYPOINT dotnet ShopifyAccess.dll`


:::
將這個Dockerfile放到`<NAS>/docker/ShopifyAccess`資料夾下

SSH登入NAS後到`<NAS>/docker/ShopifyAccess`資料夾下

輸入`docker build -t dotnet-aspnet-shopifyaccess .`建立image
:::warning
注意最後有一個點`.`
:::

因為權限不夠,所以直接在前面加上`sudo`

即可在NAS Docker介面看到建立的image

直接點選"佈署"→"進階設定"後
只要設定本機連接埠
套用並啟動Container即可

## 方法1/方法2
第一種是將NAS上資料夾檔案掛載進Container內;第二種是複製官方Runtime docker image並將程式檔案包起來成為新的image,可以發現資料大小有差。
第一種的不能將NAS上檔案刪除,第二種可以,但程式有更新就需要重新包裝docker image