Docker Swarm 完整教程

一、Docker Swarm 核心概念

1.1 集群化(Clustering)

从主机层面来看,Docker Swarm 管理的是 Docker Host 集群,首先需理解集群化这一关键概念:

  • 集群定义:由一组网络互联的服务器组成,协同工作且具备 “单一系统” 特性,可提供高可用、负载均衡和并行处理能力。

  • 集群与独立服务器的区别

    :

    • 独立服务器部署:资源利用率难最优,应用资源需求波动时缺乏弹性,服务器宕机需手动迁移应用。
    • 集群部署:无需关注单个服务器,仅需指定应用所需的内存、CPU 等资源,由集群管理程序(如 Docker Swarm)自动分配任务;集群容量可通过添加 / 删除节点调整,始终保持整体特性。

1.2 Docker Swarm Mode

  • 版本里程碑:Docker v1.12 是关键版本,Swarm 功能完全集成到 Docker Engine,无需依赖外部数据库(如 Consul、etcd、Zookeeper)。

  • 核心优势

    :

    • 零额外配置:安装 Docker 后,启动 Swarm Mode 即可使用集群管理和服务发现功能。
    • 易用性:相比 Kubernetes,创建集群无需额外安装软件,适合作为容器编排引擎的入门学习工具。
  • 模式特性

    :

    • 未启动 Swarm Mode:仅支持普通容器命令。
    • 启动 Swarm Mode:新增 Service 编排能力,支持同一主机同时运行 Swarm Service 和独立容器。

1.3 三大核心概念

概念定义与作用
swarm运行 Docker Engine 的多主机集群。Docker Engine 初始化或加入 swarm 时自动启动 Swarm Mode,具备集群管理和编排能力。
node集群中的每个 Docker Engine 节点,分两类: - manager node:执行部署命令、拆解任务、管理集群状态,多 manager 节点会自动选举 leader。 - worker node:接收并执行 manager 分配的任务,定期上报自身和任务状态;默认 manager 同时也是 worker,可配置为 “纯管理节点”。
service定义 worker 节点需执行的任务,Swarm 的核心目标是保证 service 始终处于 “期望状态”(如指定副本数)。 示例:启动 3 个 httpd 副本,worker2 宕机后,manager 会自动在 worker3 补全副本。

二、部署 Swarm 集群

2.1 集群规划

本次搭建三节点集群,节点信息如下:

节点角色主机名IP 地址说明
manager nodeswarm-manager192.168.108.30集群管理节点,负责编排
worker nodeswarm-worker1192.168.108.31工作节点,执行任务
worker nodeswarm-worker2192.168.108.32工作节点,执行任务

环境要求:

  • 所有节点 Docker 版本 ≥ v1.12,操作系统为 CentOS Stream 8(其他 Linux 系统也可)。
  • 关闭所有节点防火墙(或放行 Swarm 所需端口:2377/tcp、7946/tcp/udp、4789/udp)。
  • 通过克隆 Docker 教案中的虚拟机生成三个节点,修改各节点的 IP 地址和主机名。

2.2 初始化 Manager 节点

在 swarm-manager 节点执行以下命令,初始化 Swarm 集群:

bash
在这里插入图片描述

# --advertise-addr 指定与其他节点通信的 IP(即 manager 自身 IP)
[root@swarm-manager ~]# docker swarm init --advertise-addr 192.168.108.30
命令输出解读

执行后会返回类似以下内容,包含关键信息:

在这里插入图片描述

  • ① swarm-manager 已成为 manager node。
  • ② 提供添加 worker node 的命令(含唯一 token)。
  • ③ 提示添加额外 manager node 的方法。
验证 Manager 节点状态
[root@swarm-manager ~]# docker node ls
ID                           HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo *   swarm-manager   Ready     Active         Leader           26.1.3

此时集群仅包含 1 个 manager 节点,* 表示当前操作的节点,Leader 表示该节点是集群领导者。

2.3 添加 Worker 节点

在 swarm-worker1 和 swarm-worker2 节点分别执行步骤 2.2 中返回的 docker swarm join 命令(需携带正确 token):

# swarm-worker1 节点执行
[root@swarm-worker1 ~]# docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377
This node joined a swarm as a worker.

# swarm-worker2 节点执行(命令相同)
[root@swarm-worker2 ~]# docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377
This node joined a swarm as a worker.
验证 Worker 节点加入结果

回到 swarm-manager 节点,执行 docker node ls 查看集群节点列表:

[root@swarm-manager ~]# docker node ls
ID                           HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo *   swarm-manager   Ready     Active         Leader           26.1.3
s3o9n5wkkbiyc21ehmk3xecvk     swarm-worker1   Ready     Active         -                26.1.3
mdudczt56hzbaw7aum3smrula     swarm-worker2   Ready     Active         -                26.1.3

可见 swarm-worker1 和 swarm-worker2 已成功加入,MANAGER STATUS 为 - 表示其为 worker 节点。

找回 Worker 加入命令

若未记录初始化时的 join 命令,可在 manager 节点执行以下命令查看:

[root@swarm-manager ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5it8t4f2tbrmxuhahkwp7i4jzhq7q14l35tkjotbiln0bztrzw-bmwlgmv1inatgm1hpl1739ncy 192.168.108.30:2377

三、运行第一个 Service

3.1 部署 Service

在 swarm-manager 节点执行以下命令,部署一个基于 httpd 镜像的 Service:

# --name 为 Service 命名,httpd 为镜像名
[root@swarm-manager ~]# docker service create --name web_server httpd
1ntzbsmbu3q3d4f969gpu0a8c  # Service ID
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service 1ntzbsmbu3q3d4f969gpu0a8c converged

3.2 查看 Service 状态

1. 查看 Service 列表
[root@swarm-manager ~]# docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
1ntzbsmbu3q3   web_server   replicated   1/1        httpd:latest
  • REPLICAS: 1/1:表示 Service 期望的副本数为 1,当前已启动 1 个副本,部署完成。
  • MODE: replicated:表示 Service 采用 “副本模式”(按指定数量分布副本)。
2. 查看副本详情

通过 docker service ps <service 名> 查看副本的运行节点和状态:

[root@swarm-manager ~]# docker service ps web_server
ID             NAME           IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lfwcnkg6pgth   web_server.1   httpd:latest   swarm-worker2   Running         Running 56 seconds ago

可见唯一副本被分配到 swarm-worker2 节点,状态为 Running。

3. 验证容器运行(可选)

登录 swarm-worker2 节点,通过 docker ps 确认 httpd 容器已启动:

[root@swarm-worker2 ~]# docker ps
CONTAINER ID   IMAGE          COMMAND              CREATED         STATUS         PORTS     NAMES
bef3b50af9ea   httpd:latest   "httpd-foreground"   2 minutes ago   Up 2 minutes   80/tcp    web_server.1.lfwcnkg6pgthdkqno2pu4w8n3

当前 web_server 在 swarm 中的分布如图所示。

在这里插入图片描述

四、Service 伸缩(Scale Up/Down)

4.1 扩展副本数(Scale Up)

对于 Web 服务,通常需要多副本实现负载均衡和高可用,执行以下命令将 web_server 副本数扩展到 5:

bash

[root@swarm-manager ~]# docker service scale web_server=5
web_server scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service web_server converged
查看扩展结果

bash

# 查看 Service 副本数
[root@swarm-manager ~]# docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
1ntzbsmbu3q3   web_server   replicated   5/5        httpd:latest

# 查看副本分布
[root@swarm-manager ~]# docker service ps web_server
ID             NAME           IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lfwcnkg6pgth   web_server.1   httpd:latest   swarm-worker2   Running         Running 4 minutes ago
q4006zahgaqm   web_server.2   httpd:latest   swarm-worker1   Running         Running 53 seconds ago
ug6dgvoycg91   web_server.3   httpd:latest   swarm-worker2   Running         Running about a minute ago
324xfyww2awh   web_server.4   httpd:latest   swarm-manager   Running         Running about a minute ago
v4btzz1lr69q   web_server.5   httpd:latest   swarm-worker1   Running         Running 53 seconds ago

5 个副本分布在 3 个节点上,默认 manager 节点同时作为 worker 节点,因此 swarm-manager 也运行了 1 个副本。

在这里插入图片描述

4.2 配置 Manager 为 “纯管理节点”

若不希望 manager 节点运行 Service(避免消耗管理资源),可执行以下命令将其可用性设为 Drain(拒绝接收新任务,已运行任务会迁移):

[root@swarm-manager ~]# docker node update --availability drain swarm-manager
swarm-manager
验证节点状态
[root@swarm-manager ~]# docker node ls
ID                           HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo *   swarm-manager   Ready     Drain          Leader           26.1.3  # 可用性变为 Drain
s3o9n5wkkbiyc21ehmk3xecvk     swarm-worker1   Ready     Active         -                26.1.3
mdudczt56hzbaw7aum3smrula     swarm-worker2   Ready     Active         -                26.1.3
查看副本迁移结果
[root@swarm-manager ~]# docker service ps web_server
ID             NAME                 IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lfwcnkg6pgth   web_server.1         httpd:latest   swarm-worker2   Running         Running 8 minutes ago
q4006zahgaqm   web_server.2         httpd:latest   swarm-worker1   Running         Running 4 minutes ago
ug6dgvoycg91   web_server.3         httpd:latest   swarm-worker2   Running         Running 4 minutes ago
732oh5htny76   web_server.4         httpd:latest   swarm-worker2   Running         Running 49 seconds ago
324xfyww2awh   \_ web_server.4     httpd:latest   swarm-manager   Shutdown        Shutdown 50 seconds ago  # 原副本已关闭
v4btzz1lr69q   web_server.5         httpd:latest   swarm-worker1   Running         Running 4 minutes ago

swarm-manager 上的副本 web_server.4 已被关闭,同时在 swarm-worker2 上新建副本以维持 5 个副本总数。

在这里插入图片描述

4.3 缩减副本数(Scale Down)

执行以下命令将副本数缩减到 3:

bash

[root@swarm-manager ~]# docker service scale web_server=3
web_server scaled to 3
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service web_server converged
查看缩减结果
[root@swarm-manager ~]# docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
1ntzbsmbu3q3   web_server   replicated   3/3        httpd:latest

[root@swarm-manager ~]# docker service ps web_server
ID             NAME           IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lfwcnkg6pgth   web_server.1   httpd:latest   swarm-worker2   Running         Running 10 minutes ago
q4006zahgaqm   web_server.2   httpd:latest   swarm-worker1   Running         Running 6 minutes ago
ug6dgvoycg91   web_server.3   httpd:latest   swarm-worker2   Running         Running 7 minutes ago
324xfyww2awh   web_server.4   httpd:latest   swarm-manager   Shutdown        Shutdown 2 minutes ago  # 多余副本已关闭

web_server.4 和 web_server.5 两个副本被删除,仅保留 3 个副本。

在这里插入图片描述

五、Swarm 故障切换(Failover)

Swarm 内置故障切换机制,无需额外配置,仅需指定 Service 的 “期望状态”,集群会自动维持该状态。

5.1 模拟节点故障

以 swarm-worker1 节点宕机为例,执行以下命令关闭该节点:

在这里插入图片描述

[root@swarm-worker1 ~]# shutdown now

5.2 观察故障检测与副本迁移

1. 查看节点状态

在 swarm-manager 节点执行 docker node ls,可见 swarm-worker1 状态变为 Down:

[root@swarm-manager ~]# docker node ls
ID                           HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
bpuyqqwojwjz9avzuaeyjszyo *   swarm-manager   Ready     Drain          Leader           26.1.3
s3o9n5wkkbiyc21ehmk3xecvk     swarm-worker1   Down      Active         -                26.1.3  # 节点故障
mdudczt56hzbaw7aum3smrula     swarm-worker2   Ready     Active         -                26.1.3
2. 查看副本迁移结果
[root@swarm-manager ~]# docker service ps web_server
ID             NAME                 IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lfwcnkg6pgth   web_server.1         httpd:latest   swarm-worker2   Running         Running 41 minutes ago
gx95mteiiaq1   web_server.2         httpd:latest   swarm-worker2   Running         Running about a minute ago  # 新副本
q4006zahgaqm   \_ web_server.2     httpd:latest   swarm-worker1   Shutdown        Shutdown 37 minutes ago    # 故障节点副本关闭
ug6dgvoycg91   web_server.3         httpd:latest   swarm-worker2   Running         Running 38 minutes ago
324xfyww2awh   web_server.4         httpd:latest   swarm-manager   Shutdown        Shutdown 34 minutes ago
  • 原运行在 swarm-worker1 上的 web_server.2 被标记为 Shutdown。

  • Swarm 自动在 swarm-worker2 上新建 web_server.2 副本,维持 3 个副本的期望状态。

在这里插入图片描述

六、访问 Swarm Service

6.1 重新部署 Service(便于演示)

先删除原有 web_server,重新创建 2 个副本的 Service:

# 1. 删除原有 Service
[root@swarm-manager ~]# docker service rm web_server
web_server

# 2. 新建 Service,指定 2 个副本
[root@swarm-manager ~]# docker service create --name web_server --replicas=2 httpd
izro3jrl6e09czc0iz08q9p44
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service izro3jrl6e09czc0iz08q9p44 converged

# 3. 查看副本分布
[root@swarm-manager ~]# docker service ps web_server
ID             NAME           IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
9zve246nlqed   web_server.1   httpd:latest   swarm-worker1   Running         Running 12 seconds ago
yvker0qkyfe2   web_server.2   httpd:latest   swarm-worker2   Running         Running 13 seconds ago

6.2 容器层面的访问限制

每个副本本质是一个容器,默认仅能在容器所在主机访问:

  1. 在swarm-worker1查看容器网络配置:

    [root@swarm-worker1 ~]# docker inspect web_server.1.9zve246nlqedn272fgtddepok | grep -A 10 "Networks"
    "Networks": {
        "bridge": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "MacAddress": "02:42:ac:11:00:02",
            "NetworkID": "325e2b265f380ba7278c32b3a6a0def045452e684b23eae5341b494d864a262a",
            "EndpointID": "8e3002fa399c0b412ae04a12481d9824db22bc0c54e6c2bd7b5c47e6705d5344",
            "Gateway": "172.17.0.1",
            "IPAddress": "172.17.0.2",  # 容器 IP
            "IPPrefixLen": 16,
    
  2. 在swarm-worker1访问容器:

    [root@swarm-worker1 ~]# curl 172.17.0.2
    <html><body><h1>It works!</h1></body></html>
    

    仅能在容器所在主机访问,无法从外部网络或其他节点访问。

6.3 暴露 Service 到外部网络

需通过端口映射将容器端口暴露到主机,有两种方式:

1. 为已有 Service 添加端口映射
# --publish-add 8080:80:将容器 80 端口映射到主机 8080 端口
[root@swarm-manager ~]# docker service update --publish-add 8080:80 web_server
web_server
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service web_server converged
2. 新建 Service 时直接指定端口映射
docker service create --name web_server --publish 8080:80 --replicas=2 httpd
3. 验证外部访问

从集群任意节点(或外部主机,需网络互通)访问 8080 端口:

# 访问 manager 节点
[root@swarm-manager ~]# curl http://192.168.108.30:8080
<html><body><h1>It works!</h1></body></html>

# 访问 worker1 节点
[root@swarm-manager ~]# curl http://192.168.108.31:8080
<html><body><h1>It works!</h1></body></html>

# 访问 worker2 节点
[root@swarm-manager ~]# curl http://192.168.108.32:8080
<html><body><h1>It works!</h1></body></html>

关键特性:无论访问哪个节点的 8080 端口,均可访问到 web_server,这依赖 Swarm 的 routing mesh 功能。

七、Routing Mesh 与 Swarm 网络

7.1 Routing Mesh 原理

在这里插入图片描述

  • 定义:Swarm 内置的负载均衡机制,外部请求访问任意节点的映射端口时,会自动转发到 Service 的任意副本。

  • 核心作用

    :

    • 无需关心副本分布节点,访问集群任意节点均可触达 Service。
    • 支持配置外部负载均衡器(如 HAProxy),将请求分发到集群节点的映射端口,实现更高层级的负载均衡。
架构示意图

在这里插入图片描述

外部请求 → HAProxy(可选)→ 集群任意节点:8080 → Routing Mesh → Service 副本
                          ↓
                  192.168.108.30:8080(manager)
                  192.168.108.31:8080(worker1)
                  192.168.108.32:8080(worker2)

7.2 Swarm 核心网络

执行 docker network ls 查看节点网络:

[root@swarm-worker1 ~]# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
325e2b265f38   bridge            bridge    local
06615073d3f0   docker_gwbridge   bridge    local
77d2734d1c55   host              host      local
t2ie77rl777k   ingress           overlay   swarm  # Swarm 自动创建
a0663936827d   none              null      local
网络名称类型作用
ingressoverlaySwarm 创建时自动生成,跨主机容器通信的核心网络;Service 配置端口映射后,副本会自动接入此网络。
docker_gwbridgebridge连接容器与主机网络,使容器能够访问外部网络(如互联网)。
bridge/host/none本地网络与普通 Docker 网络功能一致,仅支持单主机内容器通信。

7.3 端口映射后的网络变化

配置 --publish-add 8080:80 后,Swarm 会重启所有副本并切换网络:

[root@swarm-manager ~]# docker service ps web_server
ID             NAME                 IMAGE          NODE           DESIRED STATE   CURRENT STATE           ERROR   PORTS
lwfdj841ph0g   web_server.1         httpd:latest   swarm-worker1   Running         Running 28 seconds ago
gh9s2wst0k1m   \_ web_server.1     httpd:latest   swarm-worker1   Shutdown        Shutdown 29 seconds ago
2yc07ps3oejh   web_server.2         httpd:latest   swarm-worker2   Running         Running 25 seconds ago
jv61apqesurf   \_ web_server.2     httpd:latest   swarm-worker2   Shutdown        Shutdown 25 seconds ago

查看新副本的网络配置,可见容器已接入 ingress 网络:

[root@swarm-worker1 ~]# docker inspect web_server.1.lwfdj841ph0glbrwwjucmckex | grep -A 5 "ingress"
"ingress": {
    "IPAMConfig": {
        "IPv4Address": "10.0.0.15"  # ingress 网络分配的 IP
    },
    "Links": null,
    "Aliases": [
        "lwfdj841ph0glbrwwjucmckex",
        "web_server.1.lwfdj841ph0glbrwwjucmckex"
    ],
:latest   swarm-worker2   Running         Running 25 seconds ago
jv61apqesurf   \_ web_server.2     httpd:latest   swarm-worker2   Shutdown        Shutdown 25 seconds ago

查看新副本的网络配置,可见容器已接入 ingress 网络:

[root@swarm-worker1 ~]# docker inspect web_server.1.lwfdj841ph0glbrwwjucmckex | grep -A 5 "ingress"
"ingress": {
    "IPAMConfig": {
        "IPv4Address": "10.0.0.15"  # ingress 网络分配的 IP
    },
    "Links": null,
    "Aliases": [
        "lwfdj841ph0glbrwwjucmckex",
        "web_server.1.lwfdj841ph0glbrwwjucmckex"
    ],
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐