在此部分中,您将学习分布式应用程序层次结构的顶层:堆栈。堆是一组相互关联的服务,它们共享依赖关系,并且可以放在一起协调工作。单个堆栈能够定义和协调整个应用程序的功能(尽管非常复杂的应用程序可能希望使用多个堆栈)。
好消息是,当您创建Compose文件并使用时,docker stack deploy
命令一直在使用堆栈。但这是在单个主机上运行的单个服务堆栈,这通常在生产中是不会发生的。在这里,您可以学习使多个服务相互关联,并在多台计算机上运行。
添加新服务并重新部署
将服务添加到我们的docker-compose.yml
文件很容易。首先,让我们添加一个免费的可视化服务,让我们看看swarm如何调度容器。
-
docker-compose.yml
在编辑器中打开并用以下内容替换其内容。请务必更换username/repo:tag
镜像详细信息。version: "3" services: web: # replace username/repo:tag with your name and image details image: username/repo:tag deploy: replicas: 5 restart_policy: condition: on-failure resources: limits: cpus: "0.1" memory: 50M ports: - "80:80" networks: - webnet # 新添加的服务 visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: - webnet networks: webnet:
这里新添加了一个
web
同等级的应用,名称为visualizer
。注意这里有两个新东西:一个volumes
为键的键值,让可视化工具访问Docker的主机套接字文件,以及placement
为键的键值,确保该服务只能在swarm管理器上运行 - 绝不能是一个worker。这是因为这个服务的镜像是由Docker创建的一个开源项目构建的,它用图将在swarm运行的Docker服务展示出来 -
确保您的shell配置为与
myvm1
通信,(完整示例在此处)。运行
docker-machine ls
以列出计算机并确保已连接到myvm1
,注意命令输出的myvm1
行active列为*时才代表你将当前shell配置成功。-
运行
docker-machine env myvm1
,然后运行给定命令以配置shell。在Mac或Linux上,命令是:
eval $(docker-machine env myvm1)
在Windows上,命令是:
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
-
在Swarm管理器上运行
docker stack deploy
命令,并更新服务:$ docker stack deploy -c docker-compose.yml getstartedlab Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm) Creating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)
-
查看可视化工具。
在Compose文件中我们定义的
visualizer
服务的发布在端口8080上。通过运行docker-machine ls
获取其中一个节点的IP地址加上端口8080,您可以看到visualizer
可视化工具:visualizer
正如您所期望的那样,以单个副本运行在管理器上,并且5个web
实例分布在整个集群中。您可以通过运行docker stack ps <stack>
来证实:docker stack ps getstartedlab
visualizer
可视化工具是一个独立的服务,可以在任何app的堆栈中添加visualizer
服务,它不依赖于任何其他东西。现在让我们给我们的应用添加一个依赖的服务:Redis的服务,提供访客计数器。
持久化数据
让我们再次通过相同的工作流程来添加Redis数据库来存储应用数据。
-
保存这个新
docker-compose.yml
文件,最后添加一个Redis服务。请务必更换username/repo:tag
镜像详细信息。version: "3" services: web: # replace username/repo:tag with your name and image details image: username/repo:tag deploy: replicas: 5 restart_policy: condition: on-failure resources: limits: cpus: "0.1" memory: 50M ports: - "80:80" networks: - webnet visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: - webnet redis: image: redis ports: - "6379:6379" volumes: - "/home/docker/data:/data" deploy: placement: constraints: [node.role == manager] command: redis-server --appendonly yes networks: - webnet networks: webnet:
Redis在Docker库中有一个官方图像,并且已被授予简称
redis
,因此username/repo
这里没有注释。Redis端口6379已由Redis预先配置为从容器暴露给主机,在我们的Compose文件中,我们将它从主机暴露给外界,因此您实际上可以输入任何节点的IP将节点导入Redis Desktop Manager并管理此Redis实例。最重要的是,
redis
规范中有一些事情会使数据在此堆栈的部署保持不变:-
redis
总是在管理器上运行,所以它总是使用相同的文件系统。 -
redis
定义本机文件系统中任意目录作为Redis存储数据的位置。(回想一下docker-machine env myvm1
输出的命令将当前命令行配置为与myvm1通信)
总之,这是在本机的物理文件系统中为Redis数据创建“真实来源”。如果没有这个,Redis会将其数据存储到容器的文件系统的
/data
目录,如果重新部署该容器,数据将会被删除。真相:
- 在Redis服务上的
placement
约束,确保它始终使用相同的主机。 - 您创建的容器允许容器访问
./data
(在本机上)作为容器内的/data
(在Redis容器内)。当堆栈部署后时,存储在./data
本机上的文件仍然存在,从而实现持久性。
你现在可以开始部署一个依赖于redis服务的堆栈。
-
-
在管理器上创建一个目录
./data
:docker-machine ssh myvm1 "mkdir ./data"
-
确保您的shell配置为与
myvm1
通信(完整示例在此处)。运行
docker-machine ls
以列出计算机并确保已连接到myvm1
,(active 列值为*)。-
如果需要,请重新运行
docker-machine env myvm1
,然后运行给定命令以配置shell。在Mac或Linux上,命令是:
eval $(docker-machine env myvm1)
在Windows上,命令是:
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression
-
再执行一次
docker stack deploy
。$ docker stack deploy -c docker-compose.yml getstartedlab
-
运行
docker service ls
以验证三个服务是否按预期运行。$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS x7uij6xb4foj getstartedlab_redis replicated 1/1 redis:latest *:6379->6379/tcp n5rvhm52ykq7 getstartedlab_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp mifd433bti1d getstartedlab_web replicated 5/5 gordon/getstarted:latest *:80->80/tcp
-
检查一个节点上的网页,例如
http://192.168.99.101
,查看访问者计数器的结果,该计数器现已存在并在Redis上存储信息。
同时,检查在任一节点的IP地址,端口8080的可视化工具,并注意看redis
与web
和visualizer
服务。