前面我们已经学习过了Docker Compose,它可以用来进行一个完整的应用程序相互依赖的多个容器的编排的,但是缺点是只能在单机模式使用,不能在分布式多机器上使用;前面我们也学习了Docker swarm,它可以将单个服务部署为多个容器,并运行在不同集群节点上,构成服务集群,缺点是只能部署单个服务,不能同时编排多个服务。
但是在实际的生产开发中,我们一个完整的应用需要的服务往往不止一个,通过docker service命令来部署的话会很麻烦,那么能不能结合Docker Compose+Docker swarm的优点呢?这就是Docker Stack。
Docker Stack用于向swarm集群部署完整的应用程序堆栈,可以在分布式多机器上同时编排多个有依赖关系的服务。能够在单个声明文件中定义复杂的多服务应用,还提供了简单的方式来部署应用并管理其完整的生命周期:初始化部署 -> 健康检查 -> 扩容 -> 更新 -> 回滚,以及其他功能!可以简单地理解为Docker Stack是集群下的Docker Compose。
Docker Compose中的不支持项
Docker Stack编排依赖于声明文件,其实也就是Docker Compse文件,不过Docker Stack对于Docker Compose文件有一个要求,文件的规范版本(顶层关键字version)必须是"3.0"或以上,而且一些Docker Compse文件中的关键字不受支持,如:
- build
- cgroup_parent
- container_name
- devices
- tmpfs
- external_links
- links
- network_mode
- restart
- security_opt
- userns_mode
由于build关键字在Docker Stack中不受支持,不能在编排的过程中构建镜像,docker stack部署用到的镜像必须是已经构建发布好,并且发布到docker仓库的,在服务编排过程各个节点中直接从docker仓库拉取。
先构建镜像:
shell
$ sudo docker image build -t flask-demo .
登陆远程镜像仓库:
shell
$ sudo docker login --username=xxx@xxxx.com registry.cn-hangzhou.aliyuncs.com
这里使用的是阿里云的免费镜像仓库:https://cr.console.aliyun.com/cn-hangzhou/instances
再修改镜像的tag:
shell
$ sudo docker image tag flask-demo:latest registry.cn-hangzhou.aliyuncs.com/morris131/flask-demo:latest
最后将镜像推送至远程仓库:
shell
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/morris131/flask-demo:latest
手动部署多service
先创建一个overlay网络:
shell
$ sudo docker network create -d overlay mynet
kunkv8prss5gihgz5deowhdfw
然后部署redis service:
shell
$ sudo docker service create --name redis --network mynet redis:latest redis-server --requirepass ABC
bn507bk9aaggf1lhhpnask9kq
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
部署flask-demo service
shell
$ sudo docker service create --name flask-demo --network mynet --env REDIS_HOST=REDIS --env REDIS_PASS=ABC -p 8080:5000 flask-demo:latest
image flask-demo:latest could not be accessed on a registry to record
its digest. Each node will access flask-demo:latest independently,
possibly leading to different nodes running different
versions of the image.
xx9chfrx2ro3j8cnvab5vp0pm
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
查看服务,可以看到flask-demo和redis都已经部署成功:
shell
$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
7yr3lamfse5k flask-demo replicated 1/1 flask-demo:latest *:8080->5000/tcp
bn507bk9aagg redis replicated 1/1 redis:latest
访问flask-demo服务:
shell
$ curl 172.20.160.13:8080
Hello Container World! I have been seen 3 times and my hostname is bf03f59d3bab.
Docker Stack部署多service
前面可以看到通过docker service手动部署多个service非常繁琐,需要一个一个service部署。
接下来使用Docker Stack来部署多service的服务。
编写docker-compose.yml:
shell
version: "3.3"
services:
flask-demo:
image: registry.cn-hangzhou.aliyuncs.com/morris131/flask-demo
environment:
- REDIS_HOST=redis-server
- REDIS_PASS=ABC
networks:
- demo-network
ports:
- 8080:5000
redis-server:
image: redis:latest
command: redis-server --requirepass ABC
networks:
- demo-network
networks:
demo-network:
启动服务:
shell
$ sudo docker stack deploy --compose-file docker-compose.yml flask
Creating network flask_demo-network
Creating service flask_redis-server
Creating service flask_flask-demo
访问服务:
shell
$ curl 172.20.160.13:8080
Hello Container World! I have been seen 1 times and my hostname is 4a88aad138e7.
Stack基本命令的使用
Docker stack命令用于swam集群中对应用堆栈涉及到的多个服务进行编排部署和全生命周期管理。
常用的命令如下,可用help命令查看详细说明:
shell
$ sudo docker stack help
Usage: docker stack COMMAND
Manage Swarm stacks
Commands:
config Outputs the final config file, after doing merges and interpolations
deploy Deploy a new stack or update an existing stack
ls List stacks
ps List the tasks in the stack
rm Remove one or more stacks
services List the services in the stack
Run 'docker stack COMMAND --help' for more information on a command.
docker stack deploy
shell
docker stack deploy [OPTIONS] STACK
根据Stack文件(通常是 docker-compose.yml)部署和更新Stack服务的命令,常用选项如下:
- -c:指定compose文件路径
- --with-registry-auth:服务创建的时候,各个工作节点同步管理节点的私有仓库登录凭证,从而各个节点可用拉取私有仓库镜像
docker stack ls
shell
docker stack ls
列出Swarm集群中的全部Stack,包括每个Stack拥有多少服务。
例如:
shell
$ sudo docker stack ls
NAME SERVICES
flask 2
docker stack ps
shell
docker stack ps [OPTIONS] STACK
列出某个已经部署的Stack相关详情。该命令支持Stack名称作为其主要参数。
在服务启动失败时,docker stack ps命令是首选的问题定位方式。该命令展示了Stack中每个服务的概况,包括服务副本所在节点、当前状态、期望状态以及异常信息,再配合docker service logs查看某个具体服务或任务的详细信息。
shell
$ sudo docker stack ps flask
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
oaq79y2xpvz0 flask_flask-demo.1 registry.cn-hangzhou.aliyuncs.com/morris131/flask-demo:latest node1 Running Running 6 minutes ago
03j987pc0yyn flask_redis-server.1 redis:latest node2 Running Running 5 minutes ago
docker stack services
shell
docker stack services [OPTIONS] STACK
列出某个已经部署的Stack的服务,包括服务的模式,使用的镜像,端口映射等。
shell
$ sudo docker stack services flask
ID NAME MODE REPLICAS IMAGE PORTS
yoynkqh2mh9n flask_flask-demo replicated 1/1 registry.cn-hangzhou.aliyuncs.com/morris131/flask-demo:latest *:8080->5000/tcp
yrg986m18pps flask_redis-server replicated 1/1 redis:latest
docker stack rm
shell
docker stack rm [OPTIONS] STACK [STACK...]
从Swarm集群中移除一个或多个Stack。移除操作执行前并不会进行二次确认。
shell
$ sudo docker stack rm flask
Removing service flask_flask-demo
Removing service flask_redis-server
Removing network flask_demo-network