如何在Docker中加速含多层项目引用的.NET解决方案构建速度
多项目.NET Docker构建优化方案
1 修正Dockerfile基础逻辑与层缓存顺序
首先调整文件拷贝顺序,利用Docker层缓存特性避免重复执行restore:
# 必须指定语法版本以支持构建缓存挂载 # syntax=docker/dockerfile:1.4 FROM sdk_image as build WORKDIR /src # 第一步仅拷贝所有依赖项目的csproj文件,保留目录结构 COPY src/BaseProject/BaseProject.csproj ./BaseProject/ COPY src/[当前项目名]/[当前项目名].csproj ./[当前项目名]/ # 仅执行restore,只要csproj文件无变更,该层会永久缓存 RUN --mount=type=cache,target=/root/.nuget/packages dotnet restore ./[当前项目名]/[当前项目名].csproj # 第二步再拷贝全量源代码 COPY . . # 构建时挂载缓存存储中间编译产物,公共项目变更前无需重复编译 RUN --mount=type=cache,target=/src/BaseProject/obj \ --mount=type=cache,target=/src/BaseProject/bin \ --mount=type=cache,target=/src/[当前项目名]/obj \ --mount=type=cache,target=/src/[当前项目名]/bin \ dotnet build ./[当前项目名]/[当前项目名].csproj --no-restore -c Release RUN dotnet publish ./[当前项目名]/[当前项目名].csproj --no-build --no-restore -c Release -o /app/output FROM runtime_image as runtime WORKDIR /app COPY --from=build /app/output . # 原Dockerfile中RUN dotnet run是错误用法,RUN为构建阶段执行命令,应改为ENTRYPOINT ENTRYPOINT ["dotnet", "[当前项目名].dll"]
上述优化适配所有子项目,仅需替换[当前项目名]为对应项目名称即可。
2 复用Nuget包与中间构建产物
使用Docker内置的构建缓存挂载(比手动管理Volume更适配并行构建场景):
--mount=type=cache,target=/root/.nuget/packages会持久化所有Nuget包,所有项目构建共享该缓存,无需每次拉取- 挂载各个项目的
obj、bin目录,只要对应项目代码无变更,就会直接复用之前的编译结果,BaseProject只需编译一次即可被所有子项目复用 - 云端构建时只需开启构建缓存持久化配置,即可跨多次构建复用上述缓存内容
3 共享公共项目构建结果
如果并行构建时希望进一步降低重复编译消耗,可以在docker-compose.yml中配置公共构建缓存:
services: base-build: build: context: . dockerfile: src/BaseProject/Dockerfile target: build cache_from: - ${REGISTRY}/base-build:latest project-a: build: context: . dockerfile: src/ProjectA/Dockerfile cache_from: - ${REGISTRY}/base-build:latest - ${REGISTRY}/project-a:latest # 其余ProjectB、ProjectC配置同ProjectA
构建时先执行docker compose build base-build并将镜像推送至镜像仓库,再执行并行构建命令,所有子项目都会直接复用BaseProject的已编译产物。
4 裁剪发布输出降低复制耗时
在dotnet publish命令中加入参数精简输出体积:
dotnet publish ./[当前项目名]/[当前项目名].csproj --no-build --no-restore -c Release -o /app/output \ /p:PublishTrimmed=true \ # 裁剪未使用的程序集代码 /p:DebugType=None \ # 不生成调试符号文件 /p:ExcludeSymbols=true \ # 排除符号文件 --self-contained false # 若使用通用runtime镜像,无需打包运行时,可减少数十MB体积
根据项目特性可选择性开启上述参数,通常可降低70%以上的发布输出体积,大幅减少COPY阶段耗时。
内容的提问来源于stack exchange,提问作者Shadow
相关产品推荐
相关产品推荐

