经过上两篇实战Windows Server Docker系列文章,大家对安装Windows Docker服务以及如何打包现有IIS应用为docker镜像已经有了基本认识。接下来我们来简单讲讲一些最基本的运维问题。鉴于到目前为止我们只谈到单服务器部署。这里暂时不涉及集群模式下的复杂生产环境运维。

本主题将涵盖下面这些主要内容,由于这个主题包含的内容较多,将分成上下两篇发布:

上篇

  • 远程操作Windows Docker服务器
  • 自动化Docker编译和部署
  • Windows Docker网络配置和端口映射

下篇

  • 负载均衡和反向代理
  • 日志解析和监控

远程操作Windows Docker服务器

和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_HOST环境变量,那么必须使用完整的格式,比如:

SET DOCKER_HOST=tcp://1.2.3.4:2375

开启远程访问之后,当需要从开发或者编译环境编译和发布docker镜像时,我们就不需要像上一篇中那么蛋疼的先copy发布出来的应用网站文件到docker服务器,然后在服务器上执行docker build了,只需要直接从开发环境执行docker build,就能直接在远程docker服务器上生成和运行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 client的机器,并不需要安装于docker服务器;
  • 对Windows版本的docker-compose来说,它就是一个单个文件的.exe文件,你只需要从官网下载Windows版本的.exe文件,将文件名改成docker-compose.exe,然后随便放到任何方便访问的目录就可以了。我比较懒,一般直接丢到c:\windows\system32目录,那样就不需要设置额外的PATH路径,就能在任何当前目录下,在命令窗口直接执行了。

有了,docker-compose,我们也可以很简单的设置我们的docker服务器每次机器启动之后,自动运行指定的docker容器,只需要配置一个机器的启动脚本,每次机器启动后自动运行docker-compose up,就可以了。

有人可能想问,如何为windows设置自动启动脚本?一个简单的方法是,使用NSSM这个小工具。例如,下载nssm的exe到本地后,只需要在命令行执行:

nssm install "Docker Startup" command param1 param2 ...

就能将指定的命令变成自动开机执行的windows service了。是不是很方便?网上介绍NSSM也文章也很多的,大家可以搜索一些,这里我就给几个link,不过多介绍了:

Windows Docker网络配置和端口映射

微软官方,主要就这一篇文档介绍了windows容器的网络设置。介绍得其实并不是很深入。主要来说,它介绍了Windows Docker支持的几种网络模式,例如:nat、transparent、overlay、l2bridge。其中,最常用的,大家最容易理解的,也是Windows Docker服务安装后的默认模式是nat模式。简单的说,就是:

  • 宿主机上运行的所有的容器,都属于一个子网段,每个容器运行时,可以静态指定网段内可用的ip,或者自动分配一个网段内的ip;
  • 子网段内的ip,在宿主机外部无法直接访问,只能从宿主机上直接访问;
  • 可以通过docker命令的-p参数,设置静态或者动态的宿主机ip到容器ip的端口映射,这样宿主机的外部网络,就可以通过宿主机的ip和端口,间接访问到容器内的网站了;

例如,在上面的示例中的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端口了。

但是,这里有个坑,很深的坑,让我一度差点怀疑人生,甚至重装了机器的坑!!!——如果你在宿主机上的浏览器里,访问比如http://localhost: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
  • --dns-opt
  • --dns-search
  • --aux-address
  • --internal
  • --ip-range

其中,最遗憾的就是--add-host参数没有实现。--add-host参数原本是用于为容器内的系统的hosts文件添加静态dns解析的,这是一个非常常用的功能,没有它,部署到容器内的应用可能无法解析某些服务器名称或者域名。当然,我们可以自己实现类似功能,例如,在上一篇 docker化现有iis应用中,我们就实现了一个通过环境变量,传入,并设置hosts的简单功能,从而避免了这个参数没实现带来的痛点。

上篇完

下篇 4 单节点Windows Docker服务器简单运维(下)

老司机实战Windows Server Docker:3 单节点Windows Docker服务器简单运维(上)的更多相关文章

  1. 老司机实战Windows Server Docker:4 单节点Windows Docker服务器简单运维(下)

    上篇中,我们主要介绍了使用docker-compose对Windows Docker单服务器进行远程管理,编译和部署镜像,并且设置容器的自动启动.但是,还有一些重要的问题没有解决,这些问题不解决,就完 ...

  2. shell 脚本实战笔记(11)--Mysql在linux下的安装和简单运维

    前言: linux中安装mysql以及配置的管理, 基础的运维和管理还是需要会一些的. 这边作下笔记, 以求天天向上(^_^). 安装流程:*). 安装mysql-server1). 借助yum检索相 ...

  3. 老司机实战Windows Server Docker:2 docker化现有iis应用的正确姿势

    前言 上一篇老司机实战Windows Server Docker:1 初体验之各种填坑介绍了安装docker服务过程中的一些小坑.这一篇,我们来填一些稍大一些的坑:如何docker化一个现有的iis应 ...

  4. 老司机实战Windows Server Docker:5 Windows Server Dockerfile葵花宝典

    前面两篇(简单运维1.简单运维2)介绍了一些Windows Server Docker相关的基本运维知识.今天这一篇,Windows Server Dockerfile葵花宝典,涵盖了许多典型场景的W ...

  5. Windows Server 2003/2008 单网卡搭建VPN

    Windows Server 2003/2008 单网卡搭建VPN 1.打开[控制面板] --> [管理工具] --> [路由和远程访问] 2.鼠标右击你要管理的电脑 在弹出式菜单中选中[ ...

  6. docker启动单节点server模式的consul | Bitdoom

    原文:docker启动单节点server模式的consul | Bitdoom docker启动单节点server模式的consul 2017-09-07 环境:MacOSX, consul_0.9. ...

  7. 打造最强Windows Server 2012 给你比Windows 8更好的体验

    每一代微软桌面操作系统推出的时候,都会同步推出相应核心的服务器操作系统,稳定性会更强哈 所以改造一下,让它保留兼容和专业的同时又有桌面操作系统的美观和便捷,多好 咳咳,让我们来看看怎么把Server ...

  8. Windows Server菜鸟宝典之一:Windows Server 2008 R2 AD服务器搭建

        1.对于将要安装成为DC的服务器来讲,其系统配置以及基本的磁盘规划在此就不在累述了,但是关键的网络连接属性是必须要注意的.可以通过打开本地连接的属性来进行配置其IP属性.作为服务器DC的IP地 ...

  9. 老司机实战Windows Server Docker:1 初体验之各种填坑

    前言 Windows Server 2016正式版发布已经有近半年时间了,除了看到携程的同学分享了一些Windows Server Docker的实践经验,网上比较深入的资料,不管是中文或英文的,都还 ...

随机推荐

  1. iOS 事件传递(Touch事件)

    先总说如下: 1.当手指触摸到屏幕时,会产生UITouch对象和UIEvent对象. 2.这两个对象产生后会被传递到UIApplication管理的一个事件队列中. 3.再有UIApplication ...

  2. node.js--HTTP模块

    HTTP模块 node.js提供了一个创建自己服务器的方式,用起来很简单,首先引用http模块 //引用HTTP模板 var http = require('http'); 创建服务实例:http.c ...

  3. js格式化日期,获取当月的第一天,与最后一天.

    //格式化日期 function setDate(date){   y=date.getFullYear();   m=date.getMonth()+1;   d=date.getDate();   ...

  4. HTML5入门十---Canvas画布实现画图(一)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. Hibernate逍遥游记-第2章-使用hibernate.properties

    1. package mypack; import org.hibernate.*; import org.hibernate.cfg.Configuration; import java.util. ...

  6. 当使用VS CODE 时,如果窗口中打开的文件无法识别HTML的话,可以使用以下方法添加要识别的文件类型

    找到该文件并修改\Microsoft VS Code\resources\app\extensions\html\package.json{ "name": "html& ...

  7. unity3d AI&#39;s sight

    just finished -----by wolf96

  8. REST服务中的日志可视化(关键技术实现)

    引言 在系统构建完成之后,我们通常会使用REST API对外提供服务,在REST API的处理过程中经常会出现一些异想不到的问题(用户权限不足.参数不全.数据库访问异常等),导致请求失败,很多时候用户 ...

  9. 利用Azure Backup备份和恢复虚拟机(2)

    虚拟机注册之后,下一步就是将他们添加为受保护的项,在菜单底部,单击"保护"按照提示选择需要保护的虚拟机     单击"下一步",在这个页面中需要选择配置虚拟机配 ...

  10. 线性表(存储结构数组)--Java 实现

    /*线性表的数组实现 *特点:插入删除慢需要平均移动一半的数据,查找较快 *注意:有重复和无重复的数据对应的操作会有些不同 *注意数组一旦创建其大小就固定了 *Java集合长度可变是由于创建新的数组将 ...