Docker Swarm
在单机容器排布中,我们定义容器启动顺序,和一件启动,采用了Docker Compose,如果是生产环境多机器部署,我们需要用到Docker Swarm ,下面请看官网描述:
- 集群模式是管理 Docker 守护进程集群的高级功能
- 如果您打算将 Swarm 用作生产运行时环境,请使用 Swarm 模式
- 如果您不打算使用 Swarm 进行部署,请改用 Docker Compose

Docker Swarm的先决条件
你必须要有docker,如果已经运行了Docker Swarm 输入命令docker system info 查看信息
如果没有运行 需要初始化Swarm集群 docker swarm init

Swarm 服务和Kubernetes 服务
这两个编排器对"服务"一词的定义截然不同。在 Swarm 中,服务同时提供调度和网络功能,负责创建容器并提供将流量路由到这些容器的工具。而在 Kubernetes 中,调度和网络功能是分开处理的,部署(或其他控制器)负责将容器调度为 Pod,而服务仅负责为这些 Pod 添加网络功能
创建和加入Swarm集群
所有机器都可通过网络通信,并都安装了Docker引擎 端口设置
必须启用以下端口。在某些系统中,这些端口默认是开放的
2377用于与管理节点通信的 TCP端口7946用于覆盖网络节点发现的 TCP/UDP端口4789用于覆盖网络流量的 UDP端口(可配置)端口
4789是 Swarm 数据路径端口(也称为 VXLAN 端口)的默认值。务必阻止任何不受信任的流量到达此端口,因为 VXLAN 不提供身份验证。此端口只能对受信任的网络开放,切勿在边界防火墙上开放
bash
# 临时关闭防火墙(测试环境)
systemctl stop firewalld
# 生产环境推荐开放指定端口(2377集群管理、7946节点通信、4789网络通信)
firewall-cmd --permanent --add-port=2377/tcp
firewall-cmd --permanent --add-port=7946/tcp
firewall-cmd --permanent --add-port=7946/udp
firewall-cmd --permanent --add-port=4789/udp
firewall-cmd --reload

该
--advertise-addr标志将管理节点配置为发布其地址IP。集群中的其他节点必须能够通过该 IP 地址访问管理节点
bash
docker swarm init --advertise-addr <MANAGER-IP>
## 输出信息有加入本集群的token
docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
此时查看node情况,会出现已经准备好的Manager 节点信息
bash
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
dxn1zf6l61qsb1josjja83ngz * manager1 Ready Active Leader
加入Swarm集群
在另一台工作机器上输入join --token命令即可加入Swarm集群,集群中的manager和worker可以指定,也可以修改升级或者降级
bash
docker swarm join \
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
192.168.99.100:2377
This node joined a swarm as a worker.
Docker Swarm 部署服务
- 该
docker service create命令用于创建服务。- 该
--name标志用于指定服务helloworld。- 该
--replicas标志指定 1 个正在运行的实例的期望状态。- 这些参数
alpine ping docker.com将服务定义为执行命令的 Alpine Linux 容器ping docker.com
bash
docker service create --replicas 1 --name helloworld alpine ping docker.com
9uk4639qpg7npwf3fn2aasksr
运行
docker service ls以下命令查看正在运行的服务列表,如果我们集群只有三台机器,但是我指定的副本是4个,也可以,会随机分配,并不一定是一台机器一个
bash
docker service ls
ID NAME SCALE IMAGE COMMAND
9uk4639qpg7n helloworld 1/1 alpine ping docker.com
运行
docker service inspect --pretty <SERVICE-ID>以显示有关服务的详细信息如果要以 json 格式返回服务详细信息,请运行不带
--pretty标志的相同命令
bash
[manager1]$ docker service inspect --pretty helloworld
ID: 9uk4639qpg7npwf3fn2aasksr
Name: helloworld
Service Mode: REPLICATED
Replicas: 1
Placement:
UpdateConfig:
Parallelism: 1
ContainerSpec:
Image: alpine
Args: ping docker.com
Resources:
Endpoint Mode: vip
运行以下命令
docker service ps <SERVICE-ID>查看哪些节点正在运行该服务
bash
[manager1]$ docker service ps helloworld
NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
helloworld.1.8p1vev3fq5zm0mi8g0as41w35 alpine worker2 Running Running 3 minutes
在集群中扩展服务
docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>
bash
docker service scale helloworld=5
helloworld scaled to 5
在集群中删除服务
bash
docker service rm helloworld
helloworld
服务滚动更新
部署一个基于 Redis 7.4.0 容器镜像的服务。然后,将使用滚动更新的方式将该服务升级到 Redis 7.4.1 容器镜像
--update-delay标志位用于配置服务任务或任务集更新之间的延迟时间
bash
docker service create \
--replicas 3 \
--name redis \
--update-delay 10s \
redis:7.4.0
0u6a4s31ybk7yw2wyvtikmu50
发布服务端口
创建服务时,可以使用该
--publish标志发布端口。` --port`target用于指定容器内部的端口,`published--bind` 用于指定路由网格上绑定的端口。如果省略端口published,则每个服务任务都会绑定一个随机的高位端口eg:将 nginx 容器中的 80 端口发布到 swarm 集群中任何节点的 8080 端口
bash
docker service create \
--name my-web \
--publish published=8080,target=80 \
--replicas 2 \
nginx

绕过路由网格
默认情况下,发布端口的 Swarm 服务会使用路由网格。当您连接到任何 Swarm 节点上发布的端口时(无论该节点是否运行特定服务),您都会被透明地重定向到运行该服务的工作节点。实际上,Docker 充当了 Swarm 服务的负载均衡器
要绕过路由网格,必须使用长
--publish服务并设置mode`--password` 参数host。如果省略该mode参数或将其设置为 `--password`ingress,则会使用路由网格
bash
docker service create --name dns-cache \
--publish published=53,target=53,protocol=udp,mode=host \
--mode global \
dns-cache
overlay网络
Docker集群会产生两种不同的流量:
控制和管理平面流量:这包括集群管理消息,例如加入或离开集群的请求。此类流量始终加密。
应用数据平面流量:包括容器流量以及与外部客户端之间的流量。
当您初始化一个集群或将 Docker 主机加入现有集群时,会在该 Docker 主机上创建两个新网络:
- 一个名为 `<overlay_network>` 的覆盖网络
ingress,用于处理与 Swarm 服务相关的控制和数据流量。当您创建 Swarm 服务但未将其连接到用户定义的覆盖网络时,它ingress默认连接到该网络。- 一个名为 的桥接网络
docker_gwbridge,它将各个 Docker 守护进程连接到参与集群的其他守护进程
创建覆盖网络
在Manager 节点创建网络
创建名为 test-network 的overlay网络(自定义网络名可修改)
--driver overlay:指定网络类型为 overlay,这是 Swarm 集群跨节点通信的唯一支持类型;--attachable:允许手动创建的容器(非 Swarm Service)也能加入该网络,提升灵活性;think-big-network:自定义网络名称,后续部署服务时需引用该名称
bash
docker network create --driver overlay --attachable test-network
验证网络是否创建成功,在Manager节点上执行
bash
docker network ls | grep test-network
部署服务指定ip和网络(用主机名约束更加稳妥)
bash
# 方式1:用IP约束部署
docker service create \
--name redis-service \
--network test-network \ # 加入自定义网络
--constraint node.ip==10.19.1.2 \ # 强制部署到10.19.1.2
--publish 6379:6379 \ # 端口映射
--replicas 1 \ # 单副本
redis:latest # 镜像名
# 方式2:用主机名约束(替换为10.19.1.2的实际主机名,如redis-node)
# docker service create \
# --name redis-service \
# --network test-network \
# --constraint node.hostname==redis-node \
# --publish 6379:6379 \
# --replicas 1 \
# redis:latest
数据持久化,例如Mysql(--mount)
bash
# 部署MySQL时添加数据挂载
docker service create \
--name db-service \
--network think-big-network \
--constraint node.ip==10.19.3.1 \
--publish 3306:3306 \
--replicas 1 \
--env MYSQL_ROOT_PASSWORD=123456 \
--mount type=bind,src=/home/ubuntu/mysql/data,dst=/var/lib/mysql \ # 数据持久化挂载
mysql:8.0
验证网络通信(直接用服务名,overlay网络自动解析)
bash
# 进入app-service容器
docker exec -it $(docker ps | grep app-service | awk '{print $1}') /bin/bash
# ping Redis服务(直接用服务名,overlay网络自动解析)
ping redis-service
# ping 数据库服务
ping db-service
# ping MinIO服务
ping minio-service