Docker4Dev #6 使用 Windows Container 运行.net应用

关于d4d系列:之前这个系列叫做docker4dotnet,因为当时主要是为了能够探索在docker上运行.net应用;现在我觉得应该叫做docker4developer,因为我希望能够帮助更多的开发人员使用docker技术。今天这篇就算是新的Docker4Dev系列的开始,后续我会陆续发布更多的帮助开发人员使用容器的文章。


随着 Windows Server 2016 的正式发布,Windows Container也可以被部署到生产环境了。Linux Container存在的时间很久了,但是直到2013年Docker的出现我们才有了一种很简单的方式来使用Container技术,而在Windows平台上,类似的Container技术其实也存在很长时间了,但是由于Windows本身的一些特点,我们一直很难(就算经过复杂的配置)使用类似Linux Container的完整应用级别的隔离。这其中的原因我个人觉得主要是因为Windows的封闭性,造成社区无法按照自己的要求对其进行改进。2013年Docker发布后,对整个IT市场造成的冲击巨大,微软同样也感受到了威胁,对于Container技术的追赶也随即开始,让人感到欣慰的是,微软这次没有再次采用闭门造车的方式,而是采用了更加开放的方法与社区合作,接受社区中已有的工具和方法;Windows Container对于Docker工具链的良好支持就说了这一点。


因此,如果你熟悉Docker,那么这篇文章的内容对你没有什么新奇之处;但是如果你像我一样是个在Windows平台上工作多年的开发人员,就会发觉其中的好处。


你需要怎样的环境?

首先,搭建一个可以运行 Windows Container 的环境有3个选择:Windows Server 2016, Windows 10 和 Nano Server。另外,你需要了解 Windows Container 有2种不同的运行模式:Windows Server Container 和 Hyper-V 模式。这其中的区别请见下图:


其实在我们运行的时候,你是感觉不到其中的区别的,你仍然使用熟悉的 docker run 命令来启动容器,不过操作系统会根据上面表格所列自动的选择当前平台上的默认Container类型运行你的容器。


如果你希望尝试 Windows Container, 最简单的方式就是安装 Windows 10 (专业版或者企业版),然后安装 Docker for Windows 的工具。具体方法可以参考:https://docs.docker.com/docker-for-windows/


这里我准备了一个简单的PowerShell脚本,直接运心就可以完成启用Windows 10上的Container和Hyper-V功能,由于Windows 10只能运行Hyper-V Container,所以一定需要打开这个功能才可以。

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Enable-WindowsOptionalFeature -Online -FeatureName containers -All
Restart-Computer -Force


用Docker支持传统 .net 开发

之所以说“传统”,这主要是为了和 .net core做区分,因为.net core本身是跨平台的,所以完全可以使用 Linux Container 来运行(具体请见之前的d4d系列文章),也就不需要 Windows Container 的支持,当然你也可以使用 Windows Container 来运行 .net core,这完全没有问题。但是我觉得大多数 .net 开发人员还是更加关心自己的 .net 2.0/3.5/4.5 应用如何使用 Container。


在配置好以上所需要的开发环境之后,你就可以用 Visual Studio 进行传统.net应用的开发,并用docker完成Windows Container的镜像打包和运行了。只是有一点,你需要将你的Docker for Windows 工具切换到 Windows Container的支持上才行。


一旦完成了切换,你用 docker 所做的所有操作就都转向 Windows Container 了。(注:这其实只是现在的一个折中做法,未来的 docker 工具一定是可以同时操作 Windows 和 Linux 两种 Container 类型的)。


首先我们用 Visual Studio 2017 来创建一个 asp.net 4.5的应用程序,然后F5运行一下,确保程序可以正常启动。


现在,我们来添加一个Dockerfile,为了区分我把它命名为 Dockerfile.windows


以下是这个Dockerfile.windows的内容

FROM harbor-bj.devopshub.cn/microsoft/iis
SHELL ["powershell"]RUN Install-WindowsFeature Net-Framework-45-ASPNET ; \Install-WindowsFeature Web-Asp-Net45ARG source=.
WORKDIR 'c:\app'RUN Remove-Website -Name 'Default Web Site'
RUN New-Website -Name 'aspnet45docker' -Port 80 \-PhysicalPath 'c:\app' -ApplicationPool '.NET v4.5'EXPOSE 80
COPY $source .


注意几点:

1. 为了能够更快的下载基础镜像,我这里使用了LEANSOFT在北京的harbor站点;这里我已经预先同步了Docker Hub上的基础镜像。
2. 建议大家先预先下载这个基础镜像,因为 Windows 的基础镜像都很大 (WindowsServerCore 有4个G,NanoServer也有400M)
3. 这个Dockerfile中使用了 PowerShell 作为脚本引擎,所以后续你看到的命令都是 PowerShell 命令,比如: Install-WindowsFeature, New-Website 等等。

说实话,这个Dockerfile写得很顺手,毕竟之前对PowerShell的熟悉程度还是超过了shell script,这可能是 Windows 开发人员的好消息。


现在你就可以用熟悉的方式“发布站点”到本地文件夹,然后在里面进行 docker build 了,为了保证这个Dockerfile.windows可以被正常的复制到发布站点中,我还添加了一个Post-Build 脚本,确保每次发布都自动复制这个Dockerfile.windows 文件。


在发布完成的目标目录内运行以下命令就可以打包了

docker build -f Dockerfile.windows -t aspnet45web01:win-v1 .


好了,现在启动Container

docker run -itd -p 81:80 aspnet45web01:win-v1

进行到这里,用过 Docker for Windows 的同学一定会打开浏览器 http://localhost:81 来访问站点,但是你啥也看不到;这是因为 Docker for Windows 对 Windows Container 的支持还不够完整,没有进行 localhost 的自动映射,所以你需要使用 docker inspect 来获取容器的 ip 地址,然后通过 ip地址直接访问。

docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" <container id>


打开以上命令获取的ip地址,注意不要用 81 端口,而使用容器本身的80端口,因为我们是直接对容器进行访问。现在你就可以看到一个传统的.net 4.5应用运行在 Windows Container中了,如果你注意看了我的 Dockerfile,你就知道这个站点实际是跑在 IIS 上面的。


一点感受

Windows Container虽然已经可以投入生产了,但是就和 Docker 刚刚出现时一样存在一些问题,最大的问题是镜像文件太大。上面说了,WindowServerCore镜像4个G,这确实是有点夸张。我觉得微软的目的是为了能够用同样的镜像同时支持Windows Server Container和Hyper-V Container,毕竟Hyper-V Container是作为一个VM存在的,用一个完整的操作系统镜像就可以同时在2中模式上运行,这样当然是有好处的,因为大家不用考虑不同的运行模式而改用不同的基础镜像。但是我觉得从技术上,如果采用 Windows Server Container,微软应该是可以提供非常小的基础镜像,类似 docker 提供的空镜像,这样对第一次部署容器会有很大的性能提升。


但是话说回来,当你第一完成一个容器部署后,因为基础镜像已经存在,每次更新的数据就只有很小的部分(只是应用程序本身),这样后续的部署速度还是很快的。


另外,对于Hyper-V Container的存在的目的,我觉得除了可以提供更好的容器隔离能力(因为是VM,所以根本就是2台机器,不存在共享内核的问题),另外一个重要的目的就是在Windows平台上支持Linux Container的运行。希望微软的动作可以更快一点,毕竟你有全球最好的开发人员,没有什么是技术上做不到的。


相关文章:

docker4dotnet #1 – 前世今生 & 世界你好

docker4dotnet #2 容器化主机

docker4dotnet #3 .net猿和小鲸鱼的苹果山之旅

docker4dotnet #4 使用Azure云存储搭建高速 Docker registry

docker4dotnet #5 使用VSTS/TFS搭建基于容器的持续交付管道



推荐一个培训

基于Docker的DevOps实战培训】是由徐磊老师主讲的三天封闭式收费课程,地点北京,时间2017年03月24-26日。课程结合了徐磊老师多年来在DevOps上的实践经验和Docker技术,具有很强的实战意义。详细内容及报名方式点击“阅读原文”。


内容转载自公众号

DevOps
DevOps
了解更多

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

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

相关文章

jquery对象和DOM对象的相互转换详解

jquery对象和DOM对象的相互转换 在讨论jquery对象和DOM对象的相互转换之前&#xff0c;先约定好定义变量的风格如果获取的是jquery对象&#xff0c;那么在变量前面加上$,例如 var $varible jquery对象&#xff1b; 如果获取的是DOM对象&#xff0c;则定义如下&#xff1a; …

人脸注册源码faceregiste

人脸注册&#xff1a; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using AForge; using …

LC67---删除有序链表中重复的元素---牛客---JAVA

import java.util.*;/** public class ListNode {* int val;* ListNode next null;* }*/public class Solution {/*** * param head ListNode类 * return ListNode类*/public ListNode deleteDuplicates (ListNode head) {if(headnull)return head;ListNode temp head;wh…

破坏双亲委派机制的那些事

转载自 破坏双亲委派机制的那些事 前言 今天重读《深入理解Java虚拟》这本书&#xff0c;读到破坏双亲委派机制这一小节&#xff0c;其中有一段话&#xff0c;如下 双亲委派模型的第二次“被破坏”是由这个模型自身的缺陷所导致的&#xff0c;双亲委派很好地解决了各个类加…

Windows 容器

什么是容器 它们是隔离、资源控制且可移植的操作环境。 基本上&#xff0c;容器是一个隔离的位置&#xff0c;应用程序可在其中运行&#xff0c;而不会影响系统的其他部分&#xff0c;并且系统也不会影响该应用程序。 容器是虚拟化的下一个演化。 如果你在容器内&#xff0c;看…

人脸认证源码faceIdentify

人脸认证&#xff1a; using AForge.Video.DirectShow; using face; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Dr…

选择排序+推导过程

图解 代码实现 package com.atguigu.sort;import java.util.Arrays; import java.util.List;/*** 创建人 wdl* 创建时间 2021/3/21* 描述*/ public class SelectSort {public static void main(String[] args) {int []arr{101,34,119,1};System.out.println("排序前"…

Echart折线图 柱状图

echat_百度搜索 Examples - Apache ECharts Examples - Apache ECharts Examples - Apache ECharts 修改左侧的数据 点击右侧下载可以得到html页面 Examples - Apache ECharts Examples - Apache ECharts

Streaming的算法Reservoir Sampling

转载自 这是一个惊艳了我的算法题 Reservoir Sampling( Reservoir sampling ) 这是我在今年求职过程中面试的时候被问到的&#xff0c;因为之前很少接触Streaming的算法&#xff0c;在听到这个题目的时候被惊呆了&#xff0c;根本不能理解&#xff1a; 给一个Streaming…

软件定义数据中心—Windows Server SDDC技术与实践

《软件定义数据中心—Windows Server SDDC技术与实践》是国内第一本讲解微软Windows Server 软件定义数据中心的中文图书&#xff0c;书中系统、全面地介绍了微软Windows Server 软件定义数据中心各个模块&#xff08;SDS/SDN/SDC/容器&#xff09;的概念、技术和架构&#xff…

人脸登陆facelogin

人脸登陆&#xff1a; using AForge.Video.DirectShow; using face; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Dr…

插入排序+思路分析

图解 代码实现 package com.atguigu.sort;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class InsertSort {public static void main(String[] args) {int[] arr{101,34,119,1};insertSort(arr);}//插入排序public static void insertSort(in…

.NET 十五岁,谈谈我眼中的.NET

2002年2月13日&#xff0c;第一个版本随着visual studio.net的发布&#xff0c;今天已经走过15年, .net团队写了一篇文章&#xff0c;里面有一个视频&#xff0c;Anders Hejlsberg已是白发苍苍的老人&#xff0c;我也从刚出校门的码农长成软件开发工程师&#xff0c;我爱编程。…

中国朝代及首都

朝 代 起 讫 都 城 今 地 夏 约前2146-1675年 安邑 山西夏县 ①商 约前1675-1029年 亳 河南商丘 周 西周 ②约前1029-771年 镐京 陕西西安 东周 前770-256年 洛邑 河南洛阳 秦 前221-207年 咸阳 陕西咸阳 汉 ③西汉 前206—公元25 长安 陕西西安 东汉 25—220 洛阳 河南洛阳 三…

什么注解可以改变BigDecimal类型的字段返回的小数位数?

什么注解可以改变BigDecimal类型的字段返回的小数位数&#xff1f;_myme95的博客-CSDN博客 问题背景&#xff1a;我在数据库里有一个字段&#xff0c;是decimal(20,15)类型&#xff0c;但是我在代码里返回数据给前端时&#xff0c;我要返回5位小数给前端。那么怎么转换BigDecim…

ThreadLocal的非数据安全用法

启发于同学处理的bug&#xff0c;他遇到的问题是&#xff1a; “有三台Tomcat服务器&#xff0c;其中有一台Tomcat服务器出现这种情况&#xff1a;一个用户A登录了系统&#xff0c;如果有新的用户B接着登录系统&#xff0c;会把用户A的登录信息给替换成新用户B的信息。这造成无…

理解并从头搭建redis集群

部分开发人员工作当中只是在应用中使用redis&#xff0c;比如用来做数据结果的缓存。而且现在有很多不错的redis客户端工具(redisson)&#xff0c;基本上可以不用关注redis命令就可以完成相当部分的功能。所以可能会对如下这些问题关注点不够&#xff1a; 如何容灾&#xff1f;…

希尔排序+过程分析

图解 代码实现 package com.atguigu.sort;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class ShellSort {public static void main(String[] args) {int[] arr {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};shellSort(arr);}//使用逐步推导的方式来编写…

mybatis报错Type interface xxx.Dao is not...

今天在做mybatis的时候&#xff0c;遇到一个错误&#xff0c;大家看看这个错误吧&#xff1a;org.apache.ibatis.binding.BindingException: Type interface cn.mybatis_chop10_1.dao.IEmpDao is not known to the MapperRegistry.我前找找后找找&#xff0c;就是找不出来&…

win10打字突然变成繁体

win10打字突然变成繁体 按住CtrlShiftF&#xff0c;即可在繁体与为简体间切换。