自定义容器映像进行调试

注意

本部分介绍如何在选择 Dockerfile 容器生成类型时自定义 Docker 容器。 如果使用 .NET SDK 生成类型,自定义选项会有所不同,并且本部分中的大部分信息不适用。 请改为参阅使用 dotnet publish 容器化 .NET 应用

在“调试”配置中生成时,Visual Studio 执行的一些优化操作有助于提高容器化项目生成过程的性能。 容器化应用的生成过程并不像仅遵循 Dockerfile 中所述的步骤那样简单。 在容器中生成比在本地计算机上生成要慢。 因此,在调试配置中生成时,Visual Studio 实际上会在本地计算机上生成项目,然后使用卷装载将输出文件夹共享到容器。 启用了此优化的生成称为快速模式生成。

在“快速”模式下,Visual Studio 使用参数调用 docker build,该参数指示 Docker 仅生成 Dockerfile 中的第一个阶段(通常是 base 阶段)。 可以通过设置 MSBuild 属性 DockerfileFastModeStage 来对此进行更改,如容器工具 MSBuild 属性所述。 Visual Studio 处理该过程的其余部分,而与 Dockerfile 的内容无关。 因此,修改 Dockerfile(例如自定义容器环境或安装其他依赖项)时,应将修改放在第一阶段。 不会执行 Dockerfile 的 buildpublishfinal 阶段中的任何自定义步骤。

通常仅当在调试配置中生成时才会进行此性能优化。 在发布配置中,生成在 Dockerfile 中指定的容器中进行。 可以通过在项目文件中将 ContainerDevelopmentMode 设置为快速来为发布配置启用此行为:

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
   <ContainerDevelopmentMode>Fast</ContainerDevelopmentMode>
</PropertyGroup>

如果要为所有配置禁用性能优化并按 Dockerfile 指定的方式生成,请在项目文件中将 ContainerDevelopmentMode 属性设置为常规,如下所示:

<PropertyGroup>
   <ContainerDevelopmentMode>Regular</ContainerDevelopmentMode>
</PropertyGroup>

若要恢复性能优化,请从项目文件中删除该属性。

启动调试 (F5) 时,将重新使用以前启动的容器(如有)。 如果不想重复使用以前的容器,则可以在 Visual Studio 中使用 RebuildClean 命令强制 Visual Studio 使用新的容器 。

运行调试程序的过程取决于项目类型和容器操作系统:

方案 调试器进程
.NET Core 应用(Linux 容器) Visual Studio 下载 vsdbg 并将其映射到容器,然后通过程序和参数(即 dotnet webapp.dll)进行调用,接着调试程序附加到进程中。
.NET Core 应用(Windows 容器) Visual Studio 使用 onecoremsvsmon 并将其映射到容器,将其作为入口点运行,然后 Visual Studio 与其建立连接并附加到程序中。
.NET Framework 应用 Visual Studio 使用 msvsmon 并将其映射到容器,将其作为入口点(Visual Studio 可通过此入口点与其建立连接)的一部分运行,并附加到程序中。 此过程与通常在其他计算机或虚拟机上设置远程调试的过程类似。

有关 vsdbg.exe 的信息,请参阅通过 Visual Studio 对 Linux 和 OS X 上的 .NET Core 进行 Offroad 调试

修改容器映像以用于调试和生产

若要修改用于调试和生产的容器映像,请修改 base 阶段。 将自定义项添加到基础阶段部分中的 Dockerfile,通常是 Dockerfile 中的第一部分。 有关 Dockerfile 命令的信息,请参阅 Docker 文档中的 Dockerfile 参考

# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
# <add your commands here>

# This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebApplication3/WebApplication3.csproj", "WebApplication3/"]
RUN dotnet restore "WebApplication3/WebApplication3.csproj"
COPY . .
WORKDIR "/src/WebApplication3"
RUN dotnet build "WebApplication3.csproj" -c Release -o /app/build

# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
RUN dotnet publish "WebApplication3.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", "WebApplication3.dll"]

修改容器映像以仅用于调试

可以通过某些方式自定义容器以帮助调试,例如出于诊断目的安装某些内容,而不会影响生产版本。

若要修改容器以仅用于调试,请创建一个阶段,然后使用 MSBuild 属性 DockerfileFastModeStage 告知 Visual Studio 在调试时使用自定义的阶段。 有关 Dockerfile 命令的信息,请参阅 Docker 文档中的 Dockerfile 参考

注意

此处的说明适用于单容器案例。 也可以使用 Docker Compose 对多个容器执行相同的操作,但 Docker Compose 所需的技术略有不同。 例如,阶段由 dockercompose.debug.yml 文件中的设置控制。

在以下示例中,我们安装 procps-ng 包,但仅在调试模式下安装。 此包会提供命令 pidof,Visual Studio 需要该命令(在针对 .NET 5 及更早版本时),但不在此处使用的 Mariner 映像中。 我们用于快速模式调试的阶段是 debug,即此处定义的自定义阶段。 快速模式阶段不需要从 buildpublish 阶段继承,它可以直接从 base 阶段继承,因为 Visual Studio 将装载一个卷,其中包含了运行应用所需的所有内容,如本文前面所述。

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

# This stage is used when running from VS in fast mode (Default for Debug configuration)
FROM mcr.microsoft.com/dotnet/aspnet:6.0-cbl-mariner2.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM base AS debug
RUN tdnf install procps-ng -y

# This stage is used to build the service project
FROM mcr.microsoft.com/dotnet/sdk:6.0-cbl-mariner2.0 AS build
WORKDIR /src
COPY ["WebApplication1/WebApplication1.csproj", "WebApplication1/"]
RUN dotnet restore "WebApplication1/WebApplication1.csproj"
COPY . .
WORKDIR "/src/WebApplication1"
RUN dotnet build "WebApplication1.csproj" -c Release -o /app/build

# This stage is used to publish the service project to be copied to the final stage
FROM build AS publish
RUN dotnet publish "WebApplication1.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", "WebApplication1.dll"]

在项目文件中,添加此设置,告知 Visual Studio 在调试时使用自定义的阶段 debug

  <PropertyGroup>
     <!-- other property settings -->
     <DockerfileFastModeStage>debug</DockerfileFastModeStage>
  </PropertyGroup>

使用 AOT 部署自定义调试映像

若要支持本机 AOT 部署,请安装 GNU 调试器 (GDB),但仅在调试时使用的映像上安装,而不是最终运行时映像上安装。 Dockerfile 包含一个生成变量 LAUNCHING_FROM_VS,此变量可以是 truefalse。 如果为 true,则使用安装 GDB 所在的 aotdebug 阶段。 请注意,Visual Studio 仅支持适用于 Linux 容器的本机 AOT 和 GDB。

# These ARGs allow for swapping out the base used to make the final image when debugging from VS
ARG LAUNCHING_FROM_VS
# This sets the base image for final, but only if LAUNCHING_FROM_VS has been defined
ARG FINAL_BASE_IMAGE=${LAUNCHING_FROM_VS:+aotdebug}

# ... (other stages omitted)

# This stage is used as the base for the final stage when launching from VS to support debugging in regular mode (Default when not using the Debug configuration)
FROM base as aotdebug
USER root
# Install GDB to support native debugging
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
    gdb
USER app

# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
FROM ${FINAL_BASE_IMAGE:-mcr.microsoft.com/dotnet/runtime-deps:8.0} AS final
WORKDIR /app
EXPOSE 8080
COPY --from=publish /app/publish .
ENTRYPOINT ["./WebApplication1"]

可以在 Dockerfile 中使用 aotstage 自定义在调试时使用的映像,而不会影响在未从 Visual Studio 或生产环境中启动时使用的最终映像。 例如,可以安装仅在调试期间使用的工具。