You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中仅复制C#项目.csproj即可构建依赖的疑问

.NET项目Docker构建疑问解答

提供的文件内容

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["Ordering.API/Ordering.API.csproj", "Services/Ordering/Ordering.API/"]
COPY ["Ordering.Application/Ordering.Application.csproj", "Services/Ordering/Ordering.Application/"]
COPY ["Ordering.Core/Ordering.Core.csproj", "Services/Ordering/Ordering.Core/"]
COPY ["Ordering.Infrastructure/Ordering.Infrastructure.csproj", "Services/Ordering/Ordering.Infrastructure/"]

RUN dotnet restore "Services/Ordering/Ordering.API/Ordering.API.csproj"
COPY . Services/Ordering/
WORKDIR "/src/Services/Ordering/Ordering.API"
RUN dotnet build "Ordering.API.csproj" -c Release -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Ordering.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Ordering.API.Containerized.dll"]

docker-compose.yaml片段

ordering.api:
    image: ${DOCKER_REGISTRY-}orderingapi
    build:
      context: .
      dockerfile: Ordering.API/Dockerfile

疑问点

  • 为何仅复制各项目的.csproj文件到容器,就能找到并纳入所有代码?
  • 原本以为只有Ordering.API的代码通过COPY . Services/Ordering/被完整复制,为何该项目仅依靠依赖项目的.csproj文件就能解析所有非Ordering.API项目的代码?
  • dotnet restore难道不应该因为依赖项目的代码未在容器中而失败吗?毕竟仅复制了Ordering.API的代码。
  • 如果依赖项目的核心代码未导入Docker(仅复制了.csproj),这些依赖项目的.dll是如何生成的?

解答

1. COPY . Services/Ordering/实际复制了所有项目的代码

你误解了这条指令的作用:Docker构建时的context是当前目录(.),也就是docker-compose里指定的context: .,这个目录包含了所有Ordering相关的项目代码(API、Application、Core、Infrastructure)。所以COPY . Services/Ordering/是把本地所有代码都复制到容器内的/src/Services/Ordering/目录下,并非只复制Ordering.API的代码。

2. 先复制.csproj是为了利用Docker缓存优化构建速度

先单独复制各项目的.csproj文件,然后执行dotnet restore,这是Docker构建.NET项目的标准优化手段:

  • .csproj文件的变更频率远低于代码文件,当代码修改但项目依赖未变时,Docker会复用之前dotnet restore的缓存层,不需要重新下载NuGet包,大幅加快构建速度。
  • 如果一开始就复制所有代码,那么任何代码改动都会导致dotnet restore重新执行,浪费时间。

3. dotnet restore和dotnet build的工作逻辑

  • dotnet restore只需要.csproj文件就能解析项目依赖(包括项目间引用和NuGet包),它的作用是下载所需的NuGet包到容器内的缓存目录,不需要项目的实际代码。
  • 当执行COPY . Services/Ordering/后,所有项目的代码都已经在容器里了,后续的dotnet build会编译所有相关项目:因为Ordering.API的.csproj里引用了Ordering.Application,而Ordering.Application又引用了Core和Infrastructure,dotnet build会自动找到这些项目的代码(已经复制到对应路径)并编译生成各自的.dll,最终打包到Ordering.API的发布产物中。

简单来说,整个流程是:

  1. 复制所有项目的.csproj → 执行restore下载NuGet包(利用缓存)
  2. 复制所有项目的代码 → 执行build编译所有依赖项目 → 执行publish生成可部署的产物

内容的提问来源于stack exchange,提问作者toto'

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:41:05