使用容器進行 .NET 開發
先決條件
概述
在本節中,您將學習如何為容器化應用程式設定開發環境。這包括
- 新增本地資料庫並持久化資料
- 配置 Compose 在您編輯和儲存程式碼時自動更新正在執行的 Compose 服務
- 建立一個包含 .NET Core SDK 工具和依賴項的開發容器
更新應用程式
本節使用 `docker-dotnet-sample` 倉庫中的不同分支,該分支包含一個更新的 .NET 應用程式。更新後的應用程式位於你在容器化 .NET 應用程式中克隆的倉庫的 `add-db` 分支上。
要獲取更新後的程式碼,你需要檢出 `add-db` 分支。對於你在容器化 .NET 應用程式中所做的更改,本節中你可以將它們暫存起來。在終端中,在 `docker-dotnet-sample` 目錄下執行以下命令。
暫存所有之前的更改。
$ git stash -u
檢出包含更新應用程式的新分支。
$ git checkout add-db
在 `add-db` 分支中,只有 .NET 應用程式已更新。Docker 資產尚未更新。
現在你的 `docker-dotnet-sample` 目錄中應該包含以下內容。
├── docker-dotnet-sample/
│ ├── .git/
│ ├── src/
│ │ ├── Data/
│ │ ├── Models/
│ │ ├── Pages/
│ │ ├── Properties/
│ │ ├── wwwroot/
│ │ ├── appsettings.Development.json
│ │ ├── appsettings.json
│ │ ├── myWebApp.csproj
│ │ └── Program.cs
│ ├── tests/
│ │ ├── tests.csproj
│ │ ├── UnitTest1.cs
│ │ └── Usings.cs
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── Dockerfile
│ ├── README.Docker.md
│ └── README.md
新增本地資料庫並持久化資料
您可以使用容器設定本地服務,例如資料庫。在本節中,您將更新 compose.yaml
檔案以定義資料庫服務和用於持久化資料的卷。
在 IDE 或文字編輯器中開啟 `compose.yaml` 檔案。你會注意到它已經包含了用於 PostgreSQL 資料庫和卷的註釋掉的指令。
在 IDE 或文字編輯器中開啟 `docker-dotnet-sample/src/appsettings.json`。你會注意到其中包含所有資料庫資訊的連線字串。`compose.yaml` 檔案中已經包含了這些資訊,但已被註釋掉。請取消註釋 `compose.yaml` 檔案中的資料庫指令。
以下是更新後的 `compose.yaml` 檔案。
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
db:
image: postgres
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
注意要了解有關 Compose 檔案中指令的更多資訊,請參閱Compose 檔案參考。
在使用 Compose 執行應用程式之前,請注意此 Compose 檔案使用了 `secrets` 並指定了一個 `password.txt` 檔案來儲存資料庫的密碼。你必須建立此檔案,因為它未包含在原始碼倉庫中。
在 `docker-dotnet-sample` 目錄中,建立一個名為 `db` 的新目錄,並在該目錄中建立一個名為 `password.txt` 的檔案。在 IDE 或文字編輯器中開啟 `password.txt` 並新增以下密碼。密碼必須在單行上,檔案中不能有額外行。
example
儲存並關閉 `password.txt` 檔案。
現在你的 `docker-dotnet-sample` 目錄中應該包含以下內容。
├── docker-dotnet-sample/
│ ├── .git/
│ ├── db/
│ │ └── password.txt
│ ├── src/
│ ├── tests/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── Dockerfile
│ ├── README.Docker.md
│ └── README.md
執行以下命令以啟動您的應用程式。
$ docker compose up --build
開啟瀏覽器並在 https://:8080 檢視應用程式。你應該會看到一個簡單的 Web 應用程式,其中包含文字“學生姓名是”。
由於資料庫為空,應用程式不顯示姓名。對於此應用程式,你需要訪問資料庫然後新增記錄。
向資料庫新增記錄
對於示例應用程式,你必須直接訪問資料庫以建立示例記錄。
你可以使用 `docker exec` 命令在資料庫容器內執行命令。在執行該命令之前,你必須獲取資料庫容器的 ID。開啟一個新的終端視窗並執行以下命令以列出所有正在執行的容器。
$ docker container ls
您應該會看到類似以下的輸出。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb36e310aa7e docker-dotnet-server "dotnet myWebApp.dll" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-dotnet-server-1
39fdcf0aff7b postgres "docker-entrypoint.s…" About a minute ago Up About a minute (healthy) 5432/tcp docker-dotnet-db-1
在前面的示例中,容器 ID 是 `39fdcf0aff7b`。執行以下命令連線到容器中的 postgres 資料庫。將容器 ID 替換為你自己的容器 ID。
$ docker exec -it 39fdcf0aff7b psql -d example -U postgres
最後,向資料庫插入一條記錄。
example=# INSERT INTO "Students" ("ID", "LastName", "FirstMidName", "EnrollmentDate") VALUES (DEFAULT, 'Whale', 'Moby', '2013-03-20');
您應該會看到類似以下的輸出。
INSERT 0 1
透過執行 `exit` 關閉資料庫連線並退出容器 shell。
example=# exit
驗證資料是否在資料庫中持久化
開啟瀏覽器並在 https://:8080 檢視應用程式。你應該會看到一個簡單的 Web 應用程式,其中包含文字 `學生姓名是 Whale Moby`。
在終端中按 ctrl+c
停止您的應用程式。
在終端中,執行 `docker compose rm` 刪除你的容器,然後再次執行 `docker compose up` 執行你的應用程式。
$ docker compose rm
$ docker compose up --build
在瀏覽器中重新整理 https://:8080 並驗證學生姓名是否持久化,即使在容器被移除並再次執行之後。
在終端中按 ctrl+c
停止您的應用程式。
自動更新服務
使用 Compose Watch 在您編輯和儲存程式碼時自動更新正在執行的 Compose 服務。有關 Compose Watch 的更多詳細資訊,請參閱使用 Compose Watch。
在 IDE 或文字編輯器中開啟 `compose.yaml` 檔案,然後新增 Compose Watch 指令。以下是更新後的 `compose.yaml` 檔案。
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: rebuild
path: .
db:
image: postgres
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
執行以下命令,使用 Compose Watch 執行您的應用程式。
$ docker compose watch
開啟瀏覽器並驗證應用程式正在 https://:8080 執行。
您對本地機器上應用程式原始檔的任何更改現在將立即反映在執行中的容器中。
在 IDE 或文字編輯器中開啟 `docker-dotnet-sample/src/Pages/Index.cshtml`,並將第 13 行的學生姓名文字從 `Student name is` 更新為 `Student name:`。
- <p>Student Name is @Model.StudentName</p>
+ <p>Student name: @Model.StudentName</p>
儲存對 `Index.cshtml` 的更改,然後等待幾秒鐘,直到應用程式重新構建。在瀏覽器中重新整理 https://:8080,並驗證更新後的文字是否出現。
在終端中按 ctrl+c
停止您的應用程式。
建立開發容器
此時,當你執行容器化應用程式時,它使用的是 .NET 執行時映象。雖然這個小映象適用於生產環境,但它缺少開發時可能需要的 SDK 工具和依賴項。此外,在開發過程中,你可能不需要執行 `dotnet publish`。你可以使用多階段構建在同一個 Dockerfile 中為開發和生產構建階段。有關更多詳細資訊,請參閱多階段構建。
向你的 Dockerfile 新增一個新的開發階段,並更新你的 `compose.yaml` 檔案以將此階段用於本地開發。
以下是更新後的 Dockerfile。
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
ARG TARGETARCH
COPY . /source
WORKDIR /source/src
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final
WORKDIR /app
COPY --from=build /app .
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
USER appuser
ENTRYPOINT ["dotnet", "myWebApp.dll"]
以下是更新後的 `compose.yaml` 檔案。
services:
server:
build:
context: .
target: development
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: rebuild
path: .
environment:
- ASPNETCORE_ENVIRONMENT=Development
db:
image: postgres
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txt
您的容器化應用程式現在將使用 `mcr.microsoft.com/dotnet/sdk:8.0-alpine` 映象,其中包括 `dotnet test` 等開發工具。繼續閱讀下一節,瞭解如何執行 `dotnet test`。
摘要
在本節中,我們研究瞭如何設定 Compose 檔案以新增本地資料庫並持久化資料。您還學習瞭如何使用 Compose Watch 在程式碼更新時自動重建和執行容器。最後,您學習瞭如何建立包含開發所需的 SDK 工具和依賴項的開發容器。
相關資訊
後續步驟
在下一節中,您將學習如何使用 Docker 執行單元測試。