在Docker Swarm环境中使用Consul实现服务发现的技术咨询
解决方案
一、全局配置Docker Swarm使用Consul DNS
要让所有Swarm容器默认优先使用Consul DNS,同时保留AD DNS解析传统服务的能力,需修改每个Swarm节点的Docker守护进程配置:
- 编辑
/etc/docker/daemon.json,添加以下配置:
{ "dns": ["127.0.0.1", "<AD_DNS_SERVER_IP>"], "dns-search": ["consul", "<你的AD域名>"] }
- 把Consul DNS(部署在本地主机,用
127.0.0.1)放在首位,确保容器优先查询Consul;AD DNS作为后备,处理非容器服务的解析请求 dns-search自动补全域名后缀,减少服务名输入的冗余
- 重启Docker服务生效:
systemctl restart docker
- 验证配置:
启动测试容器检查解析能力:
# 测试Consul服务解析 docker run --rm alpine nslookup <已注册到Consul的服务名> # 测试AD主机解析 docker run --rm alpine nslookup <AD内的主机名>
二、Swarm服务自动注册到Consul(无需修改应用代码)
不需要强制使用sidecar代理,以下两种方案均可实现无代码侵入的服务自动注册:
方案1:Consul原生Docker服务发现
利用Consul对Docker API的支持,自动监听并注册指定的Swarm服务:
- 在每个Consul节点创建配置文件
/etc/consul.d/docker-config.hcl:
catalog { docker { enabled = true endpoint = "unix:///var/run/docker.sock" expose_by_default = false service_label = "consul.register" } }
enabled = true:开启Docker服务发现功能expose_by_default = false:仅注册带有指定标签的服务,避免无关容器被注册service_label = "consul.register":标记需要注册到Consul的Swarm服务
- 重启Consul服务:
systemctl restart consul
- 部署Swarm服务时添加注册标签:
docker service create \ --name your-app-service \ --label consul.register=true \ --label consul.service.name=your-app \ --label consul.service.port=8080 \ your-private-registry/your-app-image
- 可通过自定义标签指定Consul中显示的服务名、端口,Consul会自动同步Swarm服务的虚拟IP和端口信息
方案2:Consul Template(适配复杂场景)
如果需要自定义健康检查、注册规则等,可使用Consul Template监听Swarm服务变化,自动生成Consul注册配置:
- 在每个Swarm节点安装Consul Template
- 创建模板文件
/etc/consul-templates/swarm-services.ctmpl:
{{ range services }} service { name = "{{ .Name }}" id = "{{ .ID }}" address = "{{ .Endpoint.VirtualIPs.0.Addr }}" port = {{ .Endpoint.Ports.0.PublishedPort }} check { http = "http://{{ .Endpoint.VirtualIPs.0.Addr }}:{{ .Endpoint.Ports.0.PublishedPort }}/health" interval = "10s" } } {{ end }}
- 启动Consul Template,自动同步配置:
consul-template -consul-addr=127.0.0.1:8500 -template="/etc/consul-templates/swarm-services.ctmpl:/etc/consul.d/swarm-services.json" -reload-signal=SIGHUP
Swarm服务更新时,Consul会自动同步注册信息,同时支持自定义健康检查规则。
三、配置Consul转发DNS请求到AD
让Consul将非.consul后缀的域名请求转发到AD DNS,修改Consul的DNS配置:
- 编辑
/etc/consul.d/dns-config.hcl:
dns { enable_truncate = true only_passing = true forward { policy = "only" domains = ["<你的AD域名>"] servers = ["<AD_DNS_SERVER_IP>:53"] } }
policy = "only":仅对指定域名的请求进行转发domains:填写你的AD域名(如corp.example.com)servers:AD DNS服务器的IP和端口
- 重启Consul服务生效:
systemctl restart consul
四、验证流程
- 部署带注册标签的测试服务,在Consul UI确认服务已注册
- 在容器内用
nslookup your-app.service.consul验证服务解析 - 在容器内用
nslookup ad-host.<你的AD域名>验证AD主机解析 - 测试容器服务与传统非Docker服务的互通性
内容的提问来源于stack exchange,提问作者Farhan Sabbir Siddique
相关产品推荐
相关产品推荐

