教你创建一个带诊断工具的.NET镜像

作者:InCerry 时间:2021-09-28 03:11:11 

现阶段的问题

现在是云原生和容器化时代,.NET Core对于云原生来说有非常好的兼容和亲和性,dotnet社区以及微软为.NET Core提供了非常方便的镜像容器化方案。所以现在大多数的dotnet程序都是部署在各种容器化环境中,比如我们常见的Docker。

微软官方为.NET提供的许多Docker镜像,让我们可以很方便的创建容器化的.NET应用。如下所示就是部分官方提供的不同操作系统的镜像。

教你创建一个带诊断工具的.NET镜像

其它更详细的内容大家可以点击后面的网址查看:https://hub.docker.com/_/microsoft-dotnet-runtime/

使用VS新建一个项目,微软官方给出的多段构建Dockerfile如下所示:

# 使用aspnet runtime镜像作为基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal AS base
WORKDIR /app
EXPOSE 80

# 使用sdk镜像进行编译
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal 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

# 使用build镜像发布
FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish

# 拷贝编译结果到base镜像,完成镜像打包
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]

现在看起来一切都很美好,但是假设我们遇到某一些线上CPU 100%、内存占用率很高或者程序突然停止响应等问题我们需要使用dotnet-tracedotnet-dump等工具时就会发现使用不了。

教你创建一个带诊断工具的.NET镜像

而且在没有安装.NET SDK的情况下,我们也无法安装dotnet tool。

教你创建一个带诊断工具的.NET镜像

解决方案

1.直接使用命令安装dotnet sdk,然后再安装dotnet tool,微软在官网给出的非常方便的安装方案,但是这不是我们想要的,毕竟每次还得下载多麻烦。

教你创建一个带诊断工具的.NET镜像

2.构建最终镜像使用sdk镜像,这样的话我们就可以直接安装好这些工具,这也不是我们想要的,因为sdk镜像太大了,不利于我们分发和下载(自建机房的钞能力除外)。

教你创建一个带诊断工具的.NET镜像

3.就是我们今天提到的方案,我们可以利用Docker多段构建,使用sdk镜像安装好dotnet tool以后,直接COPY到我们runtime的镜像,然后在runtime的镜像中使用。

# 使用aspnet runtime镜像作为基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal AS base
WORKDIR /app
EXPOSE 80

# 使用sdk镜像进行编译
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal 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
# !!! 在build镜像安装dotnet tools
RUN dotnet tool install -g dotnet-dump \
   && dotnet tool install -g dotnet-trace

# 使用build镜像发布
FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish

# 拷贝编译结果到base镜像,完成镜像打包
FROM base AS final
WORKDIR /app

# !!! 从build镜像中把dotnet工具COPY出来 并设置为PATH
COPY --from=build /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="$PATH:/root/.dotnet/tools"

COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]

其中关键就是这两步,在build中使用dotnet tool来安装好所需要的工具,然后复制到runtime镜像中。

...
# !!! 在build镜像安装dotnet tools
RUN dotnet tool install -g dotnet-dump \
   && dotnet tool install -g dotnet-trace
...
# !!! 从build镜像中把dotnet工具COPY出来 并设置为PATH
COPY --from=build /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="$PATH:/root/.dotnet/tools"

当然我们可以打包一个包含好工具的runtime,供后面使用,就不用每次都安装tool了。我个人比较喜欢使用Ubuntu作为基础镜像,大家也可以用Alpine之类的基础镜像来进一步缩小体积。

# 使用sdk镜像进行编译
FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build

# !!! 在build镜像安装dotnet tools
RUN dotnet tool install -g dotnet-dump \
   && dotnet tool install -g dotnet-trace

# 使用aspnet runtime镜像作为基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
WORKDIR /app

# !!! 从build镜像中把dotnet工具COPY出来 并设置为PATH
COPY --from=build /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="$PATH:/root/.dotnet/tools"

最终镜像也很小,当然我们可以使用单文件发布和Native AOT让镜像它变得更小,那就是后话了,不在本文中介绍。

教你创建一个带诊断工具的.NET镜像

常用的工具

因为公司是自建机房,所以对于存储和网络带宽都比较宽裕,我们一般会在生产环境运行的镜像中安装下面这些工具。

RUN dotnet tool install -g dotnet-dump \
   && dotnet tool install -g dotnet-trace \
   && dotnet tool install -g dotnet-counters \
   && dotnet tool install -g dotnet-sos \
   && dotnet tool install -g dotnet-gcdump \
   && dotnet tool install -g dotnet-monitor \
   && dotnet tool install -g dotnet-symbol \
   && dotnet tool install -g JetBrains.dotTrace.GlobalTools

在遇到线上问题的时候,排查起来非常方便,对于一些内存泄漏和CPU满的问题,配合dotTrace很容易就能定位到问题所在。

来源:https://www.cnblogs.com/InCerry/p/how-to-build-dotnet-image-with-trace-tool.html

标签:.NET,镜像,诊断工具
0
投稿

猜你喜欢

  • Java内部类及其特点的讲解

    2023-06-09 19:39:41
  • Java编码摘要算法实例解析

    2022-07-21 23:33:29
  • Unity自定义编辑器界面(Inspector界面)

    2023-01-09 08:40:46
  • java多线程有序读取同一个文件

    2022-05-28 20:41:57
  • 常见的排序算法,一篇就够了

    2022-06-16 06:56:34
  • 详谈java 堆区、方法区和栈区

    2023-11-23 18:35:22
  • C#使用Monitor类实现线程同步

    2021-07-20 03:01:14
  • 全面解析Java支持的数据类型及Java的常量和变量类型

    2022-03-25 16:54:10
  • 使用Jenkins来构建GIT+Maven项目的方法步骤

    2021-11-15 07:57:33
  • java当中的定时器的4种使用方式

    2022-08-07 14:31:39
  • 浅谈JVM之使用JFR解决内存泄露

    2022-10-19 01:55:30
  • C#线程定义和使用方法详解

    2022-08-18 00:51:51
  • JVM致命错误日志详解(最新推荐)

    2023-08-22 07:42:30
  • Spring Bean自动装配入门到精通

    2023-11-03 07:29:09
  • 详解C#面相对象编程中的继承特性

    2022-06-09 09:15:24
  • Java微信公众平台开发(13) 微信JSSDK中Config配置

    2022-12-29 15:58:24
  • Spring实战之注入集合值操作示例

    2023-03-04 04:02:53
  • JVM教程之内存管理和垃圾回收(三)

    2023-11-10 15:49:54
  • JavaWeb搭建网上图书商城毕业设计

    2023-08-29 00:08:32
  • Java如何实现上传文件到服务器指定目录

    2021-10-16 14:38:31
  • asp之家 软件编程 m.aspxhome.com