Using a private DNS server improves the security, privacy, and performance of your network. In this post, you will learn how to configure a private DNS server in Docker.
Latest posts by Surender Kumar (see all)

I will use a Bind9 docker image maintained by Canonical. Please note that this post does not cover the basics of DNS or security best practices.

Prerequisites

For this guide, I will use Docker running in an Ubuntu 22.04 VM.

I also recommend that you read my previous article, MacVLAN network driver: Assign MAC address to Docker containers.

Since we will be using MacVLAN, make sure you enable interface promiscuity with the following commands:

sudo ip -detail -color link show enp0s3
sudo ip link set dev enp0s3 promisc on
Enable interface promiscuity in Linux

Enable interface promiscuity in Linux

This command is needed to enable communication between the Docker container and your internal network devices.

Create a macvlan network

First, we need a new macvlan network to connect our private DNS server container. You could use a bridge network and publish DNS ports (TCP/UDP 53) to the Docker host, but I like working with a macvlan network for various reasons that are discussed in my previous post. To create a macvlan network, run the following command:

sudo docker network create \
--driver macvlan \
--subnet 192.168.0.0/24 \
--gateway 192.168.0.1 \
--ip-range 192.168.0.80/28 \
--aux-address 'host=192.168.0.80' \
--opt parent=enp0s3 \
dns_net
Creating a macvlan network for the DNS server

Creating a macvlan network for the DNS server

I discussed this command in my previous post, so I will not discuss it in detail. In a nutshell, this command creates a new Docker network using a macvlan driver.

Prepare DNS configuration files

Since our DNS server will be running in a Docker container, the DNS (bind) configuration files will reset every time the container is restarted. To have a persistent and consistent configuration, we will store the configuration files in a directory on the Docker host and then mount the directory to the container.

Overview of DNS configuration files on the Docker host

Overview of DNS configuration files on the Docker host

As you can see in the screenshot, I created a dns directory with a config subdirectory to store the configuration file and zone files. Use a text editor to create the main configuration file, named.conf, under the ~/dns/config/ directory, and paste the following lines of code:

acl bogus_networks {
  0.0.0.0/8; 224.0.0.0/3; 10.0.0.0/8; 172.16.0.0/12;
};

acl private_networks {
  192.168.0.0/24;
};

options {
  forwarders {
    8.8.8.8;
    1.1.1.1;
  };
  allow-query { private_networks; };
  allow-recursion { private_networks; };
  blackhole { bogus_networks; };
};

zone "techtuts.local" IN {
  type master;
  file "/etc/bind/techtuts.local.zone";
  allow-query { any; };
};
Create the main configuration file of the DNS server

Create the main configuration file of the DNS server

At the top, we defined two ACLs with network subnets to block and allow. The allow-query and allow-recursion options allow requests from our private networks, whereas the blackhole option completely rejects requests from unwanted networks.

At the end, we defined the zone information for our domain with a path to the actual zone file (/etc/bind/techtuts.local.zone). Of course, you can change these values and extend them as required.

Similarly, create a zone file named techtuts.local.zone under the ~/dns/config/ directory with the following information:

;
; BIND data file for techtuts.local zone
;

$TTL    604800
$ORIGIN techtuts.local.

@       IN      SOA     ns.techtuts.local. root.techtuts.local. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;name server records
        IN      NS      ns.techtuts.local.

;name server host records
ns      IN      A       192.168.0.40

;host records for other devices
srv1            IN      A       192.168.0.40
web101          IN      A       192.168.0.82
web102          IN      A       192.168.0.83
db101           IN      A       192.168.0.92
db102           IN      A       192.168.0.93

Create a DNS zone file for a domain

Create a DNS zone file for a domain

I have added several records to this zone file. Of course, you can add other records, such as CNAME, MX, and TXT.

Once you have both files ready, you are all set to launch a Docker container using a Bind9 image.

Launch a DNS server in a Docker container

To launch a Docker container with a Bind9 DNS server, use the following command:

sudo docker run --detach \
--network dns_net \
--ip 192.168.0.41 \
--name ns1 \
--env TZ=Asia/Kolkata \
--env BIND9_USER=root \
--volume /home/surender/dns/config:/etc/bind \
--restart=always \
ubuntu/bind9
Launch a Bind DNS server in a Docker container

Launch a Bind DNS server in a Docker container

This command pulls the Bind9 Docker image on the fly and launches a container with the specified options. The restart=always option is important, as it will automatically restart your Docker container when your Docker host is restarted. Once the Docker container is launched, you can view the logs with the following command:

sudo docker logs -f ns1
View the logs of the DNS server container

View the logs of the DNS server container

If you have any error in your configuration or zone file, you will be able to view that error with this command. In my case, the zone was loaded successfully.

Verify DNS server functionality

Our DNS server is now ready to perform the name resolutions. To test whether the DNS server is working as expected, use the host or nslookup commands, as shown below:

host srv1.techtuts.local 192.168.0.41
host 4sysops.com 192.168.0.41
Testing DNS functionality using the host command

Testing DNS functionality using the host command

Similarly, we can use nslookup to query the IP address for any internal network device using our new DNS server running in Docker.

Subscribe to 4sysops newsletter!

nslookup web101.techtuts.local 192.168.0.41
nslookup db101.techtuts.local 192.168.0.41
nslookup techtutsonline.com 192.168.0.41
Testing DNS functionality using the nslookup command

Testing DNS functionality using the nslookup command

Once you verify that the DNS server is working as expected, you can configure your client devices to use this DNS server. But please remember, as I said earlier, this post covers a really simple DNS server setup; it doesn't use the best practices for running a production-ready DNS server. In a production environment, you might also want to create a secondary DNS server for failover if your primary DNS server is unavailable to avoid service disruption. For security considerations, I recommend checking out the official Bind9 documentation.

avataravatar
0 Comments

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account