firendlyhello
镜像,我们在本文中将使用这个已分享的公共镜像。docker run -p 4000:80 username/repo:tag
,使用你的用户名(username
)、仓库名(repo
)和标签名(tag
)对应替换即可。然后使用http://localhost:4000
进行访问docker-compose.yml
副本。通过第三部分的学习,你应该知道如何将我们在第二部分中编写的应用如何以服务的形式运行,并且拓展5个实例进程。
在第四部分中,我们将会把应用部署到集群中,运行在多台机器上。我们把多台机器相互组合成的docker集群称为swarm,可以部署多容器、多机器的应用。
Swarm就是一组运行docker的服务器组建而成的集群。创建后,你可以像之前那样使用docker指令,不过是需要在swarm管理节点上执行。集群中的节点可以是物理机也可以是虚拟机,他们加入集群后,被称之为节点。
Swarm有多种容器执行策略,比如“最空节点(emptiest node)”——该节点的资源利用率最低。或者“全局(global)”——确保每个节点之运行一个指定容器。你可以在docker-compose.yml
指定使用什么策略。
Swarm管理节点是唯一能执行docker指令,并且有权确认其他节点作为工作节点的节点。工作节点仅提供计算资源和能力,无权告诉其他节点能做什么和不能做什么。
到目前为止,你都是在单机上运行docker。其实docker也可以集群使用,这就是为什么要使用swarm。从现在开始,在swarm管理节点上执行的命令将在集群中运行,而不是仅在当前设备上运行。
一个swarm集群是有多个节点组成,可以是物理机也可以是虚拟机。其基本概念很简单:运行docker swarm init
开启swarm模式并使其成为管理节点,运行docker swarm join
将其他主机添加到该swarm集群中并成为工作节点。使用后面的指令,我们将了解到swarm在各种情况下的效果。我们当前使用虚拟机快速创建一个由两台设备组成的双机swarm集群。
你需要一个可以创建虚拟机的虚拟机管理程序,所以请在你的设备上安装VirtualBox。
注意:如果你使用的是像已经安装Hyper-v的window这样的系统,你不需要再安装VirtualBox。你可以直接使用Hyper-v即可,后面将介绍Hyper-V中的相关指令。如果你使用的是docker toolbox, 那么VirtualBox已经作为其一部分安装过了。
现在使用docker-machine
在VirtualBox上创建两台虚拟机:
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
首先,创建虚拟机共享的虚拟交换机,以便虚拟机能够互通。
Virtual Switch Manager
External
类型的虚拟交换机现在使用节点管理工具docker-machine
创建两个虚拟机:
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm2
你创建了两个虚拟机,名字分别为:myvm1
和myvm2
。
使用下面命令列举虚拟机并获取其IP地址。
docker-machine ls
下面是该命令的一个输出示例:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
第一台设备将作为管理节点,用于执行命令和授权其他设备成为工作节点,第二台设备作为工作节点。
你可以使用docker-machine ssh
向虚拟机发送指令,使用docker swarm init
指定让myvm1
成为管理节点的指令如下所示:
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
Swarm initialized: current node <node ID> is now a manager.
向swarm中添加节点可以使用下面的命令:
docker swarm join \
--token <token> \
<myvm ip>:<port>
要向swarm中添加管理节点,需要执行docker swarm join-token manager
,然后按照指示操作。
2377端口和2376端口
未设置
docker swarm init
和docker swarm join
的端口时,docker一般默认使用2377端口作为管理端口。
docker-machine ls
返回的机器IP地址包括端口2376,它是Docker守护程序端口。请勿使用此端口,否则您可能会遇到错误。
如果ssh指令错误,可以尝试一下
--native-ssh
选项由于某些原因无法向swarm管理节点发送指令时,
docker-machine
还可以使用本地系统的ssh服务。只需要在使用ssh指令时添加--native-ssh
选项即可:docker-machine --native-ssh ssh myvm1 ...
正如你看到的那样,你需要在新节点中执行docker swarm join
命令之前在某一个节点中执行docker swarm init
指令。复制这个指令,通过docker-machine ssh
命令发送到myvm2
中,使其成为一个工作节点:
$ docker-machine ssh myvm2 "docker swarm join \
--token <token> \
<ip>:2377"
This node joined a swarm as a worker.
恭喜!你已经创建了第一个swarm集群!
在管理节点上运行docker node ls
查看swarm中的所有节点:
$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd myvm2 Ready Active
rihwohkh3ph38fhillhhb84sk * myvm1 Ready Active Leader
离开swarm
如果你想重新开始,可以使用
docker swarm leave
移除每一个节点。
最难的部分已经完成了,现在我们只需要安装第三部分中的那样再次进行部署应用即可。只需要注意只能在swarm管理端执行docker命令,工作节点仅提供计算资源。
docker-machine
shell到目前为止,我们都是在使用docker-machine ssh
来包装docker命令。其实还有另一种方法,使用docker-machine env <machine>
来与一个docker主机取得通信。这个方法在接下来更加使用,因为它允许你访问本地主机的docker-compose.yml
文件,而不需要将其复制到其他地方。
键入docker-machine evn myvm1
,然后进行复制粘贴并运行,使用下面最后提供的语句将配置发送给到swarm管理节点。
这个命令在Mac、Linux和window中所有不同,如下面的示例中所示:
运行docker-machine env myvm1
与myvm1
通信并进行相关配置。
$ docker-machine env myvm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/sam/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell:
# eval $(docker-machine env myvm1)
执行下面的命令将当前配置发送到myvm1
节点中去:
eval $(docker-machine env myvm1)
执行docker-machine ls
来确定myvm1
处于激活状态,你应该得到类似下面的结果:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
运行docker-machine env myvm1
与myvm1
通信并进行相关配置。
PS C:\Users\sam\sandbox\get-started> docker-machine env myvm1
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.203.207:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\sam\.docker\machine\machines\myvm1"
$Env:DOCKER_MACHINE_NAME = "myvm1"
$Env:COMPOSE_CONVERT_WINDOWS_PATHS = "true"
# Run this command to configure your shell:
# & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
执行下面的命令将当前配置发送到myvm1
节点中去:
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
执行docker-machine ls
来确定myvm1
处于激活状态,你应该得到类似下面的结果:
PS C:PATH> docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * hyperv Running tcp://192.168.203.207:2376 v17.06.2-ce
myvm2 - hyperv Running tcp://192.168.200.181:2376 v17.06.2-ce
现在有了拥有swarm管理权限的myvm1
节点,你可以使用第三部分中学习到的docker stack deploy
指令和你本地的docker-complse.yml
文件副本进行部署应用。这个指令可能需要一些时间才能完成,应用也需要一些时间之后才能访问。可以在swarm管理使用docker service ps <service_name>
来确定所有服务都已经完成重部署。
你通过docker-machine
连接到了myvm1
中,你任然可以访问本地主机的文件。确保你当前与第三部分创建的docker-compose.yml
文件在相同的目录中。
只需要像前面那样再myvm1
中运行下面的指令进行部署应用。
docker stack deploy -c docker-compose.yml getstartedlab
然后这个应用部署再swarm集群中了。
注意:如果你的镜像存储在一个私有的注册附中,你需要先使用
docker login <your-registry>
指令进行登陆,然后再上面的指令中添加--with-registry-auth
选项。例如:docker login registry.example.com docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab
这会使用加密的
WAL
日志将登录令牌从本地客户端传递到部署服务的swarm节点。有了这些信息,节点就可以登录注册服务并拉取镜像。
Now you can use the same docker commands you used in part 3. Only this time notice that the services (and associated containers) have been distributed between both myvm1 and myvm2.
$ docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE
jq2g3qp8nzwx getstartedlab_web.1 gordon/get-started:part2 myvm1 Running
88wgshobzoxl getstartedlab_web.2 gordon/get-started:part2 myvm2 Running
vbb1qbkb0o2z getstartedlab_web.3 gordon/get-started:part2 myvm2 Running
ghii74p9budx getstartedlab_web.4 gordon/get-started:part2 myvm1 Running
0prmarhavs87 getstartedlab_web.5 gordon/get-started:part2 myvm2 Running
使用
docker-machine env
和docker-machine ssh
连接虚拟机:要让shell中可以连接像
myvm2
这样的不同的虚拟机,只需要重新运行相同(连接myvm2
)或不同(连接其他虚拟机,需更换相应节点名)docker-machine env myvm2
即可。如果没有运行shell或者打开新的shell终端,需要重新执行命令。可以使用docker-machine ls
命令列出节点,并查看其状态与ip地址,可以随意选择一个连入(如果有)。更多信息请查看docker machine
的入门主题。另外,可以使用
docker-machine ssh <machine> "<command>"
指令直接将命令写入到指定节点中去,不过该命令无法直接访问本地主机的文件。在Mac和Linux中,可以使用
docker-machine scp <file> <machine>:~
命令进行跨域复制文件,但是在window中需要使用Git Bash类Linux终端才行。本教程演示了
docker-machine ssh
和docker-machine env
,因为它们可以通过docker-machine CLI
在所有平台上使用。
你可以通过myvm1
和myvm2
中任意一个的IP来访问你的应用。
您创建的网络在它们之间共享并进行负载平衡。 运行docker-machine ls
获取虚拟机的IP地址,并在浏览器上访问其中任何一个,点击刷新(或使用curl
指令)。
5个容器ID随机循环出现证明了他们进行了负载均衡。
两个IP均能正常访问是因为在每个节点的入口都运行着相同的网络路由机制。这确保了swarm集群中的任意的点对应端口指向的均是相同服务,无论容器实际运行在哪个节点上。下图为三个节点的8080端口均指向一个名为my-web
的服务的网络路由示意图:
有连接异常?
有一点要注意:在使用swarm集群网络入口路由时,需要在节点激活swarm模式之前打开以下端口:
- 端口 7946 TCP/UDP 用于容器的发现与注册。
- 端口 4789 UDP 用于绑定集群入口路由。
现在你可以完成在第二部分和第三部中所学的一切内容。
通过改变docker-compose.yml
文件来拓展你的应用。
通过编辑相关代码来改变应用行为,然后重新构建、上传新的镜像。(通过最近收获的知识来完成构建、发布镜像等操作)
不管什么情况,只需要重新运行docker stack deploy
就可以完成这些改变。
你可以使用在myvm2
上执行的docker swarm join
指令将任何机器加入到swarm集群中,物理机、虚拟机均可,并将对应的容量添加到集群中。
可以通过docker stack rm
指令移除堆栈。例如:
docker stack rm getstartedlab
Swarm是保留还是移除?
在某些时候你不想保留Swarm,你可以通过在
worker
上执行ocker-machine ssh myvm2 "docker swarm leave"
和在manager
上执行docker-machine ssh myvm1 "docker swarm leave --force"
进行移除集群操作。但你在第五部分的时候需要这个集群,所以还先保留着。
docker-machine
shell环境你可以通过下面指令从docker-machine
主机环境中切换出来: Mac或者Linux命令:
eval $(docker-machine env -u)
window命令:
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression
在docker
命令行工具(比如window和mac的docker桌面端)中,这个指令用于从docker-machine
创建的虚拟机中解放出来,然后shell终端还可以做其他的事情。可以在docker主机主题中了解更多相关知识。
如果你关闭了本地主机,docker机器也会停止运行。可以运行docker-machine ls
指令查看机器状态。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Stopped Unknown
myvm2 - virtualbox Stopped Unknown
重启一台已停止的机器:
docker-machine start <machine-name>
例如:
$ docker-machine start myvm1
Starting "myvm1"...
(myvm1) Check network to re-create if needed...
(myvm1) Waiting for an IP...
Machine "myvm1" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
$ docker-machine start myvm2
Starting "myvm2"...
(myvm2) Check network to re-create if needed...
(myvm2) Waiting for an IP...
Machine "myvm2" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
全部评论