Docker | Swarm
2022年2月27日 · 7964 字 · 16 分钟 · Docker
一、前言
Swarm 是 Docker 公司推出的用来管理 docker 集群的平台,几乎全部用 GO 语言来完成的开发的,代码开源:https://github.com/docker/swarm
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。
上图可以看出,Swarm 是典型的 master-slave 结构,通过发现服务来选举 manager。manager 是中心管理节点,各个 node 上运行 agent 接受 manager 的统一管理,集群会自动通过 Raft 协议分布式选举出 manager 节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了 DNS 的负载均衡和对外部负载均衡机制的集成支持。
二、Docker Swarm 工作原理
2.1、Docker Engine client
通过 docker service create 命令去创建一个服务。
2.2、swarm manager
API这个请求直接由 Swarm manager 的 API 进行接收,接收命令并创建服务对象。orchestrator为服务创建一个任务。allocater为这个任务分配 IP 地址。dispatcher将任务分配到指定的节点。scheduler再该节点中下发指定命令。
2.3、worker node:接收 manager 任务后去运行这个任务
container创建相应的容器。worker连接到调度程序以检查分配的任务。executor执行分配给工作节点的任务。

三、Swarm 重要概念
Swarm集群的管理和编排是使用嵌入 docker 引擎的 SwarmKit,可以在 docker 初始化时启动 swarm 模式或者加入已存在的 swarm。Node每一个 docker engin 都是一个 node(节点),分为 manager 和 worker。Manager 节点还执行维护所需群集状态所需的编排和集群管理功能。Work 节点接收并执行从管理器节点分派的任务。Service一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,需要指定要使用的容器镜像。Task任务是在 docekr 容器中执行的命令,Manager 节点根据指定数量的任务副本分配任务给 worker 节点。一个任务包含了一个容器及其运行的命令。task 是 service 的执行实体,task 启动 docker 容器并在容器中执行任务。
3.1、Swarm 命令行说明
3.1.1、docker swarm
集群管理,子命令有 init, join, leave, update。(docker swarm --help 查看帮助);
执行集群的管理功能,维护集群的状态,选举一个 leader 节点去执行调度任务。
init初始化集群join将节点加入集群join-token管理加入令牌leave从集群中删除某个节点,强制删除加参数 –forceupdate更新集群unlock解锁集群
3.1.2、docker node
节点管理,子命令有 accept, promote, demote, inspect, update, tasks, ls, rm。(docker node --help 查看帮助)
接收和执行任务。参与容器集群负载调度,仅用于承载 task。
demote将集群中一个或多个节点降级inspect显示一个或多个节点的详细信息ls列出集群中的节点promote将一个或多个节点提升为管理节点rm从集群中删除停止的节点,–force 强制删除参数ps列出一个或多个节点上运行的任务update更新节点
3.1.3、docker service
服务创建,子命令有 create, inspect, update, remove, tasks。(docker service--help 查看帮助)
一个服务是 work 节点上执行任务的定义。创建一个服务,指定了容器所使用的镜像和容器运行的命令。
create创建一个新的服务inspect列出一个或多个服务的详细信息ps列出一个或多个服务中的任务信息ls列出服务rm删除一个或多个服务scale扩展一个或多个服务update更新服务
四、Swarm 的调度策略
Swarm 在调度 (scheduler) 节点(leader 节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread(平均分配), binpack(堆叠填满), random。
在 Docker Swarm 中,调度策略决定了容器(Task)在集群各个节点上的分布方式。Swarm 并不像 K8s 那样有几十种复杂的调度器,它的核心调度逻辑非常直接,主要通过 策略(Strategy) 和 约束/倾向(Constraints/Preferences) 来实现。
4.1、默认调度:Spread(扩散策略)
当你运行 docker service create 或 stack deploy 时,Swarm 默认使用 Spread 策略。
- 逻辑:它会尝试将任务均匀地分配到健康的节点上。
- 目标:最大化高可用性。如果一个节点挂了,受影响的容器最少。
4.2、通过 Placement Constraints(放置约束)
这是最常用的“强制性”设置。你可以根据节点的元数据(如角色、主机名、自定义标签)来限制服务只能运行在哪些节点上。
在 Compose 文件中设置:
services:
db:
image: mariadb
deploy:
placement:
constraints:
- "node.role == worker" # 只在工作节点运行
- "node.labels.storage == ssd" # 只在带有 ssd 标签的节点运行
- "node.hostname != node-01" # 排除掉 node-01
给节点打标签
docker node update --label-add storage=ssd node-02
4.3、通过 Placement Preferences(放置倾向)
与强制约束不同,倾向(Preferences)是“软约束”。它告诉 Swarm 尽量均匀地分布在某一类维度上。最典型的用法是跨机架或跨可用区分布。
示例:让副本尽量均匀分布在不同的数据中心
deploy:
placement:
preferences:
- spread: "node.labels.datacenter"
效果:如果你的节点分别标有 datacenter=east 和 datacenter=west,Swarm 会尝试在两个区各放一半副本。
4.4、资源调度(Resource Reservations)
Swarm 也会根据节点的剩余资源进行调度。如果你设置了资源预留(Reservation),Swarm 不会将任务分配给那些“算力不足”的节点。
deploy:
resources:
reservations:
cpus: '0.50'
memory: 512M
逻辑:如果节点 A 剩余内存不足 512M,即使该节点目前容器最少,Swarm 也不会把任务派发给它。
4.5、服务的运行模式(Mode)
改变服务的运行模式也是一种变相的调度策略:
| 模式 | 配置 | 调度行为 |
|---|---|---|
| Replicated | replicas: 3 | 在集群中挑选最合适的节点运行 3 个副本(默认)。 |
| Global | mode: global | 在集群的每个节点上各运行一个副本。常用于日志收集(Filebeat)或监控(Prometheus Exporter)。 |
4.6、如何选择
- 为了高可用:直接用默认的 Spread。
- 为了性能:给特定服务器打标签(如
gpu=true),然后用 Constraints。 - 为了容灾:使用 Placement Preferences 配合节点标签,实现跨机房分布。
- 为了全网监控:使用 Global Mode。
五、Swarm Cluster 模式特性
批量创建服务:建立容器之前先创建一个 overlay 的网络,用来保证在不同主机上的容器网络互通的网络模式。强大的集群的容错性:Swarm Cluster 不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过 scale 参数即可复制出新的副本出来。如果有需求想在每台节点上都 run 一个相同的副本,方法其实很简单,只需要在命令中将--replicas n更换成--mode=global即可。复制服务(--replicas n):将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如--replicas 3。全局服务(--mode=global):适用于集群内全部可用节点上的服务任务,例如--mode global。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。调度机制:所谓的调度其主要功能是 cluster 的 server 端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。
六、Dcoker Swarm 集群部署
6.1、环境准备 (三台 linux 机器,centos 系统)
IP:192.168.10.130 主机名:manager130 担任角色:swarm manager
IP:192.168.10.131 主机名:node131 担任角色:swarm node
IP:192.168.10.132 主机名:node132 担任角色:swarm node
6.2、创建 Swarm cluster
6.2.1、准备工作
1、修改主机名
# 192.168.10.130 执行
hostnamectl set-hostname manager130
# 192.168.10.131 执行
hostnamectl set-hostname node131
# 192.168.10.132 执行
hostnamectl set-hostname node132
2、在所有节点上配置 /etc/hosts 文件
192.168.10.130 manager130
192.168.10.131 node131
192.168.10.132 node132
3、设置防火墙
关闭三台机器上的防火墙,不建议直接关闭防火墙,一般生成环境上不允许直接关闭防火墙。如果开启防火墙,则需要在所有节点的防火墙上依次放行 2377/tcp(管理端口)、7946/tcp/udp(节点间通信端口)、4789/udp(overlay 网络端口)端口。
# 放开 2377/tcp,7946/udp,4789/udp 端口
firewall-cmd --zone=public --add-port=2377/tcp --permanent
firewall-cmd --zone=public --add-port=7946/tcp --permanent
firewall-cmd --zone=public --add-port=7946/udp --permanent
firewall-cmd --zone=public --add-port=4789/udp --permanent
# 重新加载生效
firewall-cmd --reload
# 查看
firewall-cmd --list-ports
4、安装 Docker
6.2.2、创建 Swarm 并添加节点
1、创建 Swarm 集群(manager130)
docker swarm init --advertise-addr 192.168.10.130
Swarm initialized: current node (sxwaiyl5j64dbxeanxw7wgj8e) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4ev72f2jax5vhkhc7bjx6gfb61m8w99ctscpc84p96gdp1xrcz-9mwpr765ca0fdunc94j09wlzf 192.168.10.130:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
上面命令执行后,该机器自动加入到 swarm 集群。这个会创建一个集群 token,作为集群唯一标识。记住这个 token 值,后续将其他节点加入集群都会用到这个 token 值。
其中,--advertise-addr 参数表示其它 swarm 中的 worker 节点使用此 ip 地址与 manager 联系。命令的输出包含了其它节点如何加入集群的命令。再次执行会报如下错误。
[root@manager110 ~]# docker swarm init --advertise-addr 192.168.10.130
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
解决方法:
# 这里的 leave 就是在集群中删除节点,-f 参数强制删除,执行完在重新执行 OK
docker swarm leave -f
docker swarm init --advertise-addr 192.168.10.130
2、查看集群的相关信息
docker info
发现 swarm 状态 active,且是 manager 节点。
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
sxwaiyl5j64dbxeanxw7wgj8e * manager130 Ready Active Leader 20.10.22
6.2.3、添加 node 节点主机到 Swarm 集群
在创建 Swarm 集群的时候就已经给出了添加节点的方法。如果忘记了,可以通过以下命令查看 token 和添加方法。
docker swarm join --token worker
node131 & node132 主机上执行:
docker swarm join --token SWMTKN-1-4ev72f2jax5vhkhc7bjx6gfb61m8w99ctscpc84p96gdp1xrcz-9mwpr765ca0fdunc94j09wlzf 192.168.10.130:2377
在 manager130 节点上查看 node 信息:
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
sxwaiyl5j64dbxeanxw7wgj8e * manager130 Ready Active Leader 20.10.22
zk6jluzkwevz73yzxu9za8h55 node131 Ready Active 20.10.22
owzfehdo3p0mc807n2328gb9k node132 Ready Active 20.10.22
MANAGER STATUS 的三种状态:
Leader为群体做出所有群管理和编排决策的主要管理者节点。Reachable如果 Leader 节点变为不可用,该节点有资格被选举为新的 Leader。Unavailable该节点不能和其他 Manager 节点产生任何联系,这种情况下,应该添加一个新的 Manager 节点到集群,或者将一个 Worker 节点提升为 Manager 节点。
升级 / 降级节点,示例:
# 升级
docker node promote node131
# 降级
docker node demote node131
七、在 Swarm 中部署服务
7.1、Nginx 为例
Docker 1.12 版本提供服务的 Scaling、health check、滚动升级等功能,并提供了内置的 dns、vip 机制,实现 service 的服务发现和负载均衡能力。
1、创建网络(overlay)
docker node ls
docker network create -d overlay nginx_net
docker network ls | grep nginx_net
2、部署服务
# 就创建了一个具有一个副本(--replicas 1 )的 nginx 服务,使用镜像 nginx
docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 nginx
# 查看
docker service ls
3、查询 Swarm 中服务的信息
--pretty 使命令输出格式化为可读的格式,不加 --pretty 可以输出更详细的信息:
docker service inspect --pretty my_nginx
查询到哪个节点正在运行该服务:
docker service ps my_nginx
如下该容器被调度到 manager-node 节点上启动了,然后访问 http://192.168.10.130 即可访问这个容器应用(如果调度到其他节点,访问也是如此)。
登陆该节点,可以查看到 nginx 容器在运行中
docker ps
4、在 Swarm 中动态扩展服务 (scale)
当然,如果只是通过 service 启动容器,swarm 也算不上什么新鲜东西了。Service 还提供了复制(类似 kubernetes 里的副本)功能。可以通过 docker service scale 命令来设置服务中容器的副本数比如将上面的 my_nginx 容器动态扩展到 4 个。
docker service scale my_nginx=4
和创建服务一样,增加 scale 数之后,将会创建新的容器,这些新启动的容器也会经历从准备到运行的过程,过一分钟左右,服务应该就会启动完成,这时候可以再来看一下 nginx 服务中的容器。
docker service ps my_nginx
可以看到,之前 my_nginx 容器只在 manager-node 节点上有一个实例,而现在又增加了 3 个实例。
5、模拟宕机 node 节点
如果一个节点宕机了(即该节点就会从 swarm 集群中被踢出),则 Docker 应该会将在该节点运行的容器,调度到其他节点,以满足指定数量的副本保持运行状态。
将 node131 宕机后或将 node131 的 docker 服务关闭,那么它上面的 task 实例就会转移到别的节点上。当 node131 节点恢复后,它转移出去的 task 实例不会主动转移回来,只能等别的节点出现故障后转移 task 实例到它的上面。使用命令 docker node ls,发现 node131 节点已不在 swarm 集群中了 (状态为:Down)。然后过一会查询服务的状态列表。
6、Swarm 动态缩容服务 (scale)
同理,swarm 还可以缩容,同样是使用 scale 命令。将 my_nginx 容器变为 1 个
docker service scale my_nginx=1
7、docker service update
除了上面使用 scale 进行容器的扩容或缩容之外,还可以使用 docker service update 命令。 可对服务的启动参数进行更新 / 修改。
docker service update --replicas 3 my_nginx
docker service ps my_nginx
8、删除服务
docker service rm my_nginx
7.2、Swarm 中使用 Volume (挂载目录,mount 命令)
1、查看 volume 的帮助信息
docker volume --help
2、创建一个 volume
docker volume create --name testvolume
docker volume ls
docker volume inspect testvolume
3、创建新的服务并挂载 testvolume (nginx 为例)
docker service create --replicas 3 --mount type=volume,src=testvolume,dst=/usr/share/nginx/html --name test_nginx nginx
tip:参数 src 写成 source 也可以;dst 表示容器内的路径,也可以写成 target。查看
docker service ls
docker service ps test_nginx
7.3、多服务 Swarm 集群部署
这里部署的服务有三个 (nginx 服务,visualizer 服务,portainer 服务) 除了 nginx 服务作为示例之外,visualizer(官方地址)和 portainer(官方地址)都是集群 GUI 管理服务。docker service 部署的是单个服务,我们可以使用 docker stack 进行多服务编排部署。
7.3.1、编写 docker-stack.yml 文件
点击查看完整的
docker-stack.ymlversion: "3"
services:
nginx:
image: nginx
ports:
- 8888:80
deploy:
mode: replicated
replicas: 3
visualizer:
image: dockersamples/visualizer
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock" # 让容器能够读取宿主机的 Docker 信息,从而知道集群里有哪些节点和容器。
deploy:
replicas: 1
placement:
constraints: [node.role == manager] # 强制该容器只能运行在 Manager 节点上,因为它需要管理权限来读取集群状态。
portainer:
image: portainer/portainer
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
Docker Compose (docker-compose up) VS Docker Stack (docker stack deploy)
docker-compose.yml 是为单机设计的,而 docker stack deploy 使用的文件是为集群(Swarm)设计的。
虽然它们都使用 .yml 格式,且大部分语法通用,但核心区别在于如何管理容器的生命周期。
1、核心区别
| 特性 | Docker Compose (docker-compose up) | Docker Stack (docker stack deploy) |
|---|---|---|
| 适用场景 | 单机开发/测试环境。 | 多机生产集群 (Swarm)。 |
| 核心逻辑 | 管理具体的“容器”。 | 管理抽象的“服务 (Service)”。 |
| 部署配置 | 忽略 deploy 节点。 | 依赖 deploy 节点(副本数、约束等)。 |
| 网络模式 | 默认创建桥接网络 (bridge)。 | 默认创建覆盖网络 (overlay),支持跨主机通信。 |
| 镜像构建 | 支持 build 指令(现场构建镜像)。 | 不支持 build。镜像必须预先存在于仓库。 |
| 副本控制 | 不支持(通常 1 个服务对应 1 个容器)。 | 支持 replicas,可实现高可用。 |
2、关键差异
deploy 配置块(最本质区别)
在 docker stack 中,deploy 是灵魂。它决定了服务在集群中的“行为”。
- 副本数 (
replicas):在单机 Compose 中无意义,但在 Stack 中决定了起多少个实例。 - 更新策略 (
update_config):滚动更新的频率、并行数量。 - 资源限制 (
resources):限制每个服务使用的 CPU 和内存。 - 放置约束 (
placement):比如指定“必须运行在 SSD 硬盘的节点”或“必须运行在 Manager 节点”。
3、镜像来源
- Docker Compose:可以写
build: ./app。Docker 会在本地现场帮你构建镜像并启动。 - Docker Stack:它要求所有镜像必须是预先构建好并推送到镜像仓库(如 Docker Hub)的。因为集群中的其他节点需要能从仓库下载这个镜像。它会直接忽略
build指令。
4、网络实现
- Compose:容器间通过宿主机的网桥通信。
- Stack:使用
overlay网络。即使 Nginx 在服务器 A,数据库在服务器 B,它们也能像在同一台机器上一样通过服务名通信。
5、容错能力
- Compose:如果容器挂了,虽然可以配置
restart: always,但如果宿主机直接宕机,应用就彻底离线了。 - Stack:如果某个 Worker 节点宕机,Swarm 会自动在其他健康的节点上重新拉起容器,保证
replicas数量达标。
现在的 Docker 版本已经实现了语法大融合。你完全可以用同一个 .yml 文件,既能 compose up 也能 stack deploy。只是执行 compose up 时,它会假装看不见 deploy 里的那些集群参数而已。
7.3.2、通过这个 yml 文件部署服务
docker stack deploy -c docker-stack.yml my-stack
7.3.3、测试验证
第一个服务:my-stack_nginx,先查看调度到哪个节点上。
在 Stack 部署模式下,服务的完整名称通常是 栈名_服务名。
docker service ps my-stack_nginx
看调度到 manager130 和 node132 节点上。访问:http://192.168.10.130:8888、http://192.168.10.132:8888。
八、Docker Swarm 网络管理
8.1、Swarm 集群产生两种不同类型的流量
- 控制和管理层面:包括 Swarm 消息管理等,例如请求加入或离开 Swarm,这种类型的流量总是被加密的。(涉及到集群内部的 hostname、ip-address、subnet、gateway 等)
- 应用数据层面:包括容器与客户端的通信等。(涉及到防火墙、端口映射、网口映射、VIP 等)
8.2、在 Swarm Service 中有三个重要的网络概念
Overlay networks覆盖网络,顾名思义是附着在主机底层网络之上的网络, 这个网络保证了不同主机之间容器通信,手动创建。ingress network进入网络,顾名思义是外部客户端访问服务时,服务节点间负载均衡(节点在开放端口上收到请求,上交给 IPVS,选择容器),是一种特殊的 overlay 网络,创建集群的时候自动创建。初始化或加入 Swarm 集群时会自动创建 ingress 网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本可以自定义网络docker_gwbridge是一种桥接网络,将 overlay 网络(包括 ingress 网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的 docker_gwbridge 网络。docker_gwbridge 网络在初始化或加入 Swarm 时自动创建。大多数情况下,用户不需要自定义配置,但是 Docker 允许自定义。
在初始化或刚加入 Swarm 集群时,会自动创建一个 Ingress 和 docker-gwbridge 网络
docker stack deploy 部署时,Docker 的处理逻辑如下:
- 自动创建默认网络:如果在 .yml 文件中没有显式定义网络,Docker Stack 会默认创建一个名为 my-stack_default 的 Overlay 网络。
- 自动加入服务:它会自动把该 Stack 下的所有服务(Nginx, Visualizer 等)都接入这个网络,让它们天然互通。
手动创建 Overlay networks
预定义的自定义网络
如果你希望网络名字更规范,或者需要配置特定的子网(Subnet),可以在 YAML 的最顶层定义:
networks:
my-net:
driver: overlay # 明确指定驱动为 overlay
这种情况下,执行 stack deploy 时,Docker 依然会自动帮你创建这个 my-stack_my-net。
跨 Stack 通信
如果你有两个不同的 Stack(比如 stack-db 和 stack-app),它们需要互相访问。由于 Stack 默认只允许内部通信,这时你需要预先手动创建一个外部网络:
# 手动创建一次
docker network create --driver overlay --attachable my-global-net
然后在两个 Stack 的 YAML 中都引用它:
networks:
my-global-net:
external: true # 告诉 Docker,这个网络已经存在了,别自己瞎建
总结
- 常规使用:直接 docker stack deploy,Docker 会自动为你搞定一切 Overlay 网络的创建和销毁。
- 网络隔离:属于同一个 Stack 的容器默认能互相 ping 通,不同 Stack 的容器默认是隔离的。
- 关键点:只有在 Swarm 模式下,overlay 网络才真正发挥跨主机的威力;如果是普通的单机 docker-compose,它默认使用的是 bridge 网络。
九、docker-machine、docker swarm、docker node、docker service 和 docker stack 常用命令
9.1、docker-machine 常用命令
docker-machine create创建一个 Docker 主机(常用 - d virtualbox)docker-machine ls查看所有的 Docker 主机docker-machine sshSSH 到主机上执行命令docker-machine env显示连接到某个主机需要的环境变量docker-machine inspect输出主机更多信息docker-machine kill停止某个主机docker-machine restart重启某台主机docker-machine rm删除某台主机docker-machine scp在主机之间复制文件docker-machine start启动一个主机docker-machine status查看主机状态docker-machine stop停止一个主机
9.2、docker swarm 常用命令
docker swarm init初始化集群docker swarm join-token worker查看工作节点的 tokendocker swarm join-token manager查看管理节点的 tokendocker swarm join加入集群中
9.3、docker node 常用命令
docker node ls查看所有集群节点docker node rm删除某个节点(-f 强制删除)docker node inspect查看节点详情docker node demote节点降级,由管理节点降级为工作节点docker node promote节点升级,由工作节点升级为管理节点docker node update更新节点docker node ps查看节点中的 Task 任务
9.4、docker service 常用命令
docker service create部署服务docker service inspect查看服务详情docker service logs查看某个服务日志docker service ls查看所有服务详情docker service rm删除某个服务(-f 强制删除)docker service scale设置某个服务个数docker service update更新某个服务
9.5、docker stack 常用命令
docker stack deploy部署新的堆栈或更新现有堆栈docker stack ls列出现有堆栈docker stack ps列出堆栈中的任务docker stack rm删除堆栈docker stack services列出堆栈中的服务docker stack down移除某个堆栈(不会删除数据)
十、Docker 组件
docker-compose主要是解决本地 docker 容器编排问题。docker-machine是解决 docker 运行环境问题。docker-swarm是解决多主机多个容器调度部署问题。