在现有架构下,我主要维护的是一个运行在 AlmaLinux ECS 实例上的后端服务:基于 FastAPI 构建,通过 Docker Compose 进行容器化部署。服务中包含多条 AI 对话类 SSE(Server-Sent Events)长连接接口。
随着用户规模增加,我逐渐发现一个现实问题:Docker Compose 在滚动发布和长连接共存场景下,几乎无法实现真正的零停机更新。容器重建过程中,SSE 连接被强制断开,用户体验受到明显影响。
在与 AI 进行多轮技术探讨后,我重新审视了技术选型。结论是:在当前规模与复杂度下,并不需要直接迁移到 Kubernetes。采用 Docker Swarm 即可满足零停机更新与滚动发布的需求,同时保持架构复杂度可控。
经过半天实践,我成功将服务从 Docker Compose 迁移至 Docker Swarm。以下是关键迁移步骤与问题记录。
一、初始化 Swarm 集群
在 ECS 主机上执行:
docker swarm init
该命令会将当前 Docker Engine 切换为 Swarm 模式,并初始化为单节点集群(Manager)。对于单机部署场景,这已经足够。
二、调整 Compose 文件结构
Swarm 兼容 Compose 文件格式,但需要引入 deploy 段定义编排策略,例如:
- replicas:副本数量
- update_config:更新策略(并行数、延迟、顺序等)
- restart_policy:重启策略
例如可配置:
- 每次只更新一个副本
- 新副本就绪后再停止旧副本(start-first 策略)
这一步是实现“零停机滚动更新”的核心。
三、使用 Stack 部署
Swarm 不再使用 docker-compose up,而是通过 Stack 进行编排部署:
docker stack deploy -c docker-compose.yml your_stack_name
Stack 会将服务转换为 Swarm Service,并交由调度器管理。
四、迁移过程中遇到的问题
- 本地构建镜像无法拉取
由于镜像是本地构建,未推送至 Docker Hub 或私有仓库,Swarm 默认会尝试从远程仓库解析镜像并拉取,导致部署失败。
解决方式是在部署时添加:
–resolve-image never
该参数指示 Swarm 跳过远程镜像解析,直接使用本地镜像。
- Swarm 网络无法直接访问宿主机服务
在 Compose 模式下,容器可以通过 bridge 网络访问宿主机服务(如本地数据库或 Redis)。但在 Swarm overlay 网络中,默认无法直接访问宿主机 127.0.0.1。
解决方案是将服务地址改为:
host.docker.internal
或在 Linux 环境中使用:
host-gateway
并在 compose 文件中通过 extra_hosts 显式声明 host-gateway 映射。这样容器即可访问宿主机网络资源。
五、迁移结果与技术判断
迁移至 Docker Swarm 后:
- 支持多副本运行
- 支持滚动更新与回滚
- SSE 长连接在发布期间不中断
- 架构复杂度远低于 Kubernetes
在当前业务规模下,Swarm 提供了一个性价比极高的“轻量级编排层”。它弥补了 Docker Compose 在生产环境部署能力上的不足,同时避免了 Kubernetes 带来的学习成本和运维复杂度。
对于单机或小规模集群的 AI 服务而言,这是一个务实且工程上合理的选择。