在 Swarm 中混合部署 Linux nginx 与 Windows IIS

解读

国内企业在“双轨”架构下常见:对外网关、静态资源跑在 Linux/nginx,内部旧业务跑在 Windows/IIS。Swarm 作为 Docker 官方内置编排,必须跨平台调度才能同时拉起两种 OS 容器。面试想验证三点:

  1. 是否理解 Swarm 的 Node 标签与平台约束
  2. 是否掌握 多平台镜像构建与推送(manifest list)
  3. 是否能在 Overlay 网络互通、Volume 挂载、服务发现 层面给出可落地的“混合”方案,而不是简单跑两个容器

知识点

  • Swarm 节点角色与管理:Linux manager + Windows worker 的最低配比要求
  • 平台约束--placement-prefconstraint:node.platform.os==windows/linux
  • 多平台镜像docker buildx 生成 manifest list,推送到 国内可访问的 Harbor 或阿里云 ACR,避免 Docker Hub 拉取超时
  • Overlay 网络:Linux 使用 ingress 与自定义 overlay;Windows 1809+ 才支持 L2Bridge + Overlay 混合,需提前在 daemon.json 中指定 com.docker.network.driver.overlay.ingress=true
  • 端口冲突与路由:Linux 80/443 由 ingress 统一入口,Windows IIS 业务端口建议 8080/8443 并通过 外部 LB 做七层转发
  • 持久化与隔离:Windows 容器挂载 SMB 全局映射而非 bind mount;Linux 使用 NFS 或本地 volume
  • 安全加固:Windows 容器镜像必须 基于 nanoserver 而非 servercore 缩小攻击面;Linux 侧用 distroless 或 alpine,非 root 运行
  • 故障排查:Windows 节点 docker service ps 状态为 “Pending” 时优先检查 OS 版本与镜像匹配;Linux 侧看 iptables 是否屏蔽 ingress 的 4789/7946 端口

答案

  1. 准备节点

    • 3 台 CentOS 7.9 作为 manager + Linux worker,安装 Docker 24.0.x,开启 IPVS 内核模块
    • 2 台 Windows Server 2022 作为 worker,安装 Docker EE 24.0 并加入同一 Swarm,执行
      docker swarm join --token <worker-token> manager-ip:2377
  2. 构建多平台镜像

    • 在 Linux CI 节点启用 docker buildx create --use
    • nginx 镜像:
      docker buildx build --platform linux/amd64 -t harbor.example.com/library/nginx:1.25 --push .
    • IIS 镜像(基于 mcr.microsoft.com/dotnet/framework:4.8-windowsservercore-ltsc2022):
      docker buildx build --platform windows/amd64 -t harbor.example.com/library/iis:2022 --push .
  3. 创建 Overlay 网络

    • Linux 侧:
      docker network create --driver overlay --attachable --subnet 10.10.0.0/16 cross-os
    • Windows 侧会自动同步该网络,无需重复创建
  4. 部署服务

    • nginx 服务:
      docker service create --name nginx --network cross-os --constraint 'node.platform.os==linux' --publish published=80,target=80,mode=ingress harbor.example.com/library/nginx:1.25
    • IIS 服务:
      docker service create --name iis --network cross-os --constraint 'node.platform.os==windows' --publish published=8080,target=80,mode=ingress harbor.example.com/library/iis:2022
  5. 验证与排障

    • docker service ls 两服务 REPLICAS=1/1
    • Linux 节点 curl http://localhost 返回 nginx 欢迎页;Windows 节点 curl http://localhost:8080 返回 IIS 默认页
    • 跨节点互通:在 Linux 容器内 ping iis 能解析 VIP 10.10.0.6,证明 Swarm DNS 工作正常

拓展思考

  • 若 Windows 节点版本低于 1809,Overlay 网络无法跨主机通信,只能改用 Host 模式 + 外部负载均衡,此时要 手动维护端口映射表
  • 国内云厂商的 CVM 安全组默认未放行 7946/4789,需在控制台提前放通,否则 ingress 网络会 间歇性 503
  • 生产环境建议把 nginx 作为边缘反向代理,通过 upstream 直接指向 IIS 的 service name:8080,实现 南北流量统一入口;同时给 IIS 加 read_only rootfs + gMSA 账号,解决 Windows 容器身份认证问题
  • 未来业务若继续拆分,可考虑 将 Windows 容器逐步迁移到 .NET 6 Linux 容器,降低混合维护成本,但遗留 COM+ 组件仍需 Windows 节点隔离运行,此时可用 node.label=legacy=true 做污点隔离,确保调度安全