HashiCorp Consul provides a DNS server as query interface to be used by applications for service discovery. Unless otherwise configured the DNS server listens on port 8600.

Using systemd-resolved it’s possible to forward all DNS requests for the consul. to Consul. This can be done as described in the official documentation, by writing the following contents to /etc/systemd/resolved.conf.d/consul.conf since systemd 246 and optionally symlinking the stub-resolve.conf generated by systemd-resolved to /etc/resolve.conf.

[Resolve]
DNS=127.0.0.1:8600
DNSSEC=no
Domains=~consul.
sudo ln -srf /run/systemd/resolve/stub-resolve.conf /etc/resolve.conf

This setup will not suffice for Docker containers using the default bridge interface to resolve DNS requests for Consul. This is because by default these containers inherit the DNS settings of the host, as defined inside /etc/resolv.conf. When /etc/resolv.conf only contains 127.0.0.53 as nameserver Docker assumes systemd-resolved is used and copies the contents of /run/systemd/resolve/resolve.conf into /etc/resolve.conf of the container instead.

One solution to this problem is to use systemd-resolved as a nameserver, by having the DNS stub resolver also listen on the default Docker bridge interface address and configuring this address as DNS server of the Docker container.

By default, systemd-resolved only exposes the DNS stub resolver on the loopback interface at 127.0.0.53, but since systemd 247 it’s possible to listen on additional sockets. This is done by configuring the docker0 bridge interface address as extra stub listener address inside /etc/systemd/resolved.conf.d/docker.conf as follows.

[Resolve]
DNSStubListener=yes
DNSStubListenerExtra=172.17.0.1

The DNS server of a Docker contanier can than be configured using either the --dns command-line flag or globally through the daemon configuration file /etc/docker/daemon.json as follows.

{
  "dns": ["172.17.0.1"]
}