在 Visual Studio 中自定义 Docker 容器
通过编辑你向项目添加 Docker 支持时 Visual Studio 生成的 Dockerfile,可以自定义容器映像。 无论是从 Visual Studio IDE 生成自定义容器还是设置命令行生成,都需要知道 Visual Studio 如何使用 Dockerfile 生成项目。 需要了解此类详细信息,因为出于性能原因,Visual Studio 遵循一个特殊的过程来生成和运行 Dockerfile 中不明显的容器化应用。
假设你想要在 Dockerfile 中进行更改,并在调试和生产容器中查看结果。 在这种情况下,可以在 Dockerfile 中添加命令以修改第一阶段(通常 base
)。 请参阅修改容器映像以用于调试和生产。 但是,如果只想在调试而不是生产时进行更改,则应创建另一个阶段,并使用 DockerfileFastModeStage
生成设置告知 Visual Studio 将该阶段用于调试生成。 请参阅修改容器映像以仅用于调试。
本文详细介绍容器化应用的 Visual Studio 生成过程,然后它包含有关如何修改 Dockerfile 以影响调试和生产生成的信息,或仅用于调试。
Visual Studio 中的 Dockerfile 生成
说明
本部分介绍 Visual Studio 在选择 Dockerfile 容器生成类型时使用的容器生成过程。 如果使用 .NET SDK 生成类型,自定义选项会有所不同,并且本节中的信息不适用。 而是,请参阅 Containerize a .NET app with dotnet publish,并使用 Customize your container 中所述的属性来配置容器生成过程。
多阶段生成
当 Visual Studio 生成不使用 Docker 容器的项目时,它会在本地计算机上调用 MSBuild,并在本地解决方案文件夹下的文件夹中(通常为 bin
)生成输出文件。 但是,对于容器化项目,生成过程会考虑 Dockerfile 生成容器化应用的说明。 Visual Studio 使用的 Dockerfile 分为多个阶段。 此过程依赖于 Docker 多阶段生成 功能。
多阶段生成功能有助于提高生成容器的过程,并通过允许容器仅包含运行时应用所需的位来减小容器。 多阶段生成用于 .NET Core 项目,而不是 .NET Framework 项目。
多阶段生成允许在生成中间映像的阶段创建容器映像。 例如,考虑一个典型的 Dockerfile。 第一个阶段在 Visual Studio 生成的 Dockerfile 中称为 base
,尽管这些工具不需要该名称。
# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
Dockerfile 中的行以Microsoft容器注册表(mcr.microsoft.com)中的 ASP.NET 映像开头,并创建公开端口 80 和 443 的中间映像 base
,并将工作目录设置为 /app
。
下一阶段是 build
,如下所示:
# This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:3.1-buster-slim AS build
WORKDIR /src
COPY ["WebApplication43/WebApplication43.csproj", "WebApplication43/"]
RUN dotnet restore "WebApplication43/WebApplication43.csproj"
COPY . .
WORKDIR "/src/WebApplication43"
RUN dotnet build "WebApplication43.csproj" -c Release -o /app/build
你可以看到,build
阶段是从注册表(sdk
而不是 aspnet
)中的其他原始映像开始,而不是从基础映像继续。 sdk
映像具有所有生成工具,因此它比仅包含运行时组件的 aspnet 映像要大得多。 查看 Dockerfile 余下内容时,使用单独镜像的原因就会变得清晰。
# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
RUN dotnet publish "WebApplication43.csproj" -c Release -o /app/publish
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication43.dll"]
最后阶段再次从 base
开始,并包括 COPY --from=publish
以将发布的输出复制到最终映像中。 此过程使最终映像可能更小得多,因为它不需要包括 sdk
映像中的所有生成工具。
下表总结了 Visual Studio 创建的典型 Dockerfile 中使用的阶段:
阶段 | 描述 |
---|---|
base | 创建用于发布已构建应用程序的基本运行时映像。 运行时需要可用的设置将转到此处,例如端口和环境变量。 在 VS 中以快速模式运行时(调试配置的默认设置),使用此阶段。 |
build | 项目在此阶段生成。 使用 .NET SDK 基础映像,该映像具有生成项目所需的组件。 |
publish | 此阶段派生自构建阶段,并在这一阶段发布项目,之后该项目将被复制到最终阶段。 |
final | 此阶段配置了如何启动应用,并在生产环境中或在常规模式下从 VS 运行时使用(不使用调试配置时为默认值)。 |
aotdebug | 从 VS 启动时,此阶段用作最终阶段的基础,以支持在常规模式下进行调试(不使用调试配置时为默认值)。 |
说明
仅 Linux 容器支持 aotdebug
阶段。 如果在项目上启用了本机预先 (AOT) 部署,则会在 Visual Studio 2022 17.11 及更高版本中使用该功能。
项目预热
项目预热 是指为项目(即加载项目或添加 Docker 支持时)选择 Docker 配置文件时发生的一系列步骤,以提高后续运行的性能(F5 或 Ctrl+F5)。 此行为可在 工具>选项>容器工具下进行配置。 下面是在后台运行的任务:
- 检查是否已安装并运行 Docker Desktop。
- 确保 Docker Desktop 设置为与项目相同的操作系统。
- 在 Dockerfile 的第一阶段(大部分 Dockerfile 中的
base
阶段)拉取映像。 - 生成 Dockerfile 并启动容器。
预热仅在“快速”模式下发生,因此正在运行的容器对 app 文件夹进行卷装载。 这意味着对应用所做的任何更改不会使容器失效。 此行为显著提高调试性能,并减少长时间运行任务(如拉取大规模镜像)的等待时间。
启用详细的容器工具日志
出于诊断目的,可以启用某些容器工具日志。 可以通过设置某些环境变量来启用这些日志。 对于单个容器项目,环境变量是 MS_VS_CONTAINERS_TOOLS_LOGGING_ENABLED
,然后登录 %tmp%\Microsoft.VisualStudio.Containers.Tools
。 对于 Docker Compose 项目,环境变量为 MS_VS_DOCKER_TOOLS_LOGGING_ENABLED
,随后会记录在 %tmp%\Microsoft.VisualStudio.DockerCompose.Tools
中。
警告
启用日志记录并使用令牌代理进行 Azure 身份验证时,可以将身份验证凭据记录为纯文本。 请参阅 配置 Azure 身份验证。
后续步骤
了解如何使用 Dockerfile 阶段来定制用于调试和生产的镜像,例如,仅在调试时如何在镜像上安装工具。 请参阅 配置容器映像以调试。