首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core Docker 再也不用逐个 COPY csproj 文件啦!

.NET Core Docker 再也不用逐个 COPY csproj 文件啦!

作者头像
Edi Wang
发布2020-05-07 23:41:37
1.9K0
发布2020-05-07 23:41:37
举报
文章被收录于专栏:汪宇杰博客汪宇杰博客

导语

ASP.NET Core 项目可以很容易的通过 Visual Studio 一键添加 Docker 支持。VS会帮你自动生成绝对能跑的 Dockerfile。然而随着项目的增大,这个 Dockerfile 会有对应的维护工作,我们来看看如何一劳永逸的简化它!

默认 Dockerfile 的问题

对于一个典型的 ASP.NET Core 项目(例如我的博客系统)来说,VS 默认添加的 Dockerfile 通常如下:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN apt-get update && apt-get install -y libgdiplus
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Moonglade.Web/Moonglade.Web.csproj", "Moonglade.Web/"]
COPY ["Moonglade.Web.Authentication/Moonglade.Web.Authentication.csproj", "Moonglade.Web.Authentication/"]
COPY ["Moonglade.Web.SiteIconGenerator/Moonglade.Web.SiteIconGenerator.csproj", "Moonglade.Web.SiteIconGenerator/"]
COPY ["Moonglade.Web.Middleware/Moonglade.Web.Middleware.csproj", "Moonglade.Web.Middleware/"]
# Common
COPY ["Moonglade.DateTimeOps/Moonglade.DateTimeOps.csproj", "Moonglade.DateTimeOps/"]
# 篇幅关系省略更多的 COPY
RUN dotnet restore "Moonglade.Web/Moonglade.Web.csproj"
COPY . .
WORKDIR "/src/Moonglade.Web"
RUN dotnet build "Moonglade.Web.csproj" -p:Version=10.3.0-docker -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Moonglade.Web.csproj" -p:Version=10.3.0-docker -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Moonglade.Web.dll"]

其中包含 COPY 每个目录下 csproj 工程文件的步骤。而随着项目的扩充,工程文件会不断的增加、修改或删除。那么程序员就必须去 Dockerfile 里做对应的修改。在 996 的时候很容易忘改,导致编译爆炸,开猿节流。

自动操作,一劳永逸

作为一名有头发的程序员,当一件事情需要经常重复操作的时候,就应该想个办法自动化解决问题。我们希望Dockerfile 能自动去查找和COPY工程目录下所有的csproj文件,不想每次项目文件有更改还得手工维护 Dockerfile。

在花了 996 分钟研究,并两次放弃治疗之后,我终于站在国外资料的肩膀上自主研发成功了!

最终操作是使用下面两条指令,替换所有的 COPY 指令。

COPY ./**/*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done

方法参考:https://andrewlock.net/optimising-asp-net-core-apps-in-docker-avoiding-manually-copying-csproj-files-part-2/

根据实际项目差异,我对 Andrew Lock 的代码做了少许修改,但思路是一致的。

首先,第一行的 COPY ./**/*.csproj ./ 会把所有子目录下的 csproj 工程文件复制到 ./

然而这里面有个问题在于它不会保持原有的目录结构,所有被复制出来的 csproj 文件都会平行存储于 ./ 里。原作者的博客里也指出了这个问题:

因此需要通过第二条命令重建目录结构。按照正常 by convention 的 .NET 项目命名方法,文件夹的名称就是 csproj 的名称,因此创建文件夹时直接用 ${file%.*} 拿到csproj 的名称即可。最后再把 csproj 文件移动到各自的文件夹里,效果和 VS 自动生成的 COPY 指令一模一样。

最终版 Dockerfile

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN apt-get update && apt-get install -y libgdiplus
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
# Auto copy to prevent 996
COPY ./**/*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done
RUN dotnet restore "Moonglade.Web/Moonglade.Web.csproj"
COPY . .
WORKDIR "/src/Moonglade.Web"
RUN dotnet build "Moonglade.Web.csproj" -p:Version=10.3.0-docker -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Moonglade.Web.csproj" -p:Version=10.3.0-docker -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Moonglade.Web.dll"]
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 汪宇杰博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档