Docker Compose 完全指南 / 第 11 章 · Swarm 部署:deploy、replicas、update_config
第 11 章 · Docker Swarm 部署
11.1 Docker Swarm 简介
Docker Swarm 是 Docker 原生的集群编排工具,将多台 Docker 主机组成一个虚拟的 Docker 引擎。
Swarm vs Compose 独立模式
| 维度 | Compose 独立模式 | Swarm 模式 |
|---|---|---|
| 节点数 | 单机 | 多节点集群 |
| 服务发现 | 内部 DNS | 内部 DNS + Routing Mesh |
| 负载均衡 | 无 | 内置 Ingress LB |
| 滚动更新 | 不支持 | ✅ 原生支持 |
| 自愈 | restart 策略 | 自动重新调度 |
| Secrets | 基于文件 | 加密分发 + 内存存储 |
| 配置管理 | 文件挂载 | 集群级 Config 对象 |
| 部署命令 | docker compose up | docker stack deploy |
何时使用 Swarm?
你的需求是什么?
├── 本地开发/测试 → Compose 独立模式 ✅
├── 单机轻量生产 → Compose + restart 策略 ✅
├── 多节点高可用 → Swarm ✅ 或 Kubernetes
├── 大规模企业级 → Kubernetes ✅
└── 中小团队简单集群 → Swarm ✅(运维复杂度远低于 K8s)
11.2 初始化 Swarm 集群
单节点 Swarm
# 初始化 Swarm
docker swarm init
# 查看节点
docker node ls
# ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
# xxx node1 Ready Active Leader
多节点 Swarm
# 在 Manager 节点上
docker swarm init --advertise-addr 192.168.1.100
# 输出 join token,用于 Worker 加入
# docker swarm join --token SWMTKN-xxx 192.168.1.100:2377
# 在 Worker 节点上执行上述 join 命令
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377
# 查看集群节点
docker node ls
节点角色
| 角色 | 说明 | 最少节点 |
|---|---|---|
| Manager | 运行 Swarm 管理服务(Raft 共识) | 1(生产建议 3 或 5) |
| Worker | 运行应用服务 | 0+ |
11.3 deploy 配置
deploy 配置专门用于 Swarm 模式的部署策略。
完整的 deploy 配置
services:
web:
image: myapp:latest
deploy:
# 副本数
replicas: 3
# 部署约束
placement:
constraints:
- node.role == worker # 只部署到 Worker 节点
- node.labels.zone == east # 部署到标记为 east 的节点
preferences:
- spread: node.labels.zone # 尽量分散到不同可用区
# 资源限制
resources:
limits:
cpus: "0.50" # 最多使用 0.5 个 CPU
memory: 512M # 最多使用 512MB 内存
reservations:
cpus: "0.25" # 保留 0.25 个 CPU
memory: 256M # 保留 256MB 内存
devices:
- capabilities: [gpu] # 保留 GPU
count: 1
# 滚动更新策略
update_config:
parallelism: 1 # 每次更新 1 个容器
delay: 30s # 每批更新间隔
failure_action: rollback # 失败时回滚
monitor: 60s # 监控 60s 判断是否成功
max_failure_ratio: 0.1 # 允许 10% 失败率
order: start-first # 先启动新容器再停止旧容器
# 回滚策略
rollback_config:
parallelism: 1
delay: 10s
failure_action: pause
monitor: 30s
max_failure_ratio: 0
order: stop-first
# 重启策略
restart_policy:
condition: on-failure # none | on-failure | any
delay: 5s # 重启前等待
max_attempts: 3 # 最大重启次数
window: 120s # 判断重启成功的时间窗口
# 端点模式
endpoint_mode: vip # vip(默认)| dnsrr
# 服务标签
labels:
com.example.project: myapp
com.example.environment: production
# 网络
networks:
- frontend
- backend
# 端口(Swarm 模式下使用 ingress 发布)
ports:
- target: 80
published: "80"
protocol: tcp
mode: ingress # ingress(集群级)| host(单节点)
11.4 副本与扩展
设置副本数
services:
web:
image: myapp:latest
deploy:
replicas: 3 # 运行 3 个副本
动态扩缩容
# 使用 docker service scale
docker service scale myapp_web=5
# 使用 docker compose(需要 deploy 配置)
docker compose up -d --scale web=5
# 注意:--scale 会覆盖 compose.yaml 中的 replicas
# 但不能用于已发布到 Swarm 的 stack
副本分布
services:
web:
deploy:
replicas: 6
placement:
constraints:
- node.role == worker
preferences:
- spread: node.labels.zone # 均匀分布到不同 zone
Zone A (Worker 1): web.1 web.3 web.5
Zone B (Worker 2): web.2 web.4 web.6
11.5 滚动更新
更新策略
services:
web:
image: myapp:1.0.0
deploy:
replicas: 6
update_config:
parallelism: 2 # 每次同时更新 2 个
delay: 10s # 两批之间等待 10s
failure_action: rollback
monitor: 30s
order: start-first # 推荐:先启新的再停旧的
更新时序
初始状态: [v1 v1 v1 v1 v1 v1]
第 1 批 (parallelism=2):
启动 v2, v2 → 停止 v1, v1
结果: [v1 v1 v1 v1 v2 v2]
等待 10s...
第 2 批:
启动 v2, v2 → 停止 v1, v1
结果: [v1 v1 v2 v2 v2 v2]
等待 10s...
第 3 批:
启动 v2, v2 → 停止 v1, v1
结果: [v2 v2 v2 v2 v2 v2] ✅ 更新完成
更新命令
# 更新镜像版本
docker service update --image myapp:2.0.0 myapp_web
# 使用 Compose(修改 compose.yaml 后重新 deploy)
docker stack deploy -c compose.yaml myapp
# 手动回滚
docker service rollback myapp_web
start-first vs stop-first
| 顺序 | 说明 | 适用场景 |
|---|---|---|
start-first | 先启动新容器,再停止旧容器 | Web 服务(零停机) |
stop-first | 先停止旧容器,再启动新容器 | 有状态服务(端口冲突、数据一致性) |
11.6 资源限制
services:
web:
deploy:
resources:
limits:
cpus: "1.0" # 硬限制:最多 1 个 CPU
memory: 1G # 硬限制:最多 1GB 内存
reservations:
cpus: "0.5" # 软保证:至少 0.5 个 CPU
memory: 512M # 软保证:至少 512MB 内存
# GPU 资源
ml-worker:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1 # 使用 1 个 GPU
capabilities: [gpu]
⚠️ 注意:
deploy.resources仅在 Swarm 模式下生效。独立模式下使用docker compose时需要通过docker run的--cpus和--memory参数,或在docker-compose.yaml中不使用deploy而直接通过mem_limit等属性(V1 遗留方式)。
11.7 部署约束
节点约束
services:
db:
deploy:
placement:
constraints:
# 节点角色
- node.role == manager
- node.role == worker
# 节点 ID
- node.id == abc123def
# 节点主机名
- node.hostname == server-01
# 自定义标签
- node.labels.zone == us-east
- node.labels.disk == ssd
- node.labels.environment == production
# 操作系统
- node.platform.os == linux
- node.platform.arch == x86_64
标签管理
# 给节点添加标签
docker node update --label-add zone=us-east node1
docker node update --label-add disk=ssd node1
docker node update --label-add zone=us-west node2
# 查看节点标签
docker node inspect --format '{{ .Spec.Labels }}' node1
11.8 Stack 部署
部署 Stack
# 初始化 Swarm(如果还没有)
docker swarm init
# 部署 Stack
docker stack deploy -c compose.yaml myapp
# 查看 Stack
docker stack ls
# 查看 Stack 的服务
docker stack services myapp
# 查看 Stack 的任务
docker stack ps myapp
Stack 更新
# 修改 compose.yaml 后重新部署
docker stack deploy -c compose.yaml myapp
# Swarm 会自动执行滚动更新
Stack 删除
docker stack rm myapp
与 docker compose 的区别
| 维度 | docker compose up | docker stack deploy |
|---|---|---|
| 模式 | 独立模式 | Swarm 模式 |
build 指令 | ✅ 支持 | ❌ 不支持(需预构建镜像) |
depends_on | ✅ 支持 | ❌ 不支持 |
restart | ✅ 支持 | ❌ 使用 restart_policy |
| 网络创建 | 默认 bridge | overlay 网络 |
| 端口发布 | 直接映射 | ingress routing mesh |
| Secrets | 基于文件 | 加密分发 |
11.9 Overlay 网络
Swarm 使用 overlay 网络实现跨节点通信。
services:
web:
image: myapp:latest
networks:
- frontend
- backend
db:
image: postgres:16
networks:
- backend
networks:
frontend:
driver: overlay
attachable: true # 允许非 Swarm 容器连接
backend:
driver: overlay
internal: true # 不允许外部访问
11.10 完整的 Swarm Stack 示例
# compose.swarm.yaml
services:
web:
image: myregistry.io/myapp-web:${VERSION:-latest}
ports:
- target: 80
published: "80"
mode: ingress
networks:
- frontend
- backend
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
failure_action: rollback
rollback_config:
parallelism: 1
order: stop-first
restart_policy:
condition: any
delay: 5s
placement:
constraints:
- node.role == worker
preferences:
- spread: node.labels.zone
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
networks:
- backend
volumes:
- pgdata:/var/lib/postgresql/data
secrets:
- db_password
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
deploy:
replicas: 1
placement:
constraints:
- node.labels.db == true
resources:
limits:
memory: 1G
networks:
frontend:
driver: overlay
backend:
driver: overlay
internal: true
volumes:
pgdata:
driver: local
secrets:
db_password:
external: true # 使用 docker secret create 创建
# 部署
docker secret create db_password ./secrets/db_password.txt
docker stack deploy -c compose.swarm.yaml myapp
11.11 小结
| 概念 | 说明 |
|---|---|
deploy | Swarm 专用配置,控制副本、更新、资源等 |
replicas | 服务副本数 |
update_config | 滚动更新策略(并行度、间隔、失败处理) |
restart_policy | Swarm 模式的重启策略 |
placement | 部署约束,控制服务运行在哪些节点 |
docker stack deploy | 使用 Compose 文件部署 Swarm Stack |
| Overlay 网络 | 跨节点容器通信 |
扩展阅读
上一章:第 10 章 · 敏感信息 ← | 下一章:第 12 章 · 日志 →