使用容器進行 .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

開啟瀏覽器並在 http://localhost:8080檢視應用程式。您應該會看到一個簡單的網頁應用程式,其中顯示文字「Student name is」。

應用程式沒有顯示名稱是因為資料庫是空的。對於此應用程式,您需要存取資料庫,然後新增記錄。

新增記錄到資料庫

對於範例應用程式,您必須直接存取資料庫才能建立範例記錄。

您可以使用 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

驗證資料是否保存於資料庫中

開啟瀏覽器並在 http://localhost:8080檢視應用程式。您應該會看到一個簡單的網頁應用程式,其中顯示文字「Student name is Whale Moby」。

在終端機中按 ctrl+c 以停止您的應用程式。

在終端機中,執行 docker compose rm 以移除您的容器,然後執行 docker compose up 以再次執行您的應用程式。

$ docker compose rm
$ docker compose up --build

在您的瀏覽器中重新整理 http://localhost:8080自動更新服務

使用 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

開啟瀏覽器並驗證應用程式是否正在 http://localhost: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 的變更,然後等待幾秒鐘讓應用程式重新建置。在您的瀏覽器中重新整理 http://localhost:8080,並確認更新後的文字已出現。

在終端機中按 ctrl+c 以停止您的應用程式。

建立開發容器

此時,當您執行容器化應用程式時,它使用的是 .NET runtime 映像檔。雖然這個小映像檔適用於生產環境,但它缺少您在開發時可能需要的 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 執行單元測試。