听说Windows支持原生docker了,大家一定都很兴奋。然而,大家想过没有,Windows Server Docker最适合什么场景呢?部署.NET Core应用?为什么不选择Linux下的docker?正常的决策者脑袋被门挤了才会花钱额外买Windows Server的license,用来部署.NET Core吧?所以,在本人看来,Windows Server Docker最大的价值,还是在于部署传统基于WindowsServerCore的应用。这样的应用一般有两大类,一类是基于iis的网站应用;另一类是Windows Service。本文主要关注基于iis的应用的docker部署。 那么,部署一个iis应用到docker,是不是只要起一个iis的docker容器实例,远程连接,并且,copy文件进去,能通过容器内的iis访问就行了?如果,有人问这样的问题,那么,说明他还完全没有容器的思维。上面说的这个,其实就成了将容器当虚拟机用了,这将极大地限制了docker原有的灵活扩展能力。因此,可以说是使用Windows docker最糟糕的姿势之一了。 要正确部署一个iis应用到Windows Server Docker,并不是表面那么简单。限于篇幅,并且为了更专注,本文先不涉及容器编排、负载均衡、images的构建和管理等问题(这些要考虑的问题还有很多,以后我们单独聊),这里只关注如何将一个基于iis的应用正确运行于单个Windows Server Docker实例中。即便如此,一般至少也要解决下面这些问题:
应用示例为便于理解和演示,我在github上写了一个简单的示例应用:windows-docker-iis-demo 这个应用只包含一个页面,在我本机运行时,显示类似下面的内容: Hello Docker!Configuration:env1=Dev (from appSettings in web.config)env2=Dev (from OS environment variable)Content of C:\Windows\System32\drivers\etc\hosts:# Localhost (DO NOT REMOVE)127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopback 其中env1为web.config中的appSettings值,env2读取的系统环境变量,页面最下面打印出当前Windows系统的的hosts。 定义Dockerfile如下:
我们分别来理解一下Dockerfile每一段的含义:
启动脚本SetHostsAndStartMonitoring.cmd的内容如下: powershell -executionpolicy bypass -Command 'If ($env:HOSTS) { $hosts = $env:HOSTS.Replace(':', ' ').Replace(',', '\r\n'); $hosts | Set-Content 'C:\Windows\System32\drivers\etc\hosts'; 'Applied hosts: ' + $hosts' }powershell -executionpolicy bypass -Command 'if ($env:env1) { (Get-Content 'c:\inetpub\wwwroot\iis-demo\web.config').replace('Dev', $env:env1) | Set-Content 'c:\inetpub\wwwroot\iis-demo\web.config' };c:\ServiceMonitor.exe w3svc 其中,第一部分读取HOSTS这个系统环境变量,覆盖当前系统的hosts文件;第二步读取env1环境变量,覆盖web.config中的对应配置;最后调用继承自microsoft/iis image的ServiceMonitor.exe命令,监控iis主进程,直到其退出。 下面,我们来试着build这个docker。因为到目前为止(本系列的第一篇+第二篇),我们还只能从这台Windows Server机器上执行docker命令,以后的文章会讲到如何从远程server build以及如何集成到CI工具进行build,这里先绕过。我们在VS2015中编译这个webapp,并且发布到publish目录。然后,复制整个windows-docker-iis-demo目录到这台docker宿主机的C盘根目录,以便进行docker build。这个当然不是build docker image的正常姿势,只是因为我们还没提到其他方式,我们先粗糙一点,把它build出来,以便可以运行。 在我们的Windows Server 2016机器上,打开一个administrator模式的powershell窗口,cd到c:\windows-docker-iis-demo目录,然后执行docker build命令制作image:
编译成功后,执行docker images,可以看到多了一个iis-demo:1.0的docker image。接着,让我们在宿主机的C盘创建一个temp目录(为下面的volume使用,mount到容器内部的iis日志),然后执行下面的命令运行一个iis-demo的docker instance: docker run --ip 172.24.128.2 -p 80 -v 'c:/temp:c:/inetpub/logs/LogFiles' -e 'env1=LIVE1' -e 'env2=LIVE2' -e 'HOSTS=1.2.3.4:TEST.COM' iis-demo:1.0 这里的参数分别表示:
稍等片刻,等待容器实例运行,然后在宿主机的浏览器中访问,可以看到如下的内容:
对比前面在开发环境运行的结果,我们可以看到有一些有意思又诡异的区别:
另外,在宿主机的c:\temp目录,我们可以看到从容器实例写道外部的iis log。 好了,看看至此我们已经解决了哪些最开始提到的问题了:
应该说,我们已经解决了大多数前面提到但实例运行时需要解决的问题了。然而,别忘了,这一篇里,我们只针对单服务器,单容器实例。在实际的部署案例中,是绝不允许单点,无法扩展的。 后面几篇,我会展开讲讲这一篇跳过的一些非常重要的话题,例如网络配置、远程管理、负载均衡、实时监控、以及更高级的容器编排和集群实现等等,敬请期待! |
|