從 .NET Core 2.1 開始,無論是 .NET Core 或 ASP.NET Core 專案,容器映像全部統一由 Docker Hub 上面的 microsoft/dotnet 專案提供。今天這篇文章,我就來說明如何將一份已經寫好的 ASP.NET Core 2.1 網站專案,透過 Docker 部署到容器中。
取得最新穩定版 Tag 名稱
你在建立容器映像時候,可以記得以下三個 Tag 名稱,這三個 Tag 會永遠指向最新版的 .NET Core 版本,分別是:
- 2.1-sdk
- 內建完整的 .NET Core 2.1 SDK 環境,可以幫助你建置 .NET Core 應用程式。
- 2.1-runtime
- 內建 .NET Core 2.1 Runtime 執行環境。(不含 SDK 工具)
- 內建 Microsoft.NETCore.App 中繼套件與所有相依 NuGet 套件。
- 2.1-aspnetcore-runtime
- 內建 .NET Core 2.1 Runtime 執行環境。(不含 SDK 工具)
- 內建 Microsoft.NETCore.App 中繼套件與所有相依 NuGet 套件。
- 內建 Microsoft.AspNetCore.App 與 Microsoft.AspNetCore.All 中繼套件與所有相依 NuGet 套件。
上述三個 Tag 名稱會連結到各自的 Dockerfile 檔案,建議大家可以先行讀懂內容。
想了解 .NET Core 如何部署到容器中,參考 .NET Core Docker Samples 算是一個不錯的管道,因為有相當完整的範例可參考。
請注意:如果你已經下載過這三個 Tag 的容器映像(Docker Image),預設在執行 docker build
的過程,並不會自動到 Docker Hub 下載最新版本。如果你要更新到最近的穩定版,必須透過 docker pull
重新下載才行!
認識 ASP.NET Core 的 Docker 容器範例
我們可以從 ASP.NET Core Docker Sample 文件中,得知許多建置 Docker 容器映像的範例。我們就從該文章的第一個簡易範例來看,其重點如下:
- 該 Dockerfile 範例使用了 multi-stage builds 建置技巧,並分成兩個步驟執行:
- 先透過
microsoft/dotnet:2.1-sdk
建置 ASP.NET Core 應用程式
- 再透過
microsoft/dotnet:2.1-aspnetcore-runtime
將建置好的 ASP.NET Core 應用程式,封裝進 ASP.NET Core 執行環境容器中。
- 在第一個 stage build 中,又分成兩個步驟:
- 先取得
*.sln
與 *.csproj
檔案,並還原專案中會用到的 NuGet 套件。
- 複製完整的 ASP.NET Core 原始碼到目錄中,並執行
dotnet publish
發布應用程式到 out
資料夾下。
- 在第二個 stage build 中,複製第一個 stage build 的完整發布結果到新的容器中,然後設定
ENTRYPOINT
指定容器的啟動命令。
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY aspnetapp/*.csproj ./aspnetapp/
RUN dotnet restore
# copy everything else and build app
COPY aspnetapp/. ./aspnetapp/
WORKDIR /app/aspnetapp
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapp/out ./
ENTRYPOINT ["dotnet", "aspnetapp.dll"]
完整的實作練習流程如下:
-
取得範例原始碼
git clone https://github.com/dotnet/dotnet-docker.git
cd dotnet-docker/samples/aspnetapp
-
建置 aspnetapp 容器映像
docker build -t aspnetapp .
-
執行自訂的 aspnetapp 容器
docker run -d --name=myapp --rm -p 8000:80 aspnetapp
連到 http://localhost:8000/
就可以看到網頁執行。
-
停止容器
docker stop myapp
這份 ASP.NET Core 容器範例最有趣的地方是,他可以讓你在本機不需要安裝任何 .NET Core SDK 環境,透過預先製作好的 Docker Image 就可以讓你快速的建置與發行專案。這樣的設計,最能展現效益的地方,就是 CI/CD 的過程會非常簡單,完全沒有環境的相依性!
進一步認識 microsoft/dotnet:2.1-aspnetcore-runtime
容器映像
如果深入查看這份 microsoft/dotnet:2.1-aspnetcore-runtime 容器映像,你會發現他的 Base Image 是 microsoft/dotnet:2.1-runtime-deps-stretch-slim,其內容如下:
FROM debian:stretch-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
\
# .NET Core dependencies
libc6 \
libgcc1 \
libgssapi-krb5-2 \
libicu57 \
liblttng-ust0 \
libssl1.0.2 \
libstdc++6 \
zlib1g \
&& rm -rf /var/lib/apt/lists/*
# Configure Kestrel web server to bind to port 80 when present
ENV ASPNETCORE_URLS=http://+:80 \
# Enable detection of running in a container
DOTNET_RUNNING_IN_CONTAINER=true
最後兩行,定義了兩個環境變數,尤其是 ASPNETCORE_URLS
最為重要,這個環境變數決定了你的 ASP.NET Core 應用程式要對外 Listen 哪一個 IP:Ports,這裡的 +
代表的是 Binding 所有的本機 IP 位址,而 80 就代表了只 Listen 埠號 80 (這裡是指容器內的 Port 80)。也因此,我們在執行這個容器時,需要特別加上 -p 8000:80
的關係,這代表著我們容器主機的 8000 Port 會對應到容器中的 80 Port 的意思。
docker run -d -p 8000:80 aspnetapp
如何建立含有 HTTPS 加密連線的 ASP.NET Core 網站容器
我們在建立容器映像的時候,我們都會大量利用「環境變數」來調整容器執行時期的運作邏輯,例如指定 IP:Port,或是設定 TLS/SSL 憑證金鑰等等。如果你想了解如何部署含有 HTTPS 加密連線的 ASP.NET Core 2.1 網站在 Docker 容器中,可以參考 Hosting ASP.NET Core Images with Docker over HTTPS 這份文件下去設定。
如果你在 Windows 環境下使用 Linux 容器,可以參考以下步驟進行測試:
-
先建立開發測試用的自簽憑證
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p crypticpwd
dotnet dev-certs https --trust
-
再透過環境變數指定相關憑證與相關參數
你只要透過指定「環境變數」就可以順利將先前建立建立好的 aspnetapp
容器映像,自動跑成含有 HTTPS 加密連線的 Kestrel 伺服器。
docker run --rm -it -p 8000:80 -p 8001:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=8001 -e ASPNETCORE_Kestrel__Certificates__Default__Password="crypticpwd" -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx -v %USERPROFILE%\.aspnet\https:/https/ aspnetapp
連到 https://localhost:8001/
就可以看到 HTTPS 加密網頁執行。
相關連結