640?wx_fmt=png

出品丨Docker公司(ID:docker-cn)

编译丨小东

每周一、三、五晚6点10分  与您不见不散!


说在前面


目前,有大量的应用程序以 Docker 容器的形式运行在 Windows Server 2016 上,但 Windows 容器一直与 Linux 容器在性能方面存在着一些细小的差距。但是,在已经到来的 Windows Server 2019 中,它弥补了大部分的性能差距,因此现在的 Windows Docker 容器几乎与 Linux 容器旗鼓相当。接下来,我将介绍余下的内容,点击下列标题了解前一部分内容:


&


使用 VIP 服务发现


接下来将介绍 Docker Swarm 模式的第二个增强功能。Swarm 通过 DNS 提供服务发现,因此容器可以通过服务名称相互引用,Docker 将其解析为容器的 IP 地址。这是一种使用现有技术连接服务的非常简单的方法,因此它对于在容器中运行的应用程序是透明的。


服务发现有两种模式:VIP 和 DNSRR 模式。VIP 模式使用的是虚拟 IP 地址,当容器进行 DNS 查询时,它在响应中获得单个 IP 地址,该地址是虚拟地址。网络层实际上是将其路由到运行服务副本的某一个容器中。DNSRR 模式也是 DNS 循环,DNS 响应包含所有容器IP 地址的列表,以随机顺序提供负载均衡。


VIP 模式是更好的选择,因为它不会对缓存 DNS 响应的客户端(几乎每个DNS客户端)造成任何问题。如果在服务中替换容器,则虚拟IP地址保持不变,并且客户端请求将始终路由到活动的容器。如果客户端缓存响应,DNSRR 模式可能会出现问题,因为响应是单个容器的 IP 地址,当更换该容器时,客户端无法访问该服务,直到 DNS 缓存过期并获得新响应。


DNSRR 有很好的用途,特别是对于使用 DNS 发现集群中其他节点的集群技术。在 Docker Swarm 模式中管理负载均衡和扩展集群也涵盖了这一点。


Windows Server 2016 仅支持 DNSRR 服务发现,但 Windows Server 2019 不仅支持 DNSRR 服务发现还支持 VIP 服务发现。与入口网络一起,这意味着您可以在群集模式下运行高度可用、高度可扩展和弹性的服务。


我已经为 Docker 示例投票应用程序添加了 Windows 1809 版本。您可以使用此 Docker 应用栈文件在 Windows 1809 版本的集群上运行该应用程序,该文件使用入口网络和 VIP 服务发现:


Docker 示例投票应用程代码:https://github.com/dockersamples/example-voting-app


iwr -useb -outf docker-stack-windows-1809.yml ` 

 https://raw.githubusercontent.com/sixeyed/example-voting-app/master/docker-stack-windows-1809.yml

 

docker stack deploy -c .\docker-stack-windows-1809.yml vote


现在,您可以在集群中的任何节点上浏览到在 5000 端口上的投票应用程序,并且四个投票应用程序容器中的一个容器将处理该请求:


640?wx_fmt=png


做出选择后,应用程序将向运行在容器中的 CNCF-incubating NATS 消息队列发送消息,然后三个消息处理程序容器中的一个容器将处理消息并将数据存储在与 mysql 兼容的 TiDB 数据库中 —— 在容器中运行。浏览到 5001 端口,您将看到来自投票结果应用程序的总数。


这些都是基于 1809  版本的 Windows Nano Server 基础镜像构建的小镜像。

640?wx_fmt=png


卷挂载具有可用的目录路径


Docker 卷(Volume)是您将存储与容器生命周期分开的方式。您将卷附加到容器,它将作为容器文件系统中的一个目录出现。您的应用程序写入“C:\ jenkins”(或您安装的任何路径)并且数据实际存储在卷中,该卷可能存储在 Docker 主机上。就像服务器上的 RAID 阵列,或数据中心中的单独存储单元,或云存储服务。


容器内的挂载应该对应用程序透明,但实际上在 Windows Server 2016 中使用的是符号链接目录,这就导致了一些问题。


这是一个基本问题,首先运行交互式 Windows Server Core 2016 容器,Docker 卷将本地目录挂载到容器内的目标 C:\ mount 中:

docker container run -it --rm ` 

  -v C:\temp:C:\mount `

  microsoft/windowsservercore:ltsc2016


检查容器中的目录列表,你会看到“C:\ mount”实际上是 SYMLINKD(符号链接目录)类型,它映射到一个危险的文件路径“ [\\?\ContainerMappedDirectories…”:

Microsoft Windows [Version 10.0.14393] 

(c) 2016 Microsoft Corporation. All rights reserved.

 

C:\>dir C:\ 

 Volume in drive C has no label.

 Volume Serial Number is 5AC2-AFC5

 

 Directory of C:\

 

11/22/2016  11:45 PM             1,894 License.txt 

10/22/2018  01:01 PM    <SYMLINKD>     mount [\\?\ContainerMappedDirectories\C4CCB043-FA0A-49DE-88F0-F408917EC284] 

06/28/2018  07:55 PM    <DIR>          PerfLogs 

06/28/2018  08:04 PM    <DIR>          Program Files 

07/16/2016  02:18 PM    <DIR>          Program Files (x86) 

10/22/2018  01:01 PM    <DIR>          Users 

10/22/2018  01:01 PM    <DIR>          Windows 

               1 File(s)          1,894 bytes  

               6 Dir(s)  21,218,250,752 bytes free


这会导致底层语言尝试解析符号链接并使用目标路径的应用程序出现问题,因为它们会识别双反斜杠和问号。


这个问题在 Windows Server 2019 中将不再是问题。在运行 Docker 的 1809 版本的机器上运行相同的命令:

docker container run -it --rm ` 

  -v C:\temp:C:\mount `

   mcr.microsoft.com/windows/servercore:1809

现在列表显示“C:\ mount”作为标准目录:

Microsoft Windows [Version 10.0.17763.1] 

(c) 2018 Microsoft Corporation. All rights reserved.

 

C:\>dir C:\ 

 Volume in drive C has no label.

 Volume Serial Number is 961D-F4E8

 

 Directory of C:\

 

09/15/2018  10:42 AM             5,510 License.txt 

10/04/2018  11:08 AM    <DIR>          mount 

09/15/2018  05:44 PM    <DIR>          Program Files 

09/15/2018  10:42 AM    <DIR>          Program Files (x86) 

09/15/2018  10:45 AM    <DIR>          Users 

10/22/2018  01:05 PM    <DIR>          Windows 

               1 File(s)          5,510 bytes

               5 Dir(s)  21,242,155,008 bytes free


它仍然是一个使用容器外部存储的卷,由Docker管理,但现在它对应用程序完全透明。将我的 Windows Server 2019 的 Jenkins Dockerfile 与我的 Windows Server 2016 的 Jenkins Dockerfile 进行比较,你会发现它更容易阅读。

640?wx_fmt=png


卷挂载可以覆盖现有目录


Windows Server 2016 还存在一些其它的关于卷的问题。一个是如果该目录已经存在于 Docker 镜像中,则无法使用目标目录进行卷挂载操作。

许多应用来说都存在这个问题,,因为配置目录附带了镜像中的默认配置文件。在 Linux 上,您可以运行容器并使用卷的内容覆盖 config 目录。但在 Windows 2016 上您就不能这样做了,您必须编写一个 Dockerfile 来打包你的自定义配置。


或者使用 Web 服务器,如果您想使用默认镜像,又想从卷中提供自己的内容,那么您将从 Windows Server 2016 中收到错误提示:

PS> docker container run -d ` 

  -p 8041:80 `

  -v C:\web:C:\nginx\html `

  sixeyed/nginx:windowsservercore-ltsc2016

 

13f9f189ef9b5a73b700b79556aa002fd8fb3ce5f70ced21e364d5b4ac708446

 

C:\Program Files\Docker\docker.exe: Error response from daemon: container 13f9f189ef9b5a73b700b79556aa002fd8fb3ce5f70ced21e364d5b4ac708446 encountered an error during CreateContainer: failure in a Windows system call: The directory is not empty. (0x91) extra info: 


您得到的错误消息 —— 该目录不是空的。


在 Windows Server 2019 中解决了该问题。现在,您可以在现有目录上挂载卷并替换其内容,因此容器可以查看卷的内容而不是镜像中的内容:

PS> docker container run -d ` 

  -p 8041:80 `

  -v C:\web:C:\nginx\html `

  sixeyed/nginx:windowsservercore-1809

 

42ed3441e2e2cebc37cac6ecac927ece45c65f877d4c072be4f5ff2dcef7ddcf 


在 Windows Server 2019 中将不再出现该问题的错误提示了。 现在,当我浏览应用程序时,我会看到我的网页,而不是默认的 Nginx 页面:


640?wx_fmt=png

640?wx_fmt=png


点击下列标题,阅读更多干货



如果本文对你有帮助,欢迎分享到朋友圈!获取更多Docker实用技巧,扫描下图二维码!

 640?wx_fmt=png

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐