网站开发好了 怎么发布,学校免费网站建设,网站建设国培心得体会,国外网站建设平台前面两篇#xff08;简单运维1、简单运维2#xff09;介绍了一些Windows Server Docker相关的基本运维知识。今天这一篇#xff0c;Windows Server Dockerfile葵花宝典#xff0c;涵盖了许多典型场景的Windows Server下的Dockerfile实例#xff0c;并且每一个都包含可直接…
前面两篇简单运维1、简单运维2介绍了一些Windows Server Docker相关的基本运维知识。今天这一篇Windows Server Dockerfile葵花宝典涵盖了许多典型场景的Windows Server下的Dockerfile实例并且每一个都包含可直接运行的代码实例完全开源并且新示例持续添加中。也希望大家能一起贡献经验。
示例源码
Github Repo: windows-dockerfile-lab
所有示例均经过Windows Server 2016环境实际测试。如果你需要了解如何配置一个Windows Server Docker的测试环境可以参考本系列的第一篇。
咱们从一些基础的Dockerfile命令说起
ENTRYPOINT和CMD
源码entrypoint_and_cmd
FROM microsoft/windowsservercore#usually, ENTRYPOINT should be fixed and CMD to be overridden when necessary
#always use the exec form instead of shell mode for ENTRYPOINT and CMD commands and paramsENTRYPOINT [ping, -n, 3]
CMD [baidu.com]#to build, execute: docker build -t entrypoint_and_cmd .
#to override CMD, execute: docker run --rm entrypoint_and_cmd 360.cn
每一个Dockerfile必须的两个命令是FROM命令和ENTRYPOINT/CMD。FROM命令无需多说就是指定当前docker image的爹是谁。这里重点说说ENTRYPOINT和CMD命令。ENTRYPOINT和CMD都可以用来指定docker容器实例启动时执行的启动程序这两个命令可以分别使用但是一般推荐组合使用。
以上面的示例为例这里组合使用了ENTRYPOINT和CMD运行时的效果是什么呢
如果我们在命令行执行docker run entrypoint_and_cmd启动这个docker容器它就相当于执行了下面这一行命令
ping -n 3 baidu.com
而如果我们用docker run entrypoint_and_cmd 360.cn启动这个容器则相当于执行了下面这条命令
ping -n 3 360.cn
也就是说通过CMD指定的部分在执行docker run时如果在参数中的image名字后面指定了一些参数这些参数会覆盖Dockerfile中定义的CMD后面的命令。
限于篇幅本文中演示的示例都是解决相同问题的最佳实践或者推荐实践。但是不会扩展讲太多为什么这是最佳实践但是我会附上一些参考资料感兴趣的朋友可以自行阅读。以上面的ENTRYPOINT和CMD的区别问题更多延伸内容请参考这篇文章Dockerfile: ENTRYPOINT vs CMD
ADD和COPY
源码add_and_copy
FROM microsoft/windowsservercore#on windows, ADD COPY almost the sameADD test_folder /test_folder_add
COPY test_folder /test_folder_copyADD test_folder /test_folder_add2
COPY test_folder /test_folder_copy2#unlike on linux, ADD doesnt support uncompressing zip files on windowsADD test_folder.zip /
COPY test_folder.zip /ADD test_folder.zip /test_folder_add2.zip
COPY test_folder.zip /test_folder_copy2.zip#how to ADD or COPY files containing space in the nameADD [file name with space.txt, /]
COPY [file name with space.txt, /file name with space copy.txt]#overwriting files also worksADD test.txt /test_overwrite_add.txt
ADD test_overwrite_add.txt /test_overwrite_add.txtCOPY test.txt /test_overwrite_copy.txt
COPY test_overwrite_copy.txt /test_overwrite_copy.txt#add files with wildchar also worksADD wildchar* /
RUN del wildchar*
COPY wildchar* /#the only obvious difference of ADD and COPY on windows is, you can use ADD for downloading files, but not COPYADD https://github.com/jquery/jquery/archive/3.2.1.zip /
ADD https://github.com/jquery/jquery/archive/3.2.1.zip /3.2.1_2.zipENTRYPOINT [cmd, /c, dir]#to build, execute: docker build -t add_and_copy .#to run, execute: docker run --rm add_and_copy
ADD和COPY也是几乎每个Dockerfile都会用到的命令它们的作用其实非常类似就是将文件或者目录从docker client执行的机器复制到正在编译的docker image中。这两个命令只有一些细小差别
ADD命令可用于从一个URL下载文件而COPY命令不行在Linux下的docker中ADD命令还有一个特殊能力就是如果ADD一个zip压缩包的话docker build时它能做自动解压缩但是在Windows Docker下没有这个效果
合并和减少RUN命令
源码merge_and_reduce_run
FROM microsoft/windowsservercore#run 2 commands in sequence even if the firts one fails, but not the second fails
RUN cd notexists md folder1#run 2 commands in sequence only if both succeed
RUN md folder2 md folder3#run 2 commands in sequence only if at least one succeeds
RUN md folder4 || cd notexists#if one line of RUN is too long, breakdown into multiple lines with \ at the end
#so that it is more friendly for code review
RUN echo 1 \ 2 \ 3 ENTRYPOINT [cmd, /c, dir]#to build, execute: docker build -t merge_and_reduce_run .
#to run CMD, execute: docker run --rm merge_and_reduce_run
在执行docker build的时候我们一定能注意到它有step 1step 2……每个step对于docker build来说实际上就是创建一个临时的docker image只执行了一个RUN所以如果我们不注意将每个细小的步骤都写一个RUN的话最后就会发现我们的Dockerfile的build变得非常慢因为步骤太多了。所以我们应该合理地合并没必要分开RUN的命令。
但是合并的两个命令到一个RUN里其实没表面那么简单。以上面的示例为例前面三个主要是说如何合并多个windows cmd命令
连接的两个命令代表即使前一个命令执行失败只要后一个命令执行成功这个RUN就不算失败连接的两个命令代表两个命令都必须执行成功整个RUN才成功||连接的两个命令代表只要任意一个执行成功就算整个RUN成功
注意所谓RUN成功指的是如果RUN失败的话docker build就会中断执行。因此我们要根据实际情况只允许可以失败的命令失败确保重要的命令必须成功。
当然除了合并windowns cmd命令我们也可以合并多个powershell命令到一个RUN例如
RUN powershell -command command1;command2;command3
或者如果有比较复杂的多个命令我们最好把多个命令写成一个.cmd或者.ps1脚本这样Dockerfile就只需要一个RUN了。
另外对于一行RUN太长的情况最好通过分割成多行书写这主要是为了方便做代码的Review这样在diff工具里能更清晰的显示到底改了什么参数。
到目前为止的sample其实都不不算Windows Docker特定的案例相比Linux下其实都很类似属于基础中的基础。下面我们就开始介绍一些Windows下特有的案例
unzip
源码unzip
FROM microsoft/windowsservercoreCOPY test_folder.zip /#unzipRUN powershell -Command expand-archive -Path c:\test_folder.zip -DestinationPath c:\ENTRYPOINT [cmd, /c, dir]#to build, execute: docker build -t unzip .#to run CMD, execute: docker run --rm unzip
前面我们说到ADD命令在Windows Docker下不支持解压缩zip文件。那么在Windows下如何解压缩呢最简单的方法就是使用Expand-Archive这个powershell命令。
set_hosts
源码set_hosts
FROM microsoft/iis#install ASP.NET 4.5RUN dism /online /enable-feature /all /featurename:IIS-ASPNET45 /NoRestart#deploy webapp
COPY iis-demo /inetpub/wwwroot/iis-demo
RUN /windows/system32/inetsrv/appcmd.exe add app /site.name:Default Web Site /path:/iis-demo /physicalPath:c:\inetpub\wwwroot\iis-demo#set entrypoint script
COPY scripts /scripts
ENTRYPOINT [C:\\scripts\\SetHostsAndStartMonitoring.cmd]#to build, execute: docker build -t set_hosts .
#to run, execute: docker run --rm --env-file ./hosts.env set_hosts
在前面的文章中我们提到过Windows下的Docker目前不支持docker run的--add-host参数。所以这里我们提供了一个基于环境变量这里用一个环境变量文件./hosts.env 设置Windows系统的hosts文件的方法。其中读取环境变量并设置hosts的代码其实就是下面的powershell脚本
If ($env:HOSTS) { $hosts $env:HOSTS.Replace(,, rn); $hosts | Set-Content C:\Windows\System32\drivers\etc\hostsApplied hosts: rn $hosts;
}
gacutil
源码gacutil
FROM microsoft/windowsservercore#copy minimized gacutil binary to container
COPY tools.zip /
RUN powershell -Command expand-archive -Path c:\tools.zip -DestinationPath c:\#install a DLL to GAC with gacutil
COPY Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll /
RUN /tools/gacutil.exe /i Microsoft.VisualStudio.QualityTools.UnitTestFramework.dllENTRYPOINT [cmd, /c, /tools/gacutil.exe, /l, Microsoft.VisualStudio.QualityTools.UnitTestFramework]#to build, execute: docker build -t gacutil .
#to run, execute: docker run --rm gacutil
gacutil是常用的通过命令行注册.NET DLL到GAC的工具。但是这个工具包含在.Net Framework SDK中并不包含于.NET Framework的分发库中。而为了注册几个DLL而让docker容器里面安装一个臃肿的.NET SDK实在有点难受。因此这个示例包含了从.NET Framework SDK中抽取出来的单独的gacutil工具只有94k大小。
enable_eventlog
源码enable_eventlog
FROM microsoft/windowsservercore#enable eventlog
RUN powershell.exe -command Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\WMI\Autologger\EventLog-Application Start 1# list latest 10 system eventlog
CMD powershell -command Get-EventLog system -newest 10 | Format-List#to build, execute: docker build -t enable_eventlog .
#to run, execute: docker run --rm enable_eventlog
这个太简单了不多解释了就是通过powershell设置了一个注册表值。
enable_wcf
源码enable_wcf
FROM microsoft/iis#install ASP.NET 4.5RUN dism /online /enable-feature /all /featurename:IIS-ASPNET45 /NoRestart#install WCF features, here we only enabled http and tcp protocol
#for the full list of features you can enable, execute dism /online /get-features on a windows server machine
RUN dism /online /enable-feature /featurename:WCF-HTTP-Activation45 /all
RUN dism /online /enable-feature /featurename:WCF-TCP-Activation45 /all#enable WCF protocols
RUN /windows/system32/inetsrv/appcmd.exe set config -section:system.applicationHost/sites /[0].[0].enabledProtocols:http,net.tcpENTRYPOINT [c:\\ServiceMonitor.exe, w3svc]#to build, execute: docker build -t enable_wcf .
#to run, execute: docker run --rm enable_wcf
在远古的SOA时代好像就在眼前悲伤WCF是.NET下最热门的技术之一现在是江河日下了。不过如何通过命令行enable WCF并设置IIS里的protocols呢 另外提一下上面这行ENTRYPOINT [c:\ServiceMonitor.exe, w3svc]其实不是必须的因为microsoft/iis这个image其实默认就是执行的这个ENTRYPOINT。这其实是在监控w3svc这个Windows Service的运行我们当然也可以用它来监控我们自己的Windows Service的这里顺便提一下。
set_iis_ssl
源码set_iis_ssl
FROM microsoft/iis#install ASP.NET 4.5RUN dism /online /enable-feature /all /featurename:IIS-ASPNET45 /NoRestart#setup SSL in IISADD iis-test.pfx \iis-test.pfxADD SetSSL.ps1 \SetSSL.ps1#set entrypoint scriptADD SetSSLAndStart.cmd \SetSSLAndStart.cmd
ENTRYPOINT [C:\\SetSSLAndStart.cmd]#to build, execute: docker build -t set_iis_ssl .
#to run, execute: docker run --rm -e SSL_PASStest -p 443:443 set_iis_ssl
通过命令行设置IIS的SSL这个可能干过的不多但现在SSL几乎是大多数主流网站的标配了在docker容器里部署网站也是必不可少的。其中主要的逻辑在SetSSLAndStart.cmd中调用SetSSL.ps1执行
cmd /c certutil -p %SSL_PASS% -importPFX c:\iis-test.pfx$addr[System.Net.Dns]::GetHostAddresses([System.Environment]::MachineName).IPAddressToString
$env:ssl_addr$addr[1]:443cmd /c netsh http add sslcert ipport%ssl_addr% certstorenameMY certhashC97E4D29C00D9B250EADCFE27D50F09FA76599B0 appid{4dc3e181-e14b-4a21-b022-59fc669b0914}New-WebBinding -name Default Web Site -Protocol https -HostHeader * -Port 443 -SslFlags 1
需要注意的是这里SSL_PASS包含的证书密码是读取的一个环境变量。因为pfx格式的证书中包含非常重要的私钥我们不可以将密码写在脚本中必须在docker run的时候传入。另外netsh http add sslcert的参数中certhash这个参数的值这里hardcode了iis-test.pfx这个证书的hash值如果你要安装的是你自己的证书需要用你自己证书的hash值替换。对于已经安装于当前机器的自定义证书我们可以通过下面的powershell命令列出所有的证书和它们的hash值
Get-ChildItem cert:\LocalMachine\My
再有这里的SSL我们是设置到机器当前的ip除了将SSL通过ipport参数绑定到ip我们也可以通过hostnameport将SSL绑定到hostname具体请参考netsh http add sslcert的相关文档。另外这个示例的部分代码参考了这篇文章
本篇完不过本文今后还会持续更新后面有新的Windows Server Dockerfile的武功心法我会陆续补充到这篇文章大家也可以关注相关的Github Repo获取更新。
相关文章
老司机实战Windows Server Docker1 初体验之各种填坑老司机实战Windows Server Docker2 docker化现有iis应用的正确姿势老司机实战Windows Server Docker3 单节点Windows Docker服务器简单运维上老司机实战Windows Server Docker4 单节点Windows Docker服务器简单运维下.Net大户的选择Windows Container在携程的应用Docker4Dev #6 使用 Windows Container 运行.net应用Docker基础入门及示例LinuxNginxAsp.net Core部署
原文地址http://www.cnblogs.com/teddyma/p/Windows-Server-Docker-5.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注