MYF

Get Started, Part 5: Stacks

参考文档:Get Started, Part 5: Stacks

Prerequisites

  • 安装1.13版本或者更高版本的Docker
  • 完成Part 3的prerequisites部分的Docker Compose
  • 完成Part 4的prerequisites部分的Docker Machine
  • 阅读Part 1
  • 阅读Part 2学习如何创建container
  • 确保你已经发布了friendlyhello镜像,我们使用这个共享镜像
  • 确保你的的镜像像一个部署的容器一样运行,运行这个指令,替换username, repo, tag为你自己的信息docker run -p 80:80 username/repo:tag,然后访问http://localhost/
  • 拷贝一份你在Part 3中的docker-compose.yml文件
  • 确保Part 4中创建的机器出于运行状态。运行docker-machine ls来验证这个,如果机器处于stop状态,运行docker-machine start myvm1来启动manager,然后运行docker-machine start myvm2来启动worker机器。
  • 确保你在Part 4中创建的swarm是好的,运行docker-machine ssh myvm1 "docker node ls"来验证。如果swarm是活跃的,nodes会返回ready状态。如果不是,重新初始化swarm并且加入swarm,如同Set up your swarm章节的内容。

Introduction

在part 4中,你已经学习了如何设置一个swarm,swarm也就是一串运行docker的机器,并且在其上部署了应用,多个容器在多台机器上共同发挥作用。

现在在part 5,你已经到达了分布式应用的最高层——stack。一个stack是一组相互关联的服务,他们有着共同的依赖,他们可以一起协作。一个单独的stack可以定义与协调整个应用的功能性,尽管复杂的应用可能需要多个stack。

但是也有一个好消息,你已经在技术上在part 3中使用了stack技术,当你创建一个compose file的时候,然后使用docker stack deploy。但是这只是一个单独的service stack运行在单一主机上,在真实的生产中通常不会是这样的。现在,你可以使用你学习的东西,创建多个相互关联的services,并且将他们运行在多台机器上。

You’re doing great, this is the home stretch!

Add a new service and redeploy

在我们的docker-compose.yml文件中添加service非常容易,首先,让我们先加一个免费的可视化服务,让我们看我们的swarm是如何管理container的。

1、 在编辑器中打开docker-compose.yml,将下面的文件替换原有文件。确保将username/repo:tag替换为你自己的image信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# filename: docker-compose.yml
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的点服务(peer service),叫做visualizer。注意这里的两个事情:一个是名为volumes的键,这个键给了visualizer对于Docker访问主机的socket文件,另一个是placement键,这个键保证了这个服务只会运行在swarm manager上,而不是worker机上。因为这个创建于Docker开源项目的container展示了运行在swarm上的Docker服务的图形化界面。

2、确保shell配置好来执行myvm1主机了(如果你不知道怎么做,点击这里

  • 运行docker-machine ls来列出所有的机器,确保你连接到myvm1主机,成功的话会有*在Active一栏中。
  • 如果需要,运行docker-machine env myvm1,然后运行给出的指令来配置shell

在Mac和Linux下指令是

1
eval $(docker-machine env myvm1)

在Windows中指令是:

1
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression

3、在manager机器上重运行docker stack deploy指令,然后所有需要更新的服务都会更新

1
2
3
$ docker stack deploy -c docker-compose.yml getstartedlab
Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm)
Creating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)

4、去看看visualizer

在Compose file中,你看到了visualizer运行在8080端口。访问这两个虚拟机中的任意一个ip的8080端口,你可以看到visualizer运行着:

唯一一个visualizer正在你希望看到的manager机器上运行,另外五个web的实例分布在swarm上。你可以通过docker stack ps <stack>指令对其进行协作:

1
docker stack ps getstartedlab

这个visualizer十一个独立的service,他可以运行在任何在栈中包含该service的app中,他不需要依赖任何其他的东西。现在我们创建一个需要依赖的服务:Redis服务。这个服务作为一个visitor存在。

Persist the data

让我们再次做一遍相同的工作流来将用于存储app数据的Redis服务添加进来。

1、保存新的docker-compose.yml文件,这个文件最终添加了Redis服务。确保将username/repo:tag替换为你自己的镜像信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# filename: docker-compose.yml
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端口已经被预先配置好了,这样就可以从容器暴露给主机,同时在这个compose file中,我们将其从主机暴露给外界,所以你可以在Redis Desktop Manager中输入任何一个节点的ip地址来管理这些Redis实例。

更重要的是,有一些事情在redis的指定配置中,使数据持久化于栈的开发过程中:

  • redis总是运行在manager上,所以他总是有相同的文件系统
  • redis访问主机文件系统/data的任意的目录,这里也就是Redis储存数据的地方

总的来说,这正在你的主机的物理文件系统中创建一个「source of truth」用于Redis数据。没有这些,Redis会存储数据在容器文件系统的/data目录下,这样的话一旦容器被重新部署了,数据就会被抹除。

这个「source of truth」有两个部分组成:

  • 你对于Redis服务设置的placement constraint,确保他一直使用相同的host
  • 你创建的让容器访问./data作为访问/data的volume。尽管容器会被删除和创建,但是存储在特定主机上的./data数据会持久化。

你已经准备好创建你的新的使用Redis的stack了。

2、在manager上创建一个./data目录

1
docker-machine ssh myvm1 "mkdir ./data"

3、确保你的shell已经配置好用于向myvm1输入指令了。

  • 运行docker-machine ls来显示出所有的机器,确保你已经连接到myvm1,这样的话旁边会有一个*的标志
  • 如果需要,重新运行docker-machine env myvm1,然后运行给出的指令来配置shell。

在Mac和Linux下指令是

1
eval $(docker-machine env myvm1)

在Windows中指令是:

1
& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression

4、运行docker stack deploy依次

1
docker stack deploy -c docker-compose.yml getstartedlab

5、运行docker service ls来验证这三个服务是否按照预期的运行了

1
docker service ls

6、访问你的任意一个节点,比如http://192.168.99.101,看看访客计数器,现在已经可以用了,并且存储了Redis的数据。

与此同时,访问8080端口的visualizer,你可以注意到redis服务和web服务、visualizer服务一同运行了

Recap (optional)

https://asciinema.org/a/113840