Docker 入门 第四部分: Swarms
先决条件
- 安装 Docker 1.13 或更高版本
- 按照第三部分中的描述安装Docker Compose。
- 安装了Docker Machine,Dcoker for Mac 和 Docker for windows ,但在Linux上你需要安装一下。在没有Hyper-V的win10之前的系统 以及 win10 home,使用Docker Toolbox。
- 阅读第一部分
- 在第二部分中学习如何创建容器
- 确保你已经将创建的
friendlyhello
镜像发布到registry。我们会在这里用到这个镜像 - 确保你的镜像已经作为容器被部署运行,运行这个命令,在你的信息中加入
username
,repo
, 和tag
:docker run -p 80:80 username/repo:tag
, 然后查看http://localhost/
。 - 从第三部分复制一份
docker-compose.yml
介绍
在第三部分,你使用了第二部分中编写的引用,并且,通过将它转换为服务来 定义它应该如何在生产环境中运行,在此过程中将其扩展5倍。
在这里,会将此应用部署到集群上,在多台机器上运行它。通过将多台机器加入被称为swarm的“Dockerized”集群,是多容器、多机器称为可能。
理解Swarm集群
一个swarm是一组加入集群的,运行容器的机器。在此之后,你可以继续按照习惯来使用docker命令,但现在这些命令案通过swarm manager运行在集群上。Swarm中的机器可以是物理机,也可以是虚拟机。加入Swarm后,他们被称为node
swarm manager 可以使用多种策略来运行容器,例如:
- “emptiest node” --最空闲的节点,部署容器时,使用被李勇最少的机器。
- “global” -- 去报每一台机器只获取指定容器的一个实例。
你可以在Conpose文件中指定 swarm manager 使用哪一种策略。
Swarm管理器是swarm中唯一可以执行命令,或授权其他机器worker加入swarm的机器。Worker只是用来提供生产力,它并没有权限告诉其他机器自己可以做什么,不可以做什么。
到目前为止,我们是在本地机器上以单机模式使用Docker。但Docker也可以使用swarm的切换到到swarm模式,开启swarm模式可以马上使当前机器成为Swarm管理器。之后,Docker就可以在你管理的swarm上执行你的命令,而不仅仅只是当前的机器。
部署swarm
一个swarm由多个节点组成,节点可以是物理机或虚拟机。
基本的概念相当简单:
- 运行
docker swarm init
可以开启swarm模式,并使当前的机器成为swarm管理器 - 然后在其他节点运行
docker swarm join
,使其作为worker加入swarm
下面我们使用虚拟机来快速创建一个双机集群并将其转换为swarm。
创建一个集群
本地虚拟机 (Mac, Linux, Windows 7 and 8)
本地机器上的虚拟机(MAC, LINUX, WINDOWS 7 AND 8)
你需要一个可以创建虚拟机的hypervisor,可以安装Oracle VirtualBox。
注意:如果你使用的是安装了Hyper-V的windows系统,例如Win10,那就不需要安装VirtualBox,使用Hyper-V即可。如果你正在使用Docker Toolbox,那么你应该已经安装了VirtualBox,可以愉快的开始了。
现在,使用VirtualBox驱动 用 docker-machine
创建两台虚拟机:
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
列出虚拟机并获取他们的IP地址
现在你已创建了两台虚拟机,名字叫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
初始化swarm并添加节点
第一台机器作为管理器,运行命令和验证workers加入swarm,第二台机器为worker。
你可以使用 docker-machine ssh
给你的VMs发送命令。使用 docker swarm init
将vm1
变为swarm管理器,其输入如下:
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
Swarm initialized: current node <node ID> is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token <token> \
<myvm ip>:<port>
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
✪ 2377 和2367端口
docker swarm init
和docker swarm join
始终使用2377端口(swarm管理器的端口),没有端口时采用默认端口。docker-machine ls
返回机器的IP地址和2367端口,2367端口是Docker守护进程的端口。这个端口被其他程序占用时会报错,
✪ 使用ssh出现问题?尝试一下 --native-shh参数
Docker的机器支持让你使用系统的SSH,如果因为一些原因,在给swarm管理器发送命令时遇到问题,只要在调用ssh命令时指定--native-ssh
参数即可。
docker-machine --native-ssh ssh myvm1 ...
如你所见,对 docker swarm init
的响应包含一个预置的 docker swarm join
命令,你可以在任何你要添加的节点上执行。复制这个命令,通过docker-machine ssh
把它发送给myvm2
,使myvm2
作为一个worker加入swarm。
$ 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集群上部署你的app应用
最困难的部分已经结束了。现在你只需要在你的swam上重复第三部分的过程即可。但要注意,只有swarm管理器可以运行Docker命令,worker只提供资源。
为 swarm管理器配置一个docker-machine shell
至此,你已经可以通过使用docker-machine ssh
发送命令,来与VMs进行通信。 另外一种选择是运行docker-machine env <machine>
来获取并运行一个命令,该命令配置当前的shell以和VM上的Docker守护进程通信。该方法适用于下面的步骤,因为它允许你使用本地的docker-compose.yml
文件“远程”部署app,而不需要将其复制到其他位置,
配置shell的命令因操作系统 Mac, Linux, or Windows 而有所不同,示例如下:
Mac、Linux
Mac或Linux上 DOCKER MACHINE的shell环境。
运行 docker-machine env myvm1
获取配置shell的命令,以和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)
运行给定的命令,来配置shell以和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
Windows
Windows上 DOCKER MACHINE的shell环境。
运行 docker-machine env myvm1
获取配置shell的命令,以和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
运行给定的命令,来配置shell以和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管理器上部署app
现在我们有了myvm1,我们可以将其作为swarm管理器,通过第三部分中使用的docker stack deploy
命令来把app 和docker-compose.yml
的本地拷贝部署到 myvm1. 这个命令可能需要几秒才可以完成部署,部署需要一些时间来完成。 在swarm管理器上使用docker service ps <service_name>
命令来验证所有的服务应被部署。
通过docker-machine
配置shell 链接到myvm1后,我们仍可以访问本地主机上的文件。确保和之前的目录相同,其下包括在第三部分中创建的docker-conmpose.yml
文件
和之前一样,运行下面的命令将app部署到myvm1上:
docker stack deploy -c docker-compose.yml getstartedlab
就这样,app被部署到到了swarm集群上。
注意:如果你的镜像保存在一个私有的registry上,你需要使用
docker login <your-registry>
登陆,然后你需要给上面的命令添加--with-registry-auth
参数,例如:
docker login registry.example.com
docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab
这会使用加密的WAL日志把登陆token从本地client传给部署了服务的swarm节点,有了这些信息,节点就可以登录到registry并拉取镜像。
现在你可以使用和第三部分中相同的docker命令。只是这次要注意服务(相关容器)在myvm1 和 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
连接VMs
- 设置你的shell像和myvm2通信一样,去和其他机器进行通信,只需要在相同或不同的shell中,重新运行
docker-machine env
,然后运行给定的命令连接到myvm2. 这里特指当前shell。如果你改用一个未配置的shell或打开一个新的shell,你需要重新运行命令。运行docker-machine ls
列出机器,查看他们是什么状态,获取IP地址并找出你连接的那一个(如果有的话)。要了解更多内容,请参考 Docker Machine getting started topics.- 或者你可以使用
docker-machine ssh <machine> <command>
的形式包装Docker命令,它可以直接登录到VM,但不会让你立即可以访问本地主机上的文件。- 在Mac和Linux上,你可以使用
docker-machine scp <file> <machine>:~
跨机器复制文件,但对于Windows用户,需要是一个类似于Git Bash的Linux终端模拟器来完成该工作。本文演示了
docker-machine ssh
和docker-machine env
,这些内容通过docker-machine
CLI可以在所有平台上使用。
链接你的集群
你可以使用myvm1或myvm2的IP地址来访问你的app。
你创建的网络在他们之间进行了共享并进行了负载均衡。运行docker-machine ls
来获取你的VMs的IP地址,并通过了浏览器访问它们,打开后刷新(或者使用curl
访问他们)。
会有五个容器ID会循环随机显示,这表明实现了负载均衡。
两个IP地址都可以工作的原因是swarm中的节点都参与了routing mesh(路由网格)。这确保了部署在在swarm中某个端口的服务使用将该端口保留给自己,无论实际运行的容器运行在哪个节点。下面是一张图表,对三节点集群上一个在8080端口发布的my-web
服务如何路由网格做了说明:
链接有问题?
请记住,要在swarm中使用 the ingress network(入口网络),那在开启swarm模式之前,你需要在swarm节点打开下面的端口:
- 端口 7946 TCP/UDP 用于容器网络发现
- 端口 4789 UDP 用于容器ingress network(入口网络)
迭代和扩展app
现在开始你可以做在第二、三部分学到的任何事情。
通过docker-compose.yml
可以扩展app。
通过编辑代码来改变app的行为,然后重新构建 并推送一个新的镜像。(为此,需要按照之前构建app、发布镜像的步骤进行操作)
在任一情况下,只需要简单的再次运行docker stack deploy
就可以部署这些更改。
你可以在myvm2上使用docker swarm join
把任何机器(物理机和虚拟机)加入swarm,将资源加入集群。之后只要运行docker stack deploy
,你的app就可以使用新资源了。
清理并重新启动
Stacks 和 swarms
你可以使用docker stack rm
来删除stack,例如:
docker stack rm getstartedlab
保留或删除swarm
在某些时候你可以删除swarm,如果你想使用删除,可以在worker上使用docker-machine ssh myvm2 "docker swarm leave"
,在管理器上使用docker-machine ssh myvm1 "docker swarm leave --force"
,但后面我们还要使用这个swarm,所以先保留它。
取消docker-machine shell变量设置
使用给定的命令你在取消当前shell中的docker-machine1
环境变量。
在Mac或Linux上的命令:
eval $(docker-machine env -u)
在Windows上的命令是:
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env -u | Invoke-Expression
这会断开docker-machine
创建的虚拟机的shell链接,之后你可以继续使用同一个的shell,现在使用本地的docker
命令(例如:在mac上的docker 或者 windows上的docker)。要了解更多,请参考Machine topic on unsetting environment variables。
重启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.
回顾和备忘
下面是节使用的终端的一个记录:
bash-3.2$ docker-machine create --driver virtualbox myvm1
Running pre-create checks...
Creating machine...
(myvm1) Copying /Users/johnmulhausen/.docker/machine/cache/boot2docker.iso to /Users/johnmulhausen/.docker/machine/machines/myvm1/boot2docker.iso...
(myvm1) Creating VirtualBox VM...
(myvm1) Creating SSH key...
(myvm1) Starting the VM...
(myvm1) Check network to re-create if needed...
(myvm1) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env myvm1
bash-3.2$ docker-machine create --driver virtualbox myvm2
Running pre-create checks...
(myvm2) Unable to get the latest Boot2Docker ISO release version: Get https://api.github.com/repos/boot2docker/boot2docker/releases/latest: x509: certificate signed by unknown auth
ority
Creating machine...
(myvm2) Unable to get the latest Boot2Docker ISO release version: Get https://api.github.com/repos/boot2docker/boot2docker/releases/latest: x509: certificate signed by unknown auth
ority
(myvm2) Copying /Users/johnmulhausen/.docker/machine/cache/boot2docker.iso to /Users/johnmulhausen/.docker/machine/machines/myvm2/boot2docker.iso...
(myvm2) Creating VirtualBox VM...
(myvm2) Creating SSH key...
(myvm2) Starting the VM...
(myvm2) Check network to re-create if needed...
(myvm2) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env myvm2
bash-3.2$ docker-machine ssh myvm1 "docker swarm init"
Error response from daemon: could not choose an IP address to advertise since this system has multiple addresses on different interfaces (10.0.2.15 on eth0 and 192.168.99.104 on eth
1) - specify one with --advertise-addr
exit status 1
bash-3.2$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.104:2376 v17.04.0-ce
myvm2 - virtualbox Running tcp://192.168.99.105:2376 v17.04.0-ce
bash-3.2$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.104:2377"
Swarm initialized: current node (x500bs7lrweto9chkg6xq2ybd) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-197eaghawf5wqunblowkmgwjojv38ugtmscs943xrrz0jk6bpc-4uor1vdi4cleb5kqq2ri7s17g \
192.168.99.104:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
bash-3.2$ docker-machine ssh myvm2 "docker swarm join \
> --token SWMTKN-1-197eaghawf5wqunblowkmgwjojv38ugtmscs943xrrz0jk6bpc-4uor1vdi4cleb5kqq2ri7s17g \
> 192.168.99.104:2377"
This node joined a swarm as a worker.
bash-3.2$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
fvenziy5o4xmziyzqxianzd65 myvm2 Ready Active
x500bs7lrweto9chkg6xq2ybd * myvm1 Ready Active Leader
bash-3.2$ ls
docker-compose.yml
bash-3.2$ cat docker-compose.yml
version: "3"
services:
web:
image: johndmulhausen/get-started:part1
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
bash-3.2$ docker-machine scp docker-compose.yml myvm1:~
docker-compose.yml
bash-3.2$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
Creating network getstartedlab_webnet
Creating service getstartedlab_web
bash-3.2$ docker-machine ssh myvm1 "docker stack ps getstartedlab"
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
kjeymj6rp0y8 getstartedlab_web.1 johndmulhausen/get-started:part1 myvm2 Running Running 24 seconds ago
dehkjrmu0fxn getstartedlab_web.2 johndmulhausen/get-started:part1 myvm1 Running Running 18 seconds ago
acnejfyy1cmg getstartedlab_web.3 johndmulhausen/get-started:part1 myvm2 Running Running 24 seconds ago
36lpsek707gj getstartedlab_web.4 johndmulhausen/get-started:part1 myvm1 Running Running 18 seconds ago
q5yb5uj97ef1 getstartedlab_web.5 johndmulhausen/get-started:part1 myvm2
bash-3.2$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.104:2376 v17.04.0-ce
myvm2 - virtualbox Running tcp://192.168.99.105:2376 v17.04.0-ce
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 6b039c13ef31<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 5bf07e68c49b<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> b98b5bda92e2<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 802ad212c6a0<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 60c1fe7b8cb6<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 6b039c13ef31<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 5bf07e68c49b<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> b98b5bda92e2<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 802ad212c6a0<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 60c1fe7b8cb6<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
bash-3.2$ curl http://192.168.99.105
<h3>Hello World!</h3><b>Hostname:</b> 6b039c13ef31<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
在第四部分,我们学习了swarm是什么、swarm中的节点如何成为管理器或worker、创建一个swarm、在其上部署一个应用程序。你可以看到第三部门的核心命令并没有改变,它们只是需要在swarm的master上运行。还可以看到Docker网络的强大能力,它可以跨容器实现负载均衡,即使它们运行在不同的机器上。最后,我们学习了如何在一个集群上迭代和扩展app。
下面是一些命令,可用于和swarm和VMs进行交互:
docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux)
docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10
docker-machine env myvm1 # View basic information about your node
docker-machine ssh myvm1 "docker node ls" # List the nodes in your swarm
docker-machine ssh myvm1 "docker node inspect <node ID>" # Inspect a node
docker-machine ssh myvm1 "docker swarm join-token -q worker" # View join token
docker-machine ssh myvm1 # Open an SSH session with the VM; type "exit" to end
docker node ls # View nodes in swarm (while logged on to manager)
docker-machine ssh myvm2 "docker swarm leave" # Make the worker leave the swarm
docker-machine ssh myvm1 "docker swarm leave -f" # Make master leave, kill swarm
docker-machine ls # list VMs, asterisk shows which VM this shell is talking to
docker-machine start myvm1 # Start a VM that is currently not running
docker-machine env myvm1 # show environment variables and command for myvm1
eval $(docker-machine env myvm1) # Mac command to connect shell to myvm1
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression # Windows command to connect shell to myvm1
docker stack deploy -c <file> <app> # Deploy an app; command shell must be set to talk to manager (myvm1), uses local Compose file
docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app)
docker-machine ssh myvm1 "docker stack deploy -c <file> <app>" # Deploy an app using ssh (you must have first copied the Compose file to myvm1)
eval $(docker-machine env -u) # Disconnect shell from VMs, use native docker
docker-machine stop $(docker-machine ls -q) # Stop all running VMs
docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images