Docker Stacks and DAB(Distributed Application Bundles)是Docker 1.12和Docke Compose 1.8之后的体验功能特性,随着Docker Engine中的Swarm Mode,Nodes和Services而来。
起初我们通过docker run命令成功运行一个容器之后就可以访问容器中的应用,比如跑一个nginx的web服务;
如需运行一个由多容器组成的应用,会用到docker-compose up,它会基于已定义好的yml文件来启动多个容器。比如跑一个WordPress应用(含Wordpress应用和MySQL数据库两个容器)。这就是我们常说的编排,个人认为compose编排的对象是容器;
暂且抛开外置的Swarm不谈,以上两种方式都是在单节点和极小规模的环境使用的,集群环境基本难以玩转。
随后Docker推出了Swarm Mode,可以通过简单的几条命令搭建一个Docker的集群环境,单个应用的多个容器可以被手动/自动的调度到集群中的各个节点运行,内置负载均衡功能以Service为基础提供服务,极大的提高了容器化应用的弹性。
我们可以使用docker service create命令运行一个服务,每个服务下面可含有一个或多个容器。需要注意的是,虽服务下的多个容器会被分配到不同的集群节点,但容器本身是一样的(由同一个image创建)。比如创建一个含有3个容器的nginx服务,3个容器会被分配集群中的任意3个节点,之后会由内置的负载均衡提供统一的服务出口,3个容器除了在不同节点运行之外,本身基本没有什么差异。
可惜的是我们没有办法在同一个服务里面跑两个不同类型的容器(比如一个WordPress的应用需要WPAP和WPDB两个容器,这个是实现不了的)。目前的解决方法就是手动创建WordPress应用的WPAP服务和WPDB服务,然后通过服务的相关信息进行内部网络通信和外部网络访问。
提到网络多说一句,Docker网络的两种网络模式:local(本地)和swarm(全局)。local网络只能被docker run和docker-compose使用,swarm网络只能被docker service create使用。
好在Docker在用户体验方面一直下足了功夫,此时Stacks和DAB应运而生。Stacks作为最终交付的容器化应用,下面会有多个服务,DAB专门负责这些服务的定义。例如我们可以将WordPress应用中WPAP和WPDB两个服务定义在dab文件中,之后通过docker deploy命令部署WordPress这个Stack,这样就不需要手动一个个的去部署服务了,逻辑上跟compose很类似。
集群环境中的 docker service create 类似 单机环境中的 docker run;
集群环境中的 docker deploy 类似 单机环境中的 docker-compose up;
集群环境中的 deploy dab文件 类似 单机环境中的 compose yml文件;
如果说compose是基于yml文件来编排容器,那么deploy就是基于dab文件来编排服务。
神来之笔是,就像我们可以用Dockerfile通过docker build生成Image一样,我们也可以用compose的yml文件通过docker-compose bundle生成deploy需要的dab文件,这无疑使得对DAB的理解和使用更加平滑。
为什么总说Docker上手和使用很简单?简单并不代表没有技术含量,相反,化繁为简才是真正的需要技术含量。Docker Engine简化的容器操作,Swarm Mode简化的集群部署和DAB简化的应用编排等等,这些都是最好的诠释。
前面聊了一些理论,也不知道说清楚没...下面以部署一个Docker币的应用为例动手实操体验一下。
Docker Host: 2台(CentOS 7.2+Ubuntu 16.04)
[root@manager01 ~]# lsb_release -d
Description: CentOS Linux release 7.2.1511 (Core)
root@worker01:~# lsb_release -d
Description: Ubuntu 16.04.1 LTS
Docker Engine: 1.12.3 Experimental
# docker version
Client:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 22:07:18 2016
OS/Arch: linux/amd64
Experimental: true
Server:
Version: 1.12.3
API version: 1.24
Go version: go1.6.3
Git commit: 6b644ec
Built: Wed Oct 26 22:07:18 2016
OS/Arch: linux/amd64
Experimental: true
注意:安装experimental版本才能体验Stacks和DAB的特性。
Docker Compose: 1.9.0
# docker-compose -v
docker-compose version 1.9.0, build 2585387
Docker Registry: 192.168.2.11:8080
需要Registry的原因是DAB使用的镜像必须有digests信息,所以镜像必须是存储在Registry中的。具体如下:
Generate a Distributed Application Bundle (DAB) from the Compose file.
Images must have digests stored, which requires interaction with a
Docker registry. If digests aren't stored for all images, you can fetch
them with `docker-compose pull` or `docker-compose push`.
Docker Images: werbui, rng, worker, hasher和redis
# docker images
192.168.2.11:8080/dockercoins/dockercoins_webui latest
192.168.2.11:8080/dockercoins/dockercoins_rng latest
192.168.2.11:8080/dockercoins/dockercoins_hasher latest
192.168.2.11:8080/dockercoins/dockercoins_worker latest
192.168.2.11:8080/dockercoins/dockercoins_redis latest
Docker Engine和Docker Compose如果GFW抽风下载不了的话去get.daocloud.io看看吧,业界良心。
初始化Manager节点
[root@manager01 ~]# docker swarm init --advertise-addr 192.168.2.201
Swarm initialized: current node (2kroyys1kcoryffuex9nobcl3) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-17lmhxt8er26bxhhieupx8s3vce2bezhgql1za5c394ofkqnsn-6nskpxfs4jnm7ikk73vzkilc4 \
192.168.2.201:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
加入Worker节点
root@worker01:~# docker swarm join \
--token SWMTKN-1-17lmhxt8er26bxhhieupx8s3vce2bezhgql1za5c394ofkqnsn-6nskpxfs4jnm7ikk73vzkilc4 \
192.168.2.201:2377
This node joined a swarm as a worker.
查看节点信息(需要在Manager节点执行)
[root@manager01 ~]# docker node ls
HOSTNAME STATUS AVAILABILITY MANAGER STATUS
manager01.docanix.com Ready Active Leader
worker01.docanix.com Ready Active
Overlay网络的创建只能在Manager节点执行
# docker network create -d overlay dockercoins
cy0zt5cfquov5ia9a2yen7r12
# docker network ls
NETWORK ID NAME DRIVER SCOPE
171960155d4b bridge bridge local
b1c3cdcc2dce docker_gwbridge bridge local
cy0zt5cfquov dockercoins overlay swarm
3836eec16480 host host local
0h18kkjshga7 ingress overlay swarm
643bf0bce504 none null local
注:这一步可以略过,在Stacks部署的时候会自动创建一个overlay的全局网络,目前还未找到自定义网络的方法。
# cat docker-compose.yml
version: "2"
services:
rng:
image: 192.168.2.11:8080/dockercoins/dockercoins_rng:latest
ports:
- "8001:80"
networks:
- dockercoins
hasher:
image: 192.168.2.11:8080/dockercoins/dockercoins_hasher:latest
ports:
- "8002:80"
networks:
- dockercoins
webui:
image: 192.168.2.11:8080/dockercoins/dockercoins_webui:latest
ports:
- "8000:80"
networks:
- dockercoins
redis:
image: 192.168.2.11:8080/dockercoins/dockercoins_redis:latest
networks:
- dockercoins
worker:
image: 192.168.2.11:8080/dockercoins/dockercoins_worker:latest
networks:
- dockercoins
networks:
dockercoins:
external: true
使用docker-compose pull命令拉取yml文件中定义的镜像
# docker-compose pull
Pulling worker
Digest: sha256:6f75cd9281ae6d5c68561d7917a8b21b9ce74f498d254da1b9cae990a965ffd3
Status: Downloaded newer image for 192.168.2.11:8080/dockercoins/dockercoins_worker:latest
Pulling redis
Digest: sha256:e14953e114bb12c396a3a69d1e648f1f676cbd746eea4397d6874ee0443acd1c
Status: Downloaded newer image for 192.168.2.11:8080/dockercoins/dockercoins_redis:latest
Pulling hasher
Digest: sha256:9b37ea987721cd6cc99f645f3c85a0bf5c14cbdb90c50b3905ac342f319deb05
Status: Downloaded newer image for 192.168.2.11:8080/dockercoins/dockercoins_hasher:latest
Pulling rng
Digest: sha256:60d38f18bc33863d16dd75045da00d1625789c49a764be4dc92afa5ff6bdc629
Status: Downloaded newer image for 192.168.2.11:8080/
Pulling webui
Digest: sha256:b328fa0c143959cccbbb1a9e8cea9f6aacdf54526eea5aab8810955bc9cf2ba4
Status: Downloaded newer image for 192.168.2.11:8080/dockercoins/dockercoins_webui:latest
可以看到拉取的五个镜像都有Digest信息。
使用docker-compose bundle基于yml文件生成dab文件
# docker-compose bundle
WARNING: Unsupported top level key 'networks' - ignoring
Wrote bundle to dockercoins.dab
compose v2里的networks参数目前bundle还不支持所以出现告警并忽略,应用部署的时候自动创建一个overlay网络。
查看dab文件
# ls -l
-rw-r--r-- 1 root root 690 Nov 20 13:31 docker-compose.yml
-rw-r--r-- 1 root root 1396 Nov 20 13:39 dockercoins.dab
# cat dockercoins.dab
{
"Services": {
"webui": {
"Image": "192.168.2.11:8080/dockercoins/dockercoins_webui@sha256:b328fa0c143959cccbbb1a9e8cea9f6aacdf54526eea5aab8810955bc9cf2ba4",
"Networks": [
"dockercoins"
],
"Ports": [
{
"Port": 80,
"Protocol": "tcp"
}
]
},
"Version": "0.1"
}
DAB文件内容比较长,以webui服务为例,主要是对每个服务进行描述,如服务名、镜像信息、端口信息等等。
需要注意的是DAB目前只支持Expose的端口,Published的端口会自动分配(从30000端口开始),不支持自定义,不过后面我们可以手动来修改。
使用docker deploy部署dockercoin这个Stack
# docker deploy dockercoins
Loading bundle from dockercoins.dab
Creating network dockercoins_dockercoins
Creating service dockercoins_hasher
Creating service dockercoins_redis
Creating service dockercoins_rng
Creating service dockercoins_webui
Creating service dockercoins_worker
注:Stack的名字需要跟DAB文件名一致
查看网络信息
# docker network ls
NAME DRIVER SCOPE
bridge bridge local
docker_gwbridge bridge local
dockercoins overlay swarm
dockercoins_dockercoins overlay swarm
host host local
ingress overlay swarm
none null local
名为dockercoins_dockercoins的overlay网络被自动创建
查看服务信息
# docker service ls
NAME REPLICAS
dockercoins_hasher 1/1
dockercoins_redis 1/1
dockercoins_worker 1/1
dockercoins_webui 1/1
dockercoins_rng 1/1
5个Service已经被创建且成功运行,NAME为Service的名字,REPLICAS这个Service下面有多少个正在运行的副本,可以简单理解为容器,严格意义上来说应该是Task。
注:输出信息有ID,NAME,REPLICAS,IMAGE和COMMAND五列,为方便关键仅输出了NAME和REPLICAS列。
查看Stack信息
# docker stack ps dockercoins
NAME NODE CURRENT STATE
dockercoins_worker.1 manager01.docanix.com Running 2 minutes ago
dockercoins_webui.1 manager01.docanix.com Running 2 minutes ago
dockercoins_rng.1 worker01.docanix.com Running 2 minutes ago
dockercoins_redis.1 worker01.docanix.com Running 2 minutes ago
dockercoins_hasher.1 manager01.docanix.com Running 2 minutes ago
dockercoins这个stack有5个容器运行,NAME为容器的名字,NODE为容器所在主机。
注:输出信息有ID,NAME,IMAGE,NODE,DESIRED STAT,CURRENT STATE和ERROR五列,为方便关键仅输出了NAME,NODE,CURRENT STATE列。
使用docker service inspect查看服务信息
# docker service inspect dockercoins_webui|grep -i publishedport
"PublishedPort": 30002
由于Published的端口是自动分配的,我们需要去查看相应服务的端口。
访问应用
http://192.168.2.201:30002
dockercoins应用已经成功运行。
通过docker service update命令配置自定义端口
# docker service update dockercoins_webui --publish-rm 80
dockercoins_webui
# docker service update dockercoins_webui --publish-add 8080:80
dockercoins_webui
访问测试
http://192.168.2.201:8080
可以通过自定义的8080端口访问应用
使用docker service scale实现服务的在线手动扩展
# docker service scale dockercoins_worker=2
dockercoins_worker scaled to 2
将dockercoins_worker服务扩展到2个副本
查看服务信息
# docker service ls
NAME REPLICAS
dockercoins_hasher 1/1
dockercoins_redis 1/1
dockercoins_worker 2/2
dockercoins_webui 1/1
dockercoins_rng 1/1
可以看到worker服务下面已经有2个副本在运行
查看Stack信息
# docker stack ps dockercoins
NAME NODE CURRENT STATE
dockercoins_webui.1 manager01.docanix.com Running 5 minutes ago
dockercoins_worker.1 manager01.docanix.com Running 13 minutes ago
dockercoins_redis.1 worker01.docanix.com Running 12 minutes ago
dockercoins_hasher.1 manager01.docanix.com Running 13 minutes ago
dockercoins_worker.2 manager01.docanix.com Running 2 minutes ago
dockercoins_rng.2 worker01.docanix.com Running 3 minutes ago
名为dockercoins_worker.2的容器作为worker服务的第二个副本在manager01主机上运行
访问测试
经过服务扩展至后,每秒生成的Docker币由4个变为6个。
Docker Stack和DAB的实际操作就到这里了,整体比较简单,有兴趣的朋友可以尝试一下。
DAB作为体验功能特性还是有许多需要完善的地方,很多配置目前的DAB还不支持,比如自定义Published的端口,比如Volume的定义等等,不过从整体还是来说编排一些无状态的应用还是没多大问题的。
更何况,在开源的时代,体验版都出来了,正式版还会远吗?