Skip to content

Docker Swarm

Docker Swarm 是 Docker 内置的容器集群管理工具,将多台 Docker 主机组成一个集群,提供服务高可用和水平扩展能力。

Swarm 核心概念

概念说明
Swarm集群本身,由多个 Docker 节点组成
Node(节点)集群中的 Docker 主机
Manager(管理节点)负责集群管理和任务调度,奇数个保证高可用
Worker(工作节点)运行任务容器
Service(服务)定义要运行的任务(镜像、副本数、网络等)
Task(任务)服务中的单个容器实例
Stack(栈)多服务应用的部署单元(使用 Compose 文件)
┌─────────────────────────────────────────────┐
│                  Swarm 集群                  │
│                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
│  │ Manager1 │  │ Manager2 │  │ Manager3 │  │
│  │(Leader)  │  │(Follower)│  │(Follower)│  │
│  └──────────┘  └──────────┘  └──────────┘  │
│                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
│  │ Worker1  │  │ Worker2  │  │ Worker3  │  │
│  └──────────┘  └──────────┘  └──────────┘  │
└─────────────────────────────────────────────┘

初始化集群

初始化第一个 Manager 节点

bash
# 在 Manager 节点上执行(指定 Manager 的 IP)
docker swarm init --advertise-addr 192.168.1.100

# 输出:
# Swarm initialized: current node (xxx) is now a manager.
# To add a worker to this swarm, run the following command:
#   docker swarm join --token SWMTKN-1-xxxx 192.168.1.100:2377
# To add a manager to this swarm, run:
#   docker swarm join-token manager

添加 Worker 节点

在 Worker 节点上执行初始化时给出的命令:

bash
docker swarm join \
  --token SWMTKN-1-xxxx \
  192.168.1.100:2377

添加 Manager 节点(高可用)

bash
# 在现有 Manager 上获取 Manager 加入 token
docker swarm join-token manager

# 在新 Manager 节点上执行
docker swarm join \
  --token SWMTKN-1-manager-xxxx \
  192.168.1.100:2377

查看集群状态

bash
# 查看所有节点
docker node ls

# 输出示例
# ID            HOSTNAME    STATUS  AVAILABILITY  MANAGER STATUS
# abc123 *      manager1    Ready   Active        Leader
# def456        manager2    Ready   Active        Reachable
# ghi789        worker1     Ready   Active

服务管理

创建服务

bash
# 创建基本服务
docker service create \
  --name web \
  --replicas 3 \
  --publish published=80,target=80 \
  nginx:alpine

# 创建时挂载数据卷
docker service create \
  --name db \
  --mount type=volume,source=db-data,target=/var/lib/postgresql/data \
  --env POSTGRES_PASSWORD=secret \
  postgres:16-alpine

# 限制资源
docker service create \
  --name api \
  --replicas 2 \
  --limit-memory 512m \
  --limit-cpu 0.5 \
  --reserve-memory 256m \
  myapi:latest

# 配置重启策略
docker service create \
  --name worker \
  --restart-condition on-failure \
  --restart-max-attempts 3 \
  myworker:latest

查看服务

bash
# 列出所有服务
docker service ls

# 查看服务详情
docker service inspect web

# 查看服务的所有任务(副本)
docker service ps web

# 查看服务日志
docker service logs -f web

更新服务

bash
# 更新镜像(滚动更新)
docker service update --image nginx:1.25 web

# 修改副本数(扩缩容)
docker service scale web=5
docker service update --replicas 5 web

# 更新环境变量
docker service update \
  --env-add NEW_VAR=value \
  --env-rm OLD_VAR \
  api

# 更新资源限制
docker service update \
  --limit-memory 1g \
  api

# 回滚到上一版本
docker service rollback web

删除服务

bash
docker service rm web

Stack 部署

Stack 使用 Compose 文件部署多服务应用,是生产环境推荐方式:

docker-stack.yml:

yaml
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      restart_policy:
        condition: on-failure
      resources:
        limits:
          memory: 128M
    networks:
      - frontend

  api:
    image: myapi:latest
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 512M
    environment:
      DB_HOST: db
    networks:
      - frontend
      - backend

  db:
    image: postgres:16-alpine
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager  # 只在 Manager 节点运行
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - backend

volumes:
  db-data:

networks:
  frontend:
    driver: overlay
  backend:
    driver: overlay
bash
# 部署 Stack
docker stack deploy -c docker-stack.yml myapp

# 查看 Stack 状态
docker stack ls
docker stack services myapp
docker stack ps myapp

# 更新 Stack(重新部署)
docker stack deploy -c docker-stack.yml myapp

# 删除 Stack
docker stack rm myapp

节点管理

bash
# 查看节点详情
docker node inspect worker1

# 修改节点可用性
docker node update --availability drain worker1  # 排空节点(不接受新任务)
docker node update --availability active worker1  # 恢复

# 添加节点标签
docker node update --label-add zone=us-east worker1

# 提升 Worker 为 Manager
docker node promote worker1

# 降级 Manager 为 Worker
docker node demote manager2

# 删除节点(需先 drain)
docker node rm worker1

# 在节点上自行离开集群
docker swarm leave          # Worker 节点离开
docker swarm leave --force  # Manager 节点离开

服务放置约束

yaml
deploy:
  placement:
    constraints:
      - node.role == manager          # 只在 Manager 上运行
      - node.role == worker           # 只在 Worker 上运行
      - node.hostname == server1      # 只在特定主机
      - node.labels.zone == us-east  # 按自定义标签
    preferences:
      - spread: node.labels.zone      # 均匀分布在各 zone

Swarm 网络

Swarm 使用 overlay 网络实现跨主机容器通信:

bash
# 创建 overlay 网络(Swarm 模式下)
docker network create \
  --driver overlay \
  --attachable \           # 允许独立容器连接
  my-overlay-net

# 独立容器也可以连接
docker run -d \
  --network my-overlay-net \
  --name test \
  alpine sleep 3600

Secrets 管理

Swarm 提供安全的密钥管理,密钥加密存储,只分发给需要的服务:

bash
# 创建 secret
echo "my-secret-password" | docker secret create db_password -
docker secret create ssl_cert ./ssl/cert.pem

# 列出 secrets
docker secret ls

# 在服务中使用 secret
docker service create \
  --name db \
  --secret db_password \
  -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_password \
  mysql:8.0

# 删除 secret
docker secret rm db_password

在 Compose 文件中使用:

yaml
services:
  db:
    image: mysql:8.0
    secrets:
      - db_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    external: true  # 使用已存在的 secret
    # 或者
    file: ./secrets/db_password.txt  # 从文件创建

总结

Docker Swarm 提供了简单易用的集群管理能力:

  1. 初始化docker swarm init 一条命令建立集群
  2. 高可用:多 Manager 节点,奇数个(3 或 5)
  3. 服务管理docker service 命令管理服务
  4. 滚动更新:不停机更新,失败自动回滚
  5. Stack 部署:使用 Compose 文件声明式部署

下一节介绍 Swarm 集群的高级管理。