Docker Swarm
一、用途与触发条件
当项目需要编排多节点,并使用 docker swarm init/join、docker stack deploy 或带 deploy: 字段的 stack 文件时,触发本技能。需要决定 manager/worker 拓扑、rollout、rollback 或 quorum 恢复时,同样适用。
不适用于单机使用 docker compose up 的本地开发,也不适用于镜像构建——这两种情况应使用 $specsfy-specialist-docker。许多 Compose 键(profiles、depends_on.condition、运行时 build)在 docker stack deploy 中不生效。
当 rollout 属于发布流水线的一部分时,与 $specsfy-specialist-delivery-engineering 组合使用;当需要确定授权或回滚 rollout 的信号时,与 $specsfy-specialist-observability 组合使用。
二、流程
发布或完整部署时,在 $specsfy-specialist-deploy 下工作。先核对由 $specsfy-specialist-versioning 准备的 SEMVER,在执行 docker stack deploy 之前运行 verify-docker-tag,若 tag 不一致则中断。
在任何拓扑变更之前,先梳理 managers、workers、区域、labels、quorum 以及外部依赖(registry、storage、DNS)。
验证已发布镜像与测试过的镜像一致,且 stack 文件仅使用 docker stack deploy 支持的键(并非完整 Compose schema)。
定义 services、网络、ports、volumes、configs 和 secrets,并为每个共享资源指定明确的 owner。
配置 replicas、placement constraints/preferences、resources.limits/reservations、healthcheck 和 restart_policy。
设计 update_config 与 rollback_config(并行度、delay、start-first/stop-first 顺序、failure_action),确保新版本与旧版本在 rollout 期间共存时不破坏 API/数据契约。
在具代表性的 swarm 上应用(拓扑等价于 staging,而非单节点),并用 docker service ps 和 docker service logs 观察收敛过程。
记录部署、回滚、secret 轮换、Raft 状态备份以及 manager 丢失恢复预案的流程。
三、规范
在由 $specsfy-specialist-deploy 协调的部署中,默认使用 Cloudflare Tunnel 作为公网入口。cloudflared 与应用保持在同一 overlay 网络,不把 Laravel 端口发布到宿主机。当用户明确要求更换时,接受其他代理。
通过 Docker Secret 以文件形式挂载隧道 token,并用 --token-file 启动 cloudflared。绝不把该值写入 stack。
将依赖、应用与 ingress 拆分为不同 stack,按依赖顺序发布,等待每个服务声明的收敛后再开放公网路径。
将 migrations 集中到指定的一个副本。其余服务启动时关闭 migrations,防止 rollout 期间并发执行。
HTTP、队列、scheduler 和 WebSocket 使用同一不可变镜像,各自拥有命令和 healthcheck。当其他队列 supervisor 已启用时,备用 worker 保持零副本。
在 stack 之前创建外部加密 overlay 网络。数据服务仅处于内部网络;当 outbound-only 隧道符合项目设计时,可消除宿主机上的公网端口。
manager 保持奇数(1、3 或 5),生产环境绝不让 quorum 依赖单个 manager。
按 digest 发布不可变镜像(image@sha256:...),并确保所有 node 均可访问;不允许某 node 因本地构建而偏离。
使用按名称版本化的 secrets/configs(app_secret_v2),绝不把密钥嵌入 stack 文件的环境变量。
分离 ingress 网络、服务内部网络和数据网络;不通过 ports: 公开内部服务端口。
显式定义 resources.limits 和 reservations;不依赖最宽松 node 的隐式容量。
placement.constraints 仅使用受管 labels(node.labels.*),绝不硬编码 hostname。
不要假定某个 Compose 选项(profiles、build、develop、带 condition 的 depends_on)会被 stack deploy 遵守——在依赖之前先对照受支持字段列表验证。
四、反模式
在副本很少的服务上做滚动更新却未设置 update_config.order: start-first:旧副本在新副本健康之前就下线,服务会短暂失去容量。
在多副本或会重调度的服务上使用本地卷(bind 或无分布式驱动的命名卷):调度器把容器迁到其他 node 时数据会“消失”。
就地修改 secret 文件内容:Swarm 按名称将 secrets 视为不可变;正确做法是创建新版本(app_secret_v2),挂到服务上后再移除旧的。
把开发用的 docker-compose.yml 与生产 stack 文件混为一谈:healthcheck、deploy:、secrets 和 overlay 网络往往缺失或不一致。
五、验证
部署前运行 docker stack config --compose-file <文件>(或提供方等价校验),以发现插值和 schema 错误。
在整个 rollout 期间观察 docker service ps <服务>、docker service logs、期望副本与实际副本以及 node 事件,而不只是结束时查看。
模拟 worker 故障,并在获得授权且备份已验证的环境中模拟单个 manager 丢失,确认剩余 manager 仍能维持 quorum。
验证应用回滚(docker service update --rollback 或 rollback_config),以及两个版本共存窗口期内数据迁移的兼容性。
这四点未验证前,不得宣称 stack“已可上生产”;“在我 node 上能跑”不是集群收敛的证据。
六、相关技能
$specsfy-specialist-deploy 协调服务器、镜像、Ansible 与 stack 发布;本技能只治理 Swarm。
$specsfy-specialist-versioning 准备 SEMVER,并核对镜像与 stack 清单使用的版本。
$specsfy-specialist-ansible 准备和维护 node;本技能治理 quorum、scheduler、services 与 Swarm 网络。
$specsfy-specialist-laravel 定义应用契约,$specsfy-specialist-redis 定义服务使用的持久化/缓存。
$specsfy-specialist-docker 用于镜像构建、Dockerfile 和 Compose 本地开发——边界:Swarm 从应用开始跨多节点运行并带有集群状态时开始。
当服务 rollout 属于跨环境晋升的发布流水线时,使用 $specsfy-specialist-delivery-engineering。
当需要埋点健康、错误率、延迟等决定继续、暂停或回滚 rollout 的信号时,使用 $specsfy-specialist-observability。
$specsfy-specialist-debian-server 用于集群端口、内核、文件系统与 node 的 Docker 服务。
阅读 references/standards.md,了解 Raft 拓扑、secrets/configs 生命周期、overlay 网络、rollout 策略与灾难恢复,附 Docker 官方文档来源。