In addition to the standard format of expressing IP addresses with numbers and dots, symbolic names can also refer to a host. Symbolic names are preferred as they are easier to remember. A service like Domain Name System (DNS) converts domain names into IP addresses using a database that maintains the mapping between host names (or domain names) and host numbers (or IP addresses).
In the Linux environment, name resolution is described in the
/etc/nsswitch.conf file, where the default entry for hosts includes files and DNS. It means that the system will check
/etc/hosts file before requesting the DNS server for name resolution.
Docker provides a DNS system that can route service requests using their service names. However, a Fully Qualified Domain Name (FQDN) like
nginx.service.com cannot be used within Docker. Instead, we'll need to use the container's name to connect between different services.
Let's get into it!
To follow along with this blog, you'll need the following:
- Linux System with Docker Pre-Installed
First, let's set up our DNS Server. We will use BIND 9 for the DNS Server, provided free by the Internet Consortium. It's available as a Docker image at DockerHub.
Setup Docker Network
Let's create a docker network.
docker network create --name lab-net --subnet 172.24.0.0/16
For our network, we're using a
DNS Server Configuration
- First, setup a directory to store our BIND 9 configuration and create a new file called
named.conf.optionsto start configuring the BIND 9 server.
mkdir -p /opt/bind9/configuration
2. Copy the contents below into the file.
This ensures that BIND listens on all interfaces for DNS requests, and any domain name requests that cannot be fulfilled by the BIND server (ones outside of the zone file) will be sent to the forwarders for resolution. For example,
3. Next, we'll define a Zone called
lab-net.lan, which points to
/etc/bind/zones/db. Zone File.
Let's create the file that will define our zone.
Copy the contents below into the file.
The Zone File called
db.lab-net.lan contains the domain names that will be managed by our BIND DNS server. We will assign each domain name an IP address. Mention the container's IP address during container runtime so the domain names can point to the corresponding IP addresses.
We'll now add a few domain names to our zone file. Create the
lab-net zone file.
4. Copy the contents below into the zone file.
In the above example, one name server
ns1.lab-net.lan, and two hosts
httpd.lab-net.lan have been added.
Build the Docker Image
We'll use the official Docker Image of BIND 9 as a base image and install some additional dependencies into it. Finally, we'll copy our configuration files directly into the Docker image.
- Create the
2. Copy the contents below into the
3. Build and tag the BIND image using the command below.
docker build -t dns-master . -f Dockerfile.bind9
Run the Docker Container
Once our container has been successfully built, we will now run it in our
lab-net network with an explicitly mentioned IP address.
docker run -d -p 53:53/tcp -p 53:53/udp -p 127.0.0.1:953:953/tcp --rm --name=dns-master --net=lab-net --ip=172.24.0.2 internetsystemsconsortium/bind9:9.18
Verifying server configuration:
We can now use the previously started DNS container as our DNS server. Any services we need domain mapping for can simply be rebuilt with the required domain names.
docker run -d --rm --name=nginx --net=lab-net --ip=172.24.0.3 --dns=172.24.0.2 nginx:latest
sudo docker run -d --rm --name=httpd --net=lab-net --ip=172.24.0.4 --dns=172.24.0.2 httpd:latest
As you can see, all containers now run on the same network.
docker network inspect lab-net
We can test whether our domain name mapping functions properly by executing an
nslookup command. Using the
nslookup command, we will be able to determine the IP address of a domain name and the DNS server supplying the details to us.
To check if the forwarder is working, we can perform
nslookup on a domain like
google.com, which exists outside of our internal DNS zone. If our request is successful, we should be able to see the IP address of Google's domain.
As you can see, the reply that came back has the string
Non-authorative. This means the DNS server that supplied us with domain details
google.com is not under our control. We got this outcome because we added forwarders in our BIND configuration. The domain name we requested detail for was not available in the local zone file, so its details could not be supplied by the BIND server.
This way, we can set up a local DNS server in Docker.
The benefits of setting up a local DNS server are endless. It helps a lot when you don't have access to domain names and want to test different technologies that rely somehow on a domain name.
Please comment below if you have any queries. I try to update my articles regularly to maintain legibility!