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

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 原创,首发于 【掘金】????作者格言:生活在于折腾,当你不折…

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

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

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

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

看完这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;会不会偶遇在同一…

基于事件驱动架构构建微服务第7部分:在仓储上实现事件溯源

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part7-implementing-eventsourcing-on-repositories/在本文中&#xff0c;我将讨论Repository上的Event Sourcing实现。仓储负责将事件添加到事件存储并从事件存储中检索…

python选择题题目_Python接口测试题(持续更新中)

1、json和字典的区别&#xff1f; Json是轻量级的数据交互格式&#xff0c;以key-value的键值对形式来保存数据&#xff0c;结构清晰&#xff0c;可以说是目前互联网项目开发中最常用的一种数据交互格式。 字典&#xff0c;同样是以key-value的键值对来保存数据&#xff0c;是p…

html5 ajax数据显示,html5的ajax学习(二)

一、基础知识点1.ajax可以做事情&#xff1a;局部刷新 浏览器搜索列表记录 加载更多的数据2.登录页面同步网络请求&#xff1a;页面全部刷新&#xff0c;用户量大体验很不好3.ajax的详解&#xff1a;ajax的get和post请求 同步还是异步&#xff0c;true为异步ajax.open("ge…

ISA Server服务器故障恢复一例系统盘符更换之后的应对方法

周四下午的时候&#xff0c;某政府信息中心领导打电话告诉我&#xff0c;ISA Server服务器不能开机了。随后公司的技术员到达现场&#xff0c;经过检查&#xff0c;发现服务器显卡损坏。在更换显卡后&#xff0c;服务器可以开机&#xff0c;但却不能进入系统—-服务器在经过BIO…

扩展Windows Mobile模拟器存储空间的方法

在Windows Mobile应用程序开发的初期&#xff0c;可以使用SDK自带的模拟器来进行调试&#xff0c;这给我们开发人员提供了一种方便的途径。一般的应用程序&#xff0c;占用空间的大小也就几 百K&#xff0c;或者几M&#xff0c;这在模拟器上调试起来一点问题也没有。但是有的时…

UOS LoongArch 上成功安装.NET Core 3.1

龙芯.NET团队正式发布了.NET Core 3.1 For LoongArch, 具体参见龙芯开源网站 http://www.loongnix.cn/index.php/Dotnet 。进入安装包下载地址LoongArch64-.NET Core 3.1&#xff0c;可以看到龙芯.NET团队做了很多工作&#xff0c;为Debian和Redhat两大Linux体系平台都做好了基…