No final, consegui fazê-lo funcionar. Eu estava fazendo algumas coisas erradas.
O maior erro foi que eu não havia mapeado a porta 53 no host para a porta 53 / udp dentro do contêiner do cônsul. O mapeamento completo de portas agora é assim:
services:
consul:
image: progrium/consul
hostname: "{{ ansible_hostname }}"
ports:
# Explanation of ports needed: http://stackoverflow.com/a/30692226/1514089
- "8300:8300" # This is used by servers to handle incoming requests from other agents
- "8301:8301/tcp" # This is used to handle gossip in the LAN. Required by all agents
- "8301:8301/udp" # This is used to handle gossip in the LAN. Required by all agents
- "8302:8302/tcp" # This is used by servers to gossip over the WAN to other servers
- "8302:8302/udp" # This is used by servers to gossip over the WAN to other servers
- "8400:8400" # This is used by all agents to handle RPC from the CLI
- "8500:8500" # This is used by clients to talk to the HTTP API
- "8600:8600" # Used to resolve DNS queries
- "172.17.0.1:53:53/udp"
restart: always
command: "{{ consul_command }}"
Aqui estamos vinculando à porta 53 na interface docker0. No entanto, aprendi que o IP da ponte docker0 pode mudar, então codifiquei um pouco e disse ao docker para sempre usar esse IP para a ponte docker0 especificando --bip=172.17.0.1
nas opções do daemon do docker. O próximo passo foi definir o dns padrão do daemon do docker para o mesmo IP. Meu daemon do Docker completo opta assim:
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon \
-H tcp://0.0.0.0:2375 \
-H unix:///var/run/docker.sock \
--bip=172.17.0.1/16 \
--dns=172.17.0.1 \
--dns-search=service.consul \
--storage-driver=overlay \
--cluster-store=consul://127.0.0.1:8500
Agora posso fazer isso:
$ sudo docker -H :4000 run -it joffotron/docker-net-tools
/ # dig +short consul.service.consul
10.0.0.93
10.0.0.95
10.0.0.94
Ótimo!