You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Swarm环境下单A-record实现服务内部路由方案咨询

解决方案:利用Docker Swarm路由网格+统一入口代理搞定单A记录路由&故障转移

嘿,你的需求完全能实现!而且刚好匹配你只用Docker不用K8s的场景,核心就是靠Docker Swarm内置的路由网格(Routing Mesh)+统一入口代理来搞定,甚至还能顺便实现故障转移。下面给你一步步拆解:

核心思路

简单说就是:

  1. 把所有服务都用Swarm的服务模式部署,让Swarm自动帮你做内部路由——不管服务跑在哪个worker节点,集群里所有节点的指定端口都会自动转发到服务所在的机器。
  2. 只把所有域名的A记录指向你指定的那个Judge Worker Target 1的公网IP,然后在这个节点(或者新增个专门的入口节点)部署一个统一的反向代理,把域名请求转发到Swarm服务的内部域名,剩下的路由和故障转移全交给Swarm处理。

具体操作步骤

1. 先确保Swarm集群正常跑起来

如果还没初始化Swarm,先在manager节点跑:

docker swarm init --advertise-addr <你的manager公网IP>

然后把4个worker节点用manager输出的docker swarm join命令加入集群就行。

2. 确认Swarm路由网格是开启的(默认已经开了,放心)

路由网格是Swarm的核心能力之一,默认启用,它能让集群内所有节点的发布端口都映射到服务实例。可以跑个命令验证下:

docker swarm inspect | grep -i routing-mesh

输出里Enabled要是true就没问题。

3. 用Swarm服务模式部署你的服务

别再用docker run了,改用docker service create,这样服务会被Swarm管理,还能自动生成内部域名。比如部署grav:

docker service create \
  --name grav-service \
  --publish 80:80 \
  --replicas 2 \ # 可以多开几个副本,提升可用性
  grav/grav

这里的grav-service就是集群内部的DNS域名,集群里任何节点访问这个域名,都会自动路由到运行grav的worker节点。

4. 部署统一入口代理(推荐Traefik,比Jwilder Nginx Proxy更适配Swarm)

你之前用的Jwilder Nginx Proxy也能改,但Traefik对Swarm的服务发现支持更原生,故障转移也更省心。下面是Traefik的部署步骤:

(1)先写个Traefik的配置文件traefik.yml

api:
  dashboard: true
  insecure: true # 生产环境建议关了,改用HTTPS加认证

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    swarmMode: true # 必须开这个,支持Swarm模式
    exposedByDefault: false # 只处理我们标注了traefik.enable=true的服务

certificatesResolvers:
  letsencrypt:
    acme:
      email: your-email@example.com # 填你的邮箱,用于Let's Encrypt证书申请
      storage: acme.json
      httpChallenge:
        entryPoint: web

(2)把Traefik部署成Swarm服务

# 先创建acme.json文件,权限要对,不然证书生成失败
touch acme.json && chmod 600 acme.json

# 部署Traefik
docker service create \
  --name traefik \
  --constraint node.role==manager \ # 可以部署在manager,或者专门的入口节点
  --publish 80:80 \
  --publish 443:443 \
  --publish 8080:8080 \ # Traefik的后台管理端口,方便看路由状态
  --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
  --mount type=bind,source=$(pwd)/traefik.yml,target=/etc/traefik/traefik.yml \
  --mount type=bind,source=$(pwd)/acme.json,target=/acme.json \
  traefik:v2.10

(3)给你的grav服务加Traefik标签,自动绑定域名

更新已经部署的grav服务,加上路由规则:

docker service update \
  --label-add traefik.enable=true \
  --label-add traefik.http.routers.grav.rule=Host(`grav.yourdomain.com`) \ # 填你的grav域名
  --label-add traefik.http.routers.grav.entrypoints=web \
  --label-add traefik.http.services.grav.loadbalancer.server.port=80 \ # grav的容器端口
  grav-service

这样用户访问grav.yourdomain.com时,请求会先到Traefik,Traefik通过Swarm的服务发现找到运行grav的worker节点,自动转发过去,完全不用管服务在哪台机器。

5. 最后配置域名A记录

把所有服务的域名(比如grav.yourdomain.com、judge.yourdomain.com等)的A记录都指向你指定的那个Judge Worker Target 1的公网IP就行——如果Traefik部署在其他节点,就指向Traefik所在节点的IP。

故障转移怎么实现?

Swarm本身就自带故障转移能力:如果某个worker节点挂了,Swarm会自动把该节点上的服务实例调度到其他健康的worker节点,Traefik会通过服务发现自动更新路由,用户完全感知不到,连刷新都不用。

替代方案:如果不想用Swarm路由网格

要是你因为某些原因不想用Swarm的路由网格,也可以搞个专门的入口代理服务器:

  • 把所有域名的A记录指向这台新服务器的IP。
  • 在上面部署Nginx或Traefik,配置反向代理到各个服务的内部IP(Swarm服务的虚拟IP或者节点IP)。
  • 配合Docker的服务发现工具(比如Consul),让入口代理自动感知服务的节点变化,实现动态路由。不过这个方案比Swarm路由网格复杂多了,除非你有特殊需求,不然不推荐。

几个注意点

  • 所有集群节点的防火墙要开放Swarm需要的端口:2377/tcp(集群管理)、7946/tcp/udp(节点间通信)、4789/udp(覆盖网络),还有80、443这些服务端口。
  • 用Traefik的话,acme.json的权限必须是600,不然Let's Encrypt没法生成证书。
  • 要是你坚持用Jwilder Nginx Proxy,得把它部署成Swarm服务,然后配置它用Swarm的内部域名(比如grav-service)作为后端,这样它就能自动找到服务所在的节点了。

内容的提问来源于stack exchange,提问作者Dream

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:29:18