
上篇
下篇
和Linux下的Docker服务默认通过TCP 2375/2376端口执行docker命令不同,Windows Docker服务默认只支持本机基于命名管道来执行docker命令。如果调试完Windows Docker服务后,在命令窗口执行netstat -an,可以看到,服务器并不2375或者2376这样的网关。当然,我们可以通过设置daemon.json这个配置文件(关于如何设置daemon.json文件,请参考本系列的第一篇),来启动2375/2376端口。2375端口和linux下的2375端口一样,用于非TLS的远程连接;而2376则支持基于证书的安全连接。对于,开发检测环境,一般进入2375端口就行,而针对制造环境,则需要使用2376端口,基于TLS安全联结来远程管控Docker服务器。
要进入2375端口,只应该如下在daemon.json添加hosts配置项,然后重启Docker服务:
{
"hosts": ["tcp://0.0.0.0:2375"]
}
要开启2376端口也类似,就是稍微复杂一点,需要生成和配置证书,具体的可以参考微软的这篇官方文档这里就不详述了。
开启2375端口以后,可以借助在命令窗口执行如下的netstat命令,确保2375端口已经正确:
netstat -an | findstr 2375

如果返回类似下面,就说明已经在了:
TCP 0.0.0.0:2375 0.0.0.0:0 LISTENING
TCP [::]:2375 [::]:0 LISTENING
只是起初还不够,要允许内部机器无法远程访问本机的2375端口,我们需要添加防火墙的Inbound规则,可以借助以下的powershell命令打开:
New-NetFirewallRule -DisplayName 'Docker TCP Inbound' -Profile @('Domain', 'Public', 'Private') -Direction Inbound -Action Allow -Protocol TCP -LocalPort 2375
接下来,我们就可以尝试从调试了Docker client的远程机器,访问这台Windows Docker服务器了。Docker client有诸多跨平台版本,所以只要是相兼容的版本,我既可以从Windows的docker client,也可以从linux的docker client通过2375端口远程访问docker服务器。
当我们从当前机器,比如你的开发机访问一台远程docker服务器时,我们应该为docker client指定目标HOST。一般有两种方法:一种是可以借助在每个docker命令执行时,添加-H server_name_or_ip参数,另一种是修改DOCKER_HOST环境数组,这样,就不需要每个docker命令都带-H参数了。例如,下面的命令会列举远程服务器1.2.3.4的所有docker images:
docker -H 1.2.3.4 images
docker -H tcp://1.2.3.4 images
docker -H tcp://1.2.3.4:2375 images
上面的几种指定host的语法都是可以的,如果使用默认的2375端口docker windows 2375,最简洁的就可以用第一种,少打不少字符。如果要指定DOCKER_HOST环境数组,那么需要使用完整的格式,比如:

SET DOCKER_HOST=tcp://1.2.3.4:2375
开启远程访问期间,当应该从研发或者编译环境编译和发布docker镜像时,我们就不需要像上一篇中那么蛋疼的先copy发布出来的应用网页文件到docker服务器,然后在服务器上执行docker build了,只应该直接从开发环境执行docker build,就能直接在远程docker服务器上生成和运行docker镜像了。
docker的命令行工具,有许多子命令和参数。如果要经常编译和运行docker镜像,我们显然不希望每次都手打所有参数,例如,下面的命令编译一个docker镜像,并运行一个docker容器,每次手打一边实在没啥乐趣:
docker build -t iis-demo:1.0 .
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
为了简化这个过程,通常我们会写一些带参数的powershell脚本;或者,我们可以使用另一个docker的必备命令行工具:docker-compose。
docker-compose是一个docker官方发布的docker容器编排软件,用于借助yml格式的配置文件来简化docker命令的执行。例如,上面这两个编译并运行docker容器的类库,如果我们定义如下这个docker-compose.yml配置文件:
version: "2.1"
services:
iis-demo:
build: .
image: "iis-demo:1.0"
ports:
- "80"
networks:
nat:
ipv4_address: 172.24.128.2
volumes:
- "c:/temp:c:/inetpub/logs/LogFiles"
environment:
- "env1=LIVE1"
- "env2=LIVE2"
- "HOSTS=1.2.3.4:TEST.COM"
networks:
nat:
external: true
那么,我们就可以在docker-compose.yml所在的目录,通过以下这一条命令,就能自动编译docker镜像,并且运行一个docker容器了:

docker-compose up
是不是超级简洁?事实上,docker-compose几乎包装了所有通过docker命令行可以执行的参数,而且,一个docker-compose.yml文件,可以包括多个相关的docker镜像的配置,比如,你的这个应用可能依赖于某一个DB,或者另一个应用的,那么,写在一个yml文件里,就能很方便的一键编译,一键发布,一键关闭这些相关容器。限于篇幅,本文就不细说docker-compose各种功能了,大家可以参看官方文档和实例自行摸索。
这里简单讲一下,在windows下,如何安装docker-compose。
有了,docker-compose,我们也可以很简单的设定我们的docker服务器每次机器开启以后,自动运行指定的docker容器,只应该配置一个机器的开启脚本,每次机器推进后手动运行docker-compose up,就可以了。
有人可能想问,如何为windows设定手动开启脚本?一个简单的方式是,使用NSSM这个小软件。例如,下载nssm的exe到本地后,只应该在命令行执行:
nssm install "Docker Startup" command param1 param2 ...
就能将选定的命令变成自动开机执行的windows service了。是不是很方便?网上介绍NSSM也文章也好多的,大家可以搜索一些,这里我就给几个link,不过多介绍了:
微软官网,主要就这一篇文档介绍了windows容器的网络设定。介绍得貌似并不是很深入。主要来说,它介绍了Windows Docker支持的几种网络路径,例如:nat、transparent、overlay、l2bridge。其中,最常见的,大家最容易理解的docker windows 2375,也是Windows Docker服务安装后的默认路径是nat方式。简单的说,就是:

例如,在里面的样例中的docker run --ip 172.24.128.2 -p 80 ...里,-p 80这个参数都会避免docker命令执行时,动态分配一个宿主机上的网关,映射到容器ip的80端口上。如果我们执行里面的docker run命令,或者docker-compose up命令后,在命令窗口执行docker ps,可以提到以下的正在运行的容器:
0f0e07424d80 iis-demo:latest "C:\\SetHostsAndSta..." 5 minutes ago Up 4 minutes 0.0.0.0:39924->80/tcp windowsdockeriisdemo_iis-demo_1
其中,0.0.0.0:39924就是指的,对宿主机上任意ip的39924端口的访问,已经被映射到这个容器的子网ip的80端口了。
但是,这里有个坑,很深的坑,让我一度差点怀疑人生,甚至重装了机器的坑!!!——如果你在宿主机上的浏览器里,访问诸如:39924/iis-demo,按这个网关映射,你天真的以为能够访问到容器内的网站,尤其示玩过linux下容器的小伙伴,更绝对会觉得它能访问。但是,它显然不能!!什么理由呢?我为此一度差点崩溃,最后,在某个windows docker的github issuer中,有开发人员解释说,这个是因为windows版本的推动问题,在宿主机本机,这个映射的网关能够访问,但是,在宿主机内部,访问宿主机上的ip加这个网关是可以访问的!!只允许从内部访问!!WTF?这是什么鬼的道理?不过,反正,现状就是如此,也没法忍了。
除了使用动态分配的端口,如果我们把参数改成比如-p 80:80,那么能够借助宿主机的ip:80端口,访问到容器内的网页了。再提示一遍,记住,只能从宿主机内部访问!!
微软的官网文档,除了介绍了几种常见的网络体系如何配置,还提到了一些Windows版本的Docker相对于linux版本的docker没有实现的功能,下面的很多docker命令的参数,对Windows Docker无效:
其中,最遗憾的就是--add-host参数没有实现。--add-host参数先前是用于为容器内的平台的hosts文件添加静态dns解析的,这是一个非常常见的功用,没有它,部署到容器内的应用可能能够解析某些服务器名称或者域名。当然,我们可以自己实现类似用途,例如,在上一篇 docker化现有iis应用中,我们就推动了一个通过环境变量,传入,并修改hosts的简洁功能,从而导致了这个参数没推动带来的痛点。
上篇完
下篇 4 单节点Windows Docker服务器简单运维(下)
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-120472-1.html
越王苟剑