docker发布dotnet应用时,还原过慢的解决思路

506 阅读2分钟

需求描述

使用jenkins管理项目发布,jenkins部署在docker内。
在第一个版本设计中,jenkins调用宿主机的dotnet sdk进行restore和publish。前期项目数量较少,后期项目数增多,每个项目生成过后的存储在2个G左右,导致磁盘占用过大。

第二次设计,采用docker内部编译发布,使得jenkins不再保留项目发布过后的文件,大小回归到40Mb左右。但是导致了新的问题,每个项目发布时间在2分钟左右,尤其是更新了dotnet 8.0过后,还原的时间就会占用到2-3分钟,整体时间接近5分钟。

第三次设计,解决项目还原过长的问题。有两个方案,一是回归到使用宿主机的dotnet进行发布,然后进行项目清理,麻烦点在于项目采用了一个解决方案,多个项目的设计,并行发布多个项目时,可能会引发冲突。二就是继续在docker内进行发布操作,解决还原耗时过长的问题。

解决思路

1.模拟本地环境,建立nuget缓存,使docker还原时尽可能使用本地缓存包,但是因为缓存机制,docker并不能直接操作外部文件,而复制外部的nuget缓存文件,存储高达7个G。

2.利于docker的缓存机制,在包没有更新时,使用docker缓存,而跳过还原。

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-dir
WORKDIR /publish
COPY . ./
# 筛选出所有csproj文件,以及他们的层级目录
RUN ["/bin/bash", "-c", "mkdir cs && set -evx -o pipefail && echo '#!/bin/bash' > /publish/copy_csproj.sh && echo 'find . -name \"*.csproj\" | xargs -I {} cp --parents {} /publish/cs' >> /publish/copy_csproj.sh && chmod +x /publish/copy_csproj.sh"]
RUN  /publish/copy_csproj.sh

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
ARG PRONAME
WORKDIR /publish
# 将层级目录复制进来
COPY --from=build-dir /publish/cs .
# 还原指定的项目
RUN dotnet restore ./${PRONAME}/${PRONAME}.csproj -s https://nuget.cdn.azure.cn/v3/index.json
COPY . ./
#发布指定的项目
WORKDIR /publish/${PRONAME}
RUN dotnet publish  --no-restore -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine-shanghai
ARG PRONAME
ENV APP_NAME=${PRONAME}
WORKDIR /publish
COPY --from=build-env /publish/${PRONAME}/out .
EXPOSE 9013
ENV ASPNETCORE_URLS http://*:9013
ENTRYPOINT dotnet $APP_NAME.dll
  
  
#发布命令带入项目名
docker build --build-arg PRONAME=xxx -t xxx-dev:latest -f ./xxx/Dockerfile .