系列導航及源代碼
- 使用.NET 6開發TodoList應用文章索引
需求
.NET 6 Web API應用使用最多的場景是作為后端微服務應用,在實際的專案中,我們一般都是通過將應用程式打包成docker鏡像進行發布,以便更好地進行部署,包括基于Kubernetes平臺的微服務專案部署,
一般來說作為微服務部署的應用程式,都是位于某個虛擬子網下的,也就是說它們不直接暴露給外部用戶,請求都是走的內部網路,所以很少會有HTTPS的需求,但是作為演示,在本文中我們還是會介紹如何實作HTTPS訪問docker中的應用程式,
目標
實作應用程式的docker鏡像打包運行,包括實作基于HTTPS的訪問,
原理與思路
應用程式docker鏡像打包的實作思路很簡單,準備一個正確的dockerfile,再根據需要進行HTTPS配置,最后正確構建鏡像就可以了,
實作
實作Docker鏡像打包
在Api專案中新建dockerfile檔案,一般我們構建應用程式都是通過兩步構建:第一步進行編譯發布,第二步將發布的檔案拷貝到運行時環境中,這樣可以減少鏡像的大小,
如果你是使用Visual Studio或者Rider開發專案,可以在創建專案的時候就將是否使用Docker支持選上,選擇容器環境為Linux即可,專案模版會為我們自動生成正確的Dockerfile,或者我們也可以在專案上右擊,選擇添加Docker支持,
下面是我們手寫的dockerfile的檔案內容,對于撰寫dockerfile經驗不多的小伙伴來說,最容易出錯的地方就是路徑的問題,因為我們將dockefile檔案生成在了Api專案中了,所以單從檔案內容里的路徑來看,是有問題的,但是不要緊,我們在打包鏡像的時候可以指定dockefile檔案執行的背景關系,只要在解決方案目錄下執行docker build就沒問題了,
ARG NET_IMAGE=6.0-bullseye-slim
FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
ENV ASPNETCORE_ENVIRONMENT=Development
FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build
WORKDIR /src
COPY ["src/TodoList.Api/TodoList.Api.csproj", "TodoList.Api/"]
COPY ["src/TodoList.Application/TodoList.Application.csproj", "TodoList.Application/"]
COPY ["src/TodoList.Domain/TodoList.Domain.csproj", "TodoList.Domain/"]
COPY ["src/TodoList.Infrastructure/TodoList.Infrastructure.csproj", "TodoList.Infrastructure/"]
RUN dotnet restore "TodoList.Api/TodoList.Api.csproj"
COPY ./src .
WORKDIR "/src/TodoList.Api"
RUN dotnet build "TodoList.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish --no-restore "TodoList.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TodoList.Api.dll"]
在構建鏡像之前,有幾個小坑需要注意一下:
- 暫時洗掉
Program中的UseHttpsRedirection中間件,因為我們還沒有配置HTTPS證書; - 在
Api專案的csproj檔案中,將TodoList.Api.xml檔案在Debug模式下的配置復制到Release中,否則會報錯Could not find file '/app/TodoList.Api.xml; - 修改對應appsettings.{env}.json中的資料庫連接字串,使用docker網路模型獲取其他容器的方式,將localhost改為mssql,這個名字是在本地運行sql server docker的容器名稱,我們將使用docker網路允許應用程式連接到資料庫docker容器,
下面我們就來構建一下這個鏡像,確保位于解決方案目錄下,注意最后那.指明了當前選擇的dockerfile檔案執行的背景關系路徑,即解決方案目錄:
$ docker build -t todo-list -f src/TodoList.Api/Dockerfile .
生成的鏡像:

運行起來,把80埠暴露出來,使用--link引數指出需要將當前應用容器連接到資料庫容器所在的網路,并使用API客戶端去驗證登陸請求:
$ docker run -p 80:80 --name=todo_list_in_docker --link=mssql -d todo-list
4733f35c2c9558b78e3c7b9281536d8891f19bf87b18fa0ad953e94f7b984184

請求認證:

實作HTTPS訪問
接下來我們為容器添加HTTPS支持,為了實作這一點,我們當然還是需要繼續使用UseHttpsRedirection中間件,然后需要添加一個證書,并在啟動容器的時候添加這個證書,
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p Test@Password
dotnet dev-certs https --trust
重新build并運行容器,這次我們使用HTTPS的5001埠去訪問容器中的API,需要將HTTPS容器內的443埠暴露到host上的埠(我選擇的是5001埠)并制定相關的HTTPS的環境變數,證書的指定并將host上保存證書的路徑掛載到容器內可以訪問到,
docker run \
-p 80:80 \
-p 5001:443 \
--name=todo_list_in_docker \
--link=mssql \
-e ASPNETCORE_URLS="https://+;http://+" \
-e ASPNETCORE_HTTPS_PORT=5001 \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="Test@Password" \
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx \
-v ${HOME}/.aspnet/https:/https/ \
-d \
todo-list

增加docker-compose功能
到這里我們發現了一個比較麻煩的地方在于我們需要記住這些配置,并且每次需要手動分別啟動資料庫容器和應用容器,我們完全可以通過docker-compose來完成,所以我們先把應用容器和資料庫容器都停止并洗掉掉,開始在解決方案目錄下新建docker-compose檔案:
version: '3.4'
services:
todo-list:
image: todo-list
# 配置埠轉發
ports:
- "80:80"
- "5001:443"
# 配置容器環境變數
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+;http://+
- ASPNETCORE_HTTPS_PORT=5001
- ASPNETCORE_Kestrel__Certificates__Default__Password=Test@Password
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
# 掛載證書路徑
volumes:
- ~/.aspnet/https:/https:ro
# 需要先啟動資料庫容器
depends_on:
- mssql
# todo-list通過public網路回應請求,通過private網路連接資料庫容器
networks:
- private
- public
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
# 配置埠轉發,這是為從主機直接訪問資料庫需要的,如果沒有從主機直接訪問資料庫的需求,只需要宣告容器埠1433不做轉發即可
ports:
- "1433:1433"
environment:
- SA_PASSWORD=StrongPwd123
- ACCEPT_EULA=Y
# 掛載資料目錄實作持久化
volumes:
- mssqldata:/var/opt/mssql
networks:
- private
- public
# 因為mssqldata路徑之前已經創建了,所以需要在這里宣告使用已有的
volumes:
mssqldata:
networks:
private:
public:
運行起來以后繼續請求認證:
$ docker-compose up --build
Creating network "todolist_private" with the default driver
Creating network "todolist_public" with the default driver
Recreating todolist_mssql_1 ... done
Recreating todolist_todo-list_1 ... done
Attaching to todolist_mssql_1, todolist_todo-list_1
// 省略后面的日志....
請求結果:

到此為止如何使用容器去進行應用程式打包和部署的演示就結束了,關于如何在Kubernetes和CI/CD中應用這些步驟,會在后面將微服務的系列中再次涉及到,
總結
docker打包應用程式比較容易出錯的地方在于dockerfile路徑,除此之外如果在容器中還需要有其他操作比如安裝一些第三方的agent(比如splunk agent),也需要仔細操作,關于如何進行Docker Build的Debug,可以參考其他人寫的文章,例如這篇:Debugging Docker builds,
參考資料
- Hosting ASP.NET Core images with Docker over HTTPS
- Hosting ASP.NET Core images with Docker Compose over HTTPS
- Debugging Docker builds
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/412761.html
標籤:.NET技术
