使用容器進行 .NET 開發

先決條件

完成 容器化 .NET 應用程式.

概述

在本節中,你將學習如何為你的容器化應用程式設定開發環境。這包括

  • 新增本地資料庫並持久化資料
  • 配置 Compose 在你編輯並儲存程式碼時自動更新正在執行的 Compose 服務
  • 建立一個包含 .NET Core SDK 工具和依賴項的開發容器

更新應用程式

本節使用 docker-dotnet-sample 儲存庫的不同分支,其中包含更新的 .NET 應用程式。更新的應用程式位於你在 容器化 .NET 應用程式 中克隆的儲存庫的 add-db 分支上。

要獲取更新的程式碼,你需要檢出 add-db 分支。對於你在 容器化 .NET 應用程式 中所做的更改,對於本節,你可以將它們隱藏起來。在終端中,在 docker-dotnet-sample 目錄中執行以下命令。

  1. 隱藏任何之前的更改。

    $ git stash -u
    
  2. 檢出包含更新的應用程式的新分支。

    $ 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:80
    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->80/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 應用程式,其中顯示文字“學生姓名是鯨魚莫比”。

在終端中按 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:80
    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.cshmtl 的更改,然後等待幾秒鐘讓應用程式重新構建。重新整理瀏覽器中的 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:6.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:6.0-alpine AS development
COPY . /source
WORKDIR /source/src
CMD dotnet run --no-launch-profile

FROM mcr.microsoft.com/dotnet/aspnet:6.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:80
    depends_on:
      db:
        condition: service_healthy
    develop:
      watch:
        - action: rebuild
          path: .
    environment:
       - ASPNETCORE_ENVIRONMENT=Development
       - ASPNETCORE_URLS=http://+:80'
  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:6.0-alpine` 映象,其中包含 `dotnet test` 等開發工具。繼續下一節,瞭解如何執行 `dotnet test`。

總結

在本節中,您瞭解瞭如何設定 Compose 檔案以新增本地資料庫並持久化資料。您還學習瞭如何使用 Compose Watch 在您更新程式碼時自動重建和執行容器。最後,您學習瞭如何建立包含開發所需 SDK 工具和依賴項的開發容器。

相關資訊

下一步

在下一節中,您將學習如何使用 Docker 執行單元測試。