.NET程序在Linux容器中的演变

本文将首先讨论镜像的构建时间和启动时间,接着会将一个简单的.NET程序运行在基于容器的应用上,然后观察镜像大小的变化,最终缩短镜像的构建和加载时间。此外,代码优化是本文的另一个主题。

现在,.NET开发人员可以无障碍地使用如Docker这样的Linux容器,那么让我们来尝试如何以正确的方式配置一个容器。

可能,文章的标题改成“Linux容器开发人员的演变”会更好。由于.NET可在Linux(以及Windows和macOS)上运行,所以整个世界的Linux容器和微服务已经开放给了.NET开发人员。

有着大量的开发人员,长期的运行记录和优异性能指标的.NET,现在给以Windows为中心的开发人员提供了一个使用Linux容器的机会。

虽然在Linux容器中尝试运行.NET代码是诱人的,同时也会产生一些细微差别,但是这样做是不会错的。你可以很容易地将一些.NET代码推送到镜像中。

毕竟,一切都发生的这么快,一定都很好。 对不对?

事实并非如此。让.NET代码运行在Linux容器中并不是一件简单的事情,但请记住:“先让它工作,然后让它工作得很快。”

在下面的例子中,上文说的“很快”指的是构建镜像所需的时间,启动镜像所需的时间和镜像内部代码的性能。本文将首先讨论镜像的构建时间和启动时间,接着会将一个简单的.NET程序运行在基于容器的应用上,然后观察镜像大小的变化,最终缩短镜像的构建和加载时间。此外,代码优化是本文的另一个主题。

短暂的停留

考虑一个非常简单的微服务示例,它只给出一个“Hello world”类型的HTTP响应。也就是说,当在浏览器中填写URL,你就会得到一个包括主机名的Web页面。

我们可从这个代码库中(https://github.com/donschenck/dotnet_docker_msa)下载源码,并制作第一个Dockerfile(Dockerfile.attempt1),接着使用以下命令构建镜像:

#  docker  build  -t  attempt1   -f   Dockerfile.attempt1   .

然后在容器中运行镜像:

#  docker  run   -d   -p   5000:5000   --name   attempt1   attempt1

将浏览器的URL指向主机的IP地址,情况如下:

 


数字

第一次构建镜像,一共耗时95秒。其中,下载红帽企业Linux(简称RHEL)镜像与安装.NET SDK,这些文件一共490MB。最终,镜像大小为659MB。

一般而言,镜像的后续构建将更快,因为Docker化的镜像已经在主机上可用。改变源码后,我们再次运行构建。这一次构建镜像,大约耗时50秒,得到了相同大小的镜像,也是659MB。

镜像的大小很重要。因为镜像使用操作系统的存储空间,虽然空间便宜,但它仍然是有限的商品。当定期使用容器时,我们很容易忽略过时的镜像,然而它仍然在占用磁盘。如果你不注意的话,磁盘空间将很快用尽。

如何使镜像尽可能的小?

移除镜像不需要的部分

使用命令dotnet restore --no-cache可以消除任何缓存,这样镜像的大小下降到608.6MB,减少了50.6 MB,同比缩小超过7%。

在构建镜像之前构建应用

应用是在容器中运行镜像时构建.NET程序的。这耗时大约1.6秒——虽然时间不长,但却是在浪费时间。

在恢复之前插入的dotnet build命令,并在构建镜像之前构建应用,这样的话容器将会更快地启动。这个结果可在Dockerfile.attempt3中实现。

与此同时,镜像大小却增加到610.2MB,而我们还得运行dotnet build,虽然现在花这个时间,但却可在每次启动容器时受益。

运行Dotnet Publish命令

因为容器是一个运行时环境,那我们为什么不使用dotnet publish命令发布代码,然后把代码放入镜像呢?如果这样做的话,我们就没必要在镜像中安装.NET程序了。毕竟,我们需要的是一个可在任何地方独立运行的应用。

使用dotnet发布代码,会减少镜像大小和缩短容器启动时间。更改project.json文件,注释掉下图中红框的内容,这告诉编译器此文件为一个平台构建。您可以在下图中看到它:

接下来,我们使用dotnet publish -c Release -r rheh.7.2-x64发布代码,这会把所有的编译文件和运行时文件,放入一个文件夹,我们把此文件夹复制到镜像中。

因为我们不再需要安装.NET程序,只要一个包含RHEL文件的基础镜像即可,这样就减少了镜像的大小。这是Dockerfile的第四次迭代——Dockerfile.attempt4:

FROM registry.access.redhat.com/rhel7
RUN yum install -y libunwind
RUN yum install -y libicu
ADD bin/Release/netcoreapp1.0/rhel.7.2-x64/publish/. /opt/app-root/src/
WORKDIR /opt/app-root/src/
EXPOSE 5000
CMD ["/bin/bash", "-c", "/opt/app-root/src/dotnet_docker_msa"]

请注意,yum install命令将安装一些.NET需要的依赖文件,然后运行docker build命令,最终生成一个694.6MB的镜像。

谁需要缓存?

多次运行yum install命令,前一次操作将为后一次构建缓存。如果在每个yum install命令之后,我们立即清除缓存,效果将会很好。下面是Dockerfile的第五次迭代———Dockerfile.attempt5:

FROM registry.access.redhat.com/rhel7
RUN yum install -y libunwind && yum clean all
RUN yum install -y libicu && yum clean all
ADD bin/Release/netcoreapp1.0/rhel.7.2-x64/publish/. /opt/app-root/src/
WORKDIR /opt/app-root/src/
EXPOSE 5000
CMD ["/bin/bash", "-c", "/opt/app-root/src/dotnet_docker_msa"]

基于Dockerfile.attempt5构建的镜像,其大小减少到293.7MB,这比第一次构建缩小了55%。

堆叠命令

对Dockerfile做最后更改,我们需要堆叠yum install命令,具体内容如下所示:

FROM registry.access.redhat.com/rhel7
`RUN yum install -y libunwind libicu && yum clean all
`ADD bin/Release/netcoreapp1.0/rhel.7.2-x64/publish/. /opt/app-root/src/
`WORKDIR /opt/app-root/src/
`EXPOSE 5000
`CMD ["/bin/bash", "-c", "/opt/app-root/src/dotnet_docker_msa"]

最终得到的镜像大小为257.5MB,这比第一次构建缩小了60%。

下面是各个Dockerfile构建的镜像大小对比图:


总结

在探索新技术与新模式时,我们不能将早期的结果与最优做法相混淆。虽然早期的成功会给我们带来兴奋和鼓励,但它也可能使我们丧失进步的动力。勤奋,然后不断尝试,并且始终接受改进的建议,会帮助我们走的更远。

推荐一个培训


【3天烧脑式微服务架构训练营 | 上海站】本次培训涉及:DevOps?微服务?需要解决的问题、回归、微服务那些事儿、Spring Cloud简介、服务发现:Eureka、客户端负载均衡:Ribbon、声明式的客户端:Feign、使用断路器实现微服务容错:Hystrix、微服务网关:Zuul、统一配置管理:Spring Cloud Config、微服务跟踪:Spring Cloud Sleuth、Spring Cloud常见问题总结等,点击下面图片即可查看具体培训内容。


点击阅读原文链接可直接报名。

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

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

相关文章

滤镜与通道

一、滤镜:在原有图像的基础上,产生许多离奇而炫目的效果的工具集合。 二、滤镜分为两个部分: 1.内置的滤镜 2.外挂滤镜 三、滤镜组: 1.渲染:可以在图像中创建三维形状,云彩图案和三维光照效果。 2.风格化&a…

Zookeeper 详讲(笔记)1

client发送request给follower,follower将request给leader,leader将proposal(提议)发送给所有的follower,follower进行投票,每一个follower返回一个ack给Leader,leader将commit发送给所有的follower进行更新…

React的列表渲染

//9. 列表渲染class List extends React.Component{state {list:[1,2,3,4,5],list2:[{id:1,text:java},{id:2,text:js},{id:3,text:php},{id:4,text:python},{id:5,text:node}]}render(){const arr this.state.list;const arr2 this.state.list2;const listItem []const li…

Spring-SpringMVC父子容器

转载自 Spring-SpringMVC父子容器 前言 Spring&SpringMVC作为bean管理容器和MVC默认框架,是大多数web应用都会选择的方案。在其使用过程中,尽管基于xml的配置bean管理的方式依然存在,但在很多情况下已经采用的强大的注解功能将其替代。…

微服务的概念——《微服务设计》读书笔记

《领域驱动设计》(Eric Evans):告诉我们用代码呈现真实世界的重要性,并且告诉我们如何更好地建模。 持续交付理论:如何更有效及更高效地发布软件品,并指出保持每次提交均可发布的重要性。 六边形架构理论&a…

图标设计

一、图标的作用: 1.吸引用户的注意力 2.跨语言障碍,更好的实现人机交互。 二、图标的尺寸: 1.128128 2.4848 3.256256 4.3232 5.16*16 三、icon的中文意思就是图标,图形化表示。 四、图标的色彩数量: 1.颜色数&#xf…

React中后台管理系统添加广告分类显示不出来

问题描述 添加广告分类之后,其他的页面能正常显示,看不到广告页面,或者看到广告页面不停的转圈(打开network看到client的拦截信息) 问题分析 可能是浏览器中的拦截器拦截了请求 解决办法 关闭浏览器中的拦截广告插件

自定义机架感知

副本节点的选择(机架感知) 1、默认情况下 第一个副本在client所处的节点上,如果客户端在集群之外,(在win7上运行程序,写文件到集群上),随机选一个。 第二个副本和第一个副本在不同…

想要玩转实现负载均衡,你知道这些吗?

转载自 想要玩转实现负载均衡,你知道这些吗? 一、前言 互联网早期,业务流量比较小并且业务逻辑比较简单,单台服务器便可以满足基本的需求;但随着互联网的发展,业务流量越来越大并且业务逻辑也越来越复杂&…

按钮设计

一、按钮的常识: 1.状态:正常状态、鼠标放上去的状态、按下时的状态 2.按钮的格式:bmp、gif、png、jpg(应用程序中的) gif、png、jpg、swf(网页中的) 二、按钮的表现形式: 1.图形方式 2.文字方式 3.综合方式 4.动画方式 三、按钮的…

netcore实践:跨平台动态加载native组件

缘起netcore框架下实现基于zmq的应用。在.net framework时代,我们进行zmq开发由很多的选择,比较常用的有clrzmq4和NetMQ。 其中clrzmq是基于libzmq的Interop包装, NetMQ是100%C#的zmq实现(基于AsyncIO组件)。以上两种…

>>右移运算符

>>是右移运算符。假设x5,那么x的二进制为0101,x>>1表示x右移1位,即把最右边一位的1删掉,变为010,此时x2; 仍然设x5,二进制0101,x>>2表示x右移2位,把最…

如何实现酷狗音乐pc页面点击播放时,打开多个歌曲播放时,始终在一个播放页面,(标签页的通讯)

大致有两种思路, 一种是通过wind.open()方法传第二个参数, A页面: //点击跳转播放页函数function toPlayPage(){window.open(path/xxxx/xxxx?name音乐名,music)//第二个参数写一个定值,代表跳转页面都为music标签页&#xff0…

LOGO设计

一、什么是LOGO: 是用一种特殊文字或图像组成的大众传播符号,是人们相互交流的一种视觉语言。 二、LOGO的特征: 1.识别性 2.领导性 3.同一性 4.涵盖性 5.革新性 三、LOGO的格式: 1.为了便于以后更改:ai cdr eps 2.在使…

Redis进阶之内存模型

转载自 Redis进阶之内存模型 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站高并发不可或缺的一部分。 我们使用Redis时,会接触Redis的5种对象类型(字符…

React中jsx的规则

jsx语法规则:1.定义虚拟DOM时,不要写引号。2.标签中混入JS表达式时要用{}。3.样式的类名指定不要用class,要用className。4.内联样式,要用style{{key:value}}的形式去写。5.只有一个根标签6.标签必须闭合7.标签首字母(1).若小写字…

C#将引入可空的引用类型

是的,标题没错。C#其中一份新提案假定,所有的引用类型在默认情况下都是不可空的。在新语法下,你需要显式地标明一个引用变量是可空的,就像对值类型所做的那样。 和值类型一样,T是指不可空类型,而T?是指可…

Android中SlidingDrawer开发报错You need to use a Theme.AppCompat theme (or descendant) with this activity.

Android抽屉开发报错You need to use a Theme.AppCompat theme (or descendant) with this activity. 方法1: 创建的activity时,如果不是那么强烈需要继承自AppCompatActivity,就直接继承Activity。 如将activity继承自AppCompatActivity&…

特效字的设计

一、文字的属性: 1.字体:楷体、宋体、行书、小篆 2.字号:14px 16px 20px 3.颜色:red green 4.特殊属性:文字的粗体和斜体 二、特效字的表现形式 1.文字笔画的变形 2.文字的变化与对比 3.文字的特殊材质 4.综合形式 三、…

Redis进阶之持久化

转载自 Redis进阶之持久化 一、Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义。 我们知道,在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务&am…