.NET 6 的 docker 镜像可以有多小

.NET 6 的 docker 镜像可以有多小?

Intro

最近写了一个小玩具,一个命令行调用 HTTP API 的工具,介绍可以参考:动手造轮子 —— dotnet-HTTPie,

最近在使用 System.CommandLine 重构的同时,也在尝试减少 docker 镜像的大小,这样下载镜像也会比较快一些

Before

之前的做法是在 runtime 容器中安装一个 dotnet tool,然后镜像生成出来之后大概是 89.9M,

runtime 的镜像大小就已经有 87.3M,dockerfile如下:

FROM mcr.microsoft.com/dotnet/runtime:3.1-alpine AS base
LABEL Maintainer="WeihanLi"FROM mcr.microsoft.com/dotnet/sdk:3.1-alpine AS build-env
# dotnet-httpie version, docker build --build-arg TOOL_VERSION=0.1.0 -t weihanli/dotnet-httpie:0.1.0 .
ARG TOOL_VERSION
RUN dotnet tool install --global dotnet-httpie --version ${TOOL_VERSION}FROM base AS final
COPY --from=build-env /root/.dotnet/tools /root/.dotnet/tools
ENV PATH="/root/.dotnet/tools:${PATH}"

最初是基于 dotnetcore 3.1 的,所以用的是 3.1 的镜像,后面更新到了 6.0,虽然会比 3.1 小一点点,但还是会有 80 多 M,.NET 6.0 runtime 的镜像有 81.4 M,而一个 nginx 只有 22.8 M,Redis 也只有 32.3M,还是蛮大的

Now

如果有注意 dotnet 镜像的 tag 的话,你会发现有一类是 runtime-deps,就是运行时必不可少的依赖,但是里面是不包含 sdk 和 runtime 的,这通常用于部署 self-contained 的应用,就是自己包含了运行时所需的所有依赖,拉了一个 .NET 6.0 runtime-deps 的镜像,大小只有 11.9 M,仿佛看到了希望,也许能够和 nginx 以及 redis 相媲美了

对于发布 self-contained 应用只需要在发布时指定 --self-contained 并且要指定一个 runtime 信息,官方叫法是 RID(Runtime Identifier),就是要发布平台的环境信息。

可以使用下面的命令来发布一个 self-contained 应用,因为想作为一个 dotnet-tool 一样去使用,所以我们指定了 PublishSingleFile 来生成一个单文件应用,另外为了使用指定的 command 我们也指定了 AssemblyName 为我们实际想要使用的 command http

dotnet publish ./HTTPie/HTTPie.csproj -c Release --self-contained --use-current-runtime -p:AssemblyName=http -p:PublishSingleFile=true

来看一下这样 build 出来的镜像大小吧,这里我们就不再是安装 dotnet tool 了,而是直接对源码进行 build && publish,docker 镜像如下:

FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-alpine AS base
LABEL Maintainer="WeihanLi"FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-envWORKDIR /app
COPY ./src ./
COPY ./build/version.props ./Directory.Build.props
RUN dotnet publish ./HTTPie/HTTPie.csproj -c Release --self-contained --use-current-runtime -p:AssemblyName=http -p:PublishSingleFile=true -o ./artifactsFROM base AS final
COPY --from=build-env /app/artifacts /root/.dotnet/tools
ENV PATH="/root/.dotnet/tools:${PATH}"

这里使用发布单文件应用来代替了原来安装 dotnet-tool 的过程,这样打包出来的镜像 77.7 M 比原来小了一些

从 .NET Core 3.0 开始,微软提供了一个 Trim 选项,可以移除引用的程序集里可能用不到的代码,我们来尝试一下,指定 PublishTrimmed 来试一下,使用下面的命令来进行发布

dotnet publish ./HTTPie/HTTPie.csproj -c Release --self-contained --use-current-runtime -p:AssemblyName=http -p:PublishSingleFile=true -p:PublishTrimmed=true

再来看一下打包出来的镜像大小,此时已经变成了 33.4 M

已经变之前小了一半,和 redis 已经差不多了,还能不能够更小呢?

指定 Trim 的时候会有很多警告,这是因为有些方法可能会用反射来使用某些代码,并没有直接的依赖关系,此时这种方式就有可能会造成一些问题,所以使用 Trim 的时候如果程序比较复杂需要好好的测试一下以确保没有问题

.NET 6 在 Preview 4 的时候引入了一个新的功能 .NET 6 Preview 4 Released,针对单文件应用的发布提供了一个压缩选项,我们可以通过指定 EnableCompressionInSingleFile 来进一步对单文件应用进行压缩,从而进一步减小文件的大小

dotnet publish ./HTTPie/HTTPie.csproj -c Release --self-contained --use-current-runtime -p:AssemblyName=http -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableCompressionInSingleFile=true

我们再来看一下现在构建出来的镜像大小,现在我们的镜像已经减小到了 26.9M,已经比 redis 小了

这样基本就达到了我们的预期,是不是还有优化的空间呢

我们通过 dive 来看一下镜像里的内容,在最后的拷贝的时候,可以看到我们拷贝过去的其实有两个文件一个是 http,另一个是 http.pdbpdb 文件其实是不需要的,所以我们在拷贝的时候可以只拷贝 http 就可以了

但是 pdb 文件很小,只有几十k,所以去掉了以后打包还是有 26.9M,但是镜像里就只有一个文件了,就很舒适

dive 是一个非常有帮助的工具来查看 docker 镜像里每一层的内容,在镜像启动不起来,镜像有问题的时候是一个非常好的分析工具

完整的 Dockerfile 如下:

FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-alpine AS base
LABEL Maintainer="WeihanLi"FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-envWORKDIR /app
COPY ./src ./
COPY ./build/version.props ./Directory.Build.props
RUN dotnet publish ./HTTPie/HTTPie.csproj -c Release --self-contained --use-current-runtime -p:AssemblyName=http -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableCompressionInSingleFile=true -o ./artifactsFROM base AS final
COPY --from=build-env /app/artifacts/http /root/.dotnet/tools/http
ENV PATH="/root/.dotnet/tools:${PATH}"

最后对我们的 docker 镜像进行测试

使用类似的方法对一个 hello world 应用测试一下, hello-world 是一个 console,23.4M ,API 是一个 asp.net core web api 应用,34.3M

上传到 dockerhub 之后,看到的大小会更小一些,docker registry 会对镜像进行压缩

More

使用 dotnet publish 而不是使用 dotnet tool 的方式除了大小之外,还有一些别的好处,现在我们发布包到 nuget 的时候往往会有一定的时间才能获取到这个包,现在更新 docker 镜像都是手动去做的,因为要等 nuget 上出现这个版本的包以后再进行打包,就不够自动化,使用 publish 的方式可以更好的自动化地发布

.NET 6 SDK 后续会针对 self-contained 进行一些优化,对于 --self-contained 可以使用 --sc 来代替,一个别名,简化使用,同时使用 --self-contained 的时候会默认自动使用当前 SDK 的 RID,这样发布 self-contained 应用就会更加方便了,详细可以参考 issue:https://github.com/dotnet/sdk/issues/19576

References

  • https://hub.docker.com/_/microsoft-dotnet-runtime-deps/

  • https://hub.docker.com/repository/registry-1.docker.io/weihanli/dotnet-httpie/tags?page=1&ordering=last_updated

  • https://github.com/WeihanLi/dotnet-httpie

  • https://docs.microsoft.com/en-us/dotnet/core/deploying/trim-self-contained?WT.mc_id=DT-MVP-5004222

  • https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/#compression

  • https://github.com/wagoodman/dive

  • .NET 6 Preview 4 Released

  • 动手造轮子 —— dotnet-HTTPie

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源播放器 Banshee 发布 1.0 beta 2

Banshee也是个很是不错的开源播放器,同时也是SuSE的内置播放器,默许支持靠山播放,消息区域告诉,可以快速跳过以后曲目,评分等等,也支持全局热键,媒体库支持音频和视频.新版本提供了对网络视频和PodCast的优秀支持.SuSE/Ubuntu/Fedora Linux用户可以从源中直接安置,也可以下载安…

仓库每天的账怎样做_新年第一站,济南:仓储匠人仓库问题解决与实战力培训...

【时间地点】1月15-16日,济南站济南市天桥区无影山北路88号祥云酒店5楼(师范路西口)【报名方式】直接加微信号“taishan33976”,注明姓名公司名仓储匠人。如果您认识小编的任意一位同事,欢迎直接找他们报名。【培训价格】1960元/人&#xff0…

【编程好习惯】将常量放在“==”之前

对于图1中的程序其中存在一个问题,那就是38行if语句中的判断条件,这一程序的结果是只有else语句中的程序会被执行。其中的错误在于,if语句中本应是“”,但却被误写成了“”,因而_p_ref中的prev_被斌值成了零&#xff0…

一对一指导怎么追喜欢的男生

1 它们是怎样达成平衡的2 OK. 对不起打扰了3 今天也要加油鸭!4 以色列一个父亲,为她“坐没坐相”的女儿打造的椅子。5 这个床我爱了6 静冈花火大会上摄影师发现了一个有趣的角度7 怎么样学会了吗内容自奔现翻车现场你点的每个赞,我都认真当成…

html 存储登录状态,Vue中保存用户登录状态实例代码

首先我们假设,这里的登录组件(register.vue)是App.vue组件的子组件,是通过路由进入登录组件的。登录组件中用户点击登录后,后台会传过来一个用户名,我的App.vue组件中需要拿到这个用户名,并将上面的“登录注册”字样变…

android canvas_Android 如何实现气泡选择动画

作者:Irina Galata Android 开发者: Yulia Serbenenko UI/UX 设计师 译者:skyar2009链接:https://juejin.im/post/58e5ec838d6d8100616d82e2/跨平台用户体验统一正处于增长趋势:早些时候 iOS 和安卓有着不同的体验,但是…

MVC中的验证规则

前面的博客中曾经提到过ModelBing机制,也在Demo中体现过,在MVC中更吊的是封装了自定义的验证规则。下面来一个Demo来展现一下,看了后,你一定会爱上它的,能让你少写很多JS语句。 1.View层 [html] view plaincopyprint…

网络——在网络上发送,接收数据

问题 创建并加入一个网络会话是一回事,但如果不能发送或接收任何数据那么网络会话有什么用呢? 解决方案 当玩家连接到会话时,你可以在一个PacketWriter流中存储所有想要发送的数据。完成这个操作后,你可以使用LocalNetworkPlayer.…

微服务之 EShop on dapr概览

????欢迎点赞 :???? 收藏 ⭐留言 ???? 如有错误敬请指正,赐人玫瑰,手留余香!????本文作者:由webmote 原创,首发于 【掘金】????作者格言:生活在于折腾,当你不折…

python开发面试问题及答案_前50个Python面试问题(最受欢迎)

热门Python面试问答下面列出的是关于Python编程语言的最常见面试问题和答案。让我们探索!!#1)Python可以用于Web客户端和Web服务器端编程吗?哪一个最适合Python?答案: Python由于具有创建业务逻辑&#xff…

苹果android 对比,苹果安卓旗舰差距有多少?看了这份对比,果粉傻眼了

最近,身边不少小伙伴都在换机,有的换了最新的 iPhone 12 系列,有的则是换成安卓旗舰,毕竟现在的安卓旗舰与 iPhone 之间的体验已经十分接近,甚至在一些方面安卓旗舰还有着不小的优势。下面,我们以最新的 iP…

【暴强】200种好口碑便宜护肤品 - 生活至上,美容至尚!

200种好口碑便宜护肤品 一.洁面类 1.欧泊莱均衡洁面膏40ML 25元:很丰富的泡沫,,最大的好处就是洗完了脸不干,很舒服。 2.珊拉娜除逗防疤洗面奶:泡沫非常细,毛孔清透 3.丹芭碧绿茶洁面啫喱18元:觉得洗后很…

查看和修改Oracle数据库服务器端的字符集

Oracle数据库查看和修改服务器端的字符集的方法是本文主要要介绍的内容,接下来救让我们一起来了解一下这部分内容。 A、oracle server 端字符集查询 select userenv(‘language’) from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LANGUAGE 为 server端字符显…

python画画用哪库好_Python我要学画画-turtle库

上帝说:“要有光!” 于是,就有了光。 ---《圣经》旧约创世纪篇 我要学画画,Python便有了turtle库。 turtle库是一个点线面的简单图像库。画布中心为坐标系原点,小海龟起始位置就在原点方向向右。turtle界面 Python与库…

Xubuntu菜单删改条记

作者: Zhu.CA 出自: http://www.linuxdiyf.com1. 主菜单:主菜单为 ~/.config/xfce4/desktop/menu.xml。删改可用"Xfce Settings Manager"中的"Menu editer",运用上绝对俭朴,不做过多详述。 2. System子菜单&#xff…

看完这15张动图,秒懂万有引力与航天难点!

全世界只有3.14 % 的人关注了爆炸吧知识椭圆的画法大质量天体使周围天体绕其运转模拟太阳系星球轨迹非常接近圆火箭运载卫星升空卫星飞行过程中可以点火调整姿态同步卫星必须在赤道上空北斗全球卫星导航轨道半径越大,卫星越慢人类发射的卫星越来越多嫦娥沿椭圆轨道奔…

物联网工程专业的迷茫与抉择

大家好,我是阿辉,很高兴在这里和你讲述所思所想。周末了,就聊点比较轻松的话题。正文共1633字,预计阅读时间5分钟。想必很多朋友是通过#毕业四年,我当初是如何走上编程这条路的!#这篇文章才熟知我的吧&…

html二级页面内容滑动,jQuery+CSS实现的网页二级下滑菜单效果

本文实例讲述了jQueryCSS实现的网页二级下滑菜单效果。分享给大家供大家参考。具体如下:这是一款简洁型的 jQueryCSS网页二级下滑菜单,练手写的,有需要的自己拿去美化吧,基本的动画效果和菜单下滑效果和渐变效果已经做出来了&…

parentElement,srcElement 使用

代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><meta http-equiv"Content-T…

哈哈哈,程序员没有女朋友的原因,我终于找到了!

全世界只有3.14 % 的人关注了爆炸吧知识程序员没有女朋友的原因▼程序员大脑里想的▼每天要学习太多语言&#xff0c;程序员太忙了▼女朋友 VS 编译器▼程序员sao起来&#xff0c;还需要女朋友吗&#xff1f;▼电脑才是程序员的女朋友▼互道晚安后&#xff0c;会不会偶遇在同一…