Skip to main content

Getting to know the BIND9 DNS Server with Docker

Shenzhen, China

BIND is open source software that implements the Domain Name System (DNS) protocols for the Internet. It is a reference implementation of those protocols, but it is also production-grade software, suitable for use in high-volume and high-reliability applications. BIND 9 has evolved to be a very flexible, full-featured DNS system. You can download a current version from the ISC website. Or, install our updated ISC packages for Ubuntu, CentOS/Fedora, and the standard Debian package. I want to take a look at the official Docker Image.

Test Run

Download the official Docker Image and test run it with:

docker run \
    --name=bind9 \
    --publish 53:53/udp \
    --publish 53:53/tcp \
    --publish 127.0.0.1:953:953/tcp \
    internetsystemsconsortium/bind9:9.18

The container can be accessed with:

docker exec -ti bind9 /bin/bash

Now run the following command to check whether BIND is running:

named -v
BIND 9.18.0-2+ubuntu20.04.1+isc+1-Ubuntu (Stable Release)

BIND 9 Configuration

All the configuration files of BIND 9 is in /etc/bind and /var/cache/bind directory. The main configuration files are named.conf, named.conf.default-zones, named.conf.local, and named.conf.options:

ls -la /etc/bind

-rw-r--r-- 1 root root 2403 Jan 28 07:53 bind.keys
-rw-r--r-- 1 root root  237 Jan 27 12:16 db.0
-rw-r--r-- 1 root root  271 Jan 27 12:16 db.127
-rw-r--r-- 1 root root  237 Jan 27 12:16 db.255
-rw-r--r-- 1 root root  353 Jan 27 12:16 db.empty
-rw-r--r-- 1 root root  270 Jan 27 12:16 db.local
-rw-r--r-- 1 root bind  463 Jan 27 12:16 named.conf
-rw-r--r-- 1 root bind  498 Jan 27 12:16 named.conf.default-zones
-rw-r--r-- 1 root bind  165 Jan 27 12:16 named.conf.local
-rw-r--r-- 1 root bind  846 Jan 27 12:16 named.conf.options
-rw-r----- 1 bind bind  100 Jan 28 08:25 rndc.key
-rw-r--r-- 1 root root 1317 Jan 27 12:16 zones.rfc1918

The /var/cache/bind directory contains all zone files. A zone file holds information about a certain domain name and its subdomains:

nano /var/cache/bind/hello.example.com

The zone file hello.example.com defines how a domain name is resolved and what IP it is resolved to. $ORIGIN defines a value for the @ symbol. Don’t forget the dot(.) after example.com as it is required for the FQDN (Fully Qualified Domain Name).

If you don’t put a FQDN in BIND zone file, then the value of $ORIGIN will be appended to the name. For example, ns1 is not a FQDN. So ns1 will be ns1.example.com.

$TTL 1d
$ORIGIN example.com.

@ IN  SOA   ns1 root (
      1     ;Serial
      1d    ;Refresh
      1h    ;Retry
      1w    ;Expire
      1h    ;Minimum
  )

@      IN     A       172.17.0.2

@      IN     NS      ns1
ns1    IN     A       172.17.0.2

@       IN    NS      ns2.example.com.
ns2     IN    A       172.17.0.3

@       IN    MX      10    mail
mail    IN    A       172.17.0.4
www     IN    CNAME   example.com.
ftp     IN    CNAME   example.com.

Here, example.com is the domain name and hello.example.com is the zone file for the domain name example.com.

Now I have to edit /etc/bind/named.conf.local to tell bind to load the data file hello.example.com for the zone example.com:

172.17.0.2 is the IP of the bind9 docker container:

ip a

13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
  • SOA Record: nameserver authoritative for a zone example.com is ns1.example.com and admin.example.com is an email address of a person responsible for this DNS zone.
  • NS Records: two nameservers for the example.com zone are ns[1,2].example.com
  • MX ( Mail Exchange): example.com mail exachange record. Number 10 means a preference for discarding a records A – A simply means address or in other words in example.com’s zone a ns1 would have an A ( address ) 192.168.0.10.
  • CNAME Record ( Canonical Name record ): restart the query using the canonical name instead of the original name

Run the following command to check the configuration:

named-checkconf

With this named-checkconf command no news is good news. If no output has been produced, your config files are OK. To check the DNS zone files we can use named-checkzone command:

named-checkzone example.com /var/cache/bind/hello.example.com
zone example.com/IN: loaded serial 1
OK
nano /etc/bind/named.conf.local
zone "example.com" {
        type master;
        file "hello.example.com";
};

To restart Bind I now have to stop/start the container and reconnect. I can now use my DNS service to resolve the example.com domain using dig (apt install dnsutils). @172.17.0.2 is used to tell dig to use the nameserver 172.17.0.2:

dig @172.17.0.2 hello.example.com any

; <<>> DiG 9.18.0-2+ubuntu20.04.1+isc+1-Ubuntu <<>> @172.17.0.2 example.com any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9397
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 4

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: f8ea8c503c5bc7d501000000622096e24e69af6e56bf8a80 (good)
;; QUESTION SECTION:
;example.com.                   IN      ANY

;; ANSWER SECTION:
example.com.            86400   IN      SOA     ns1.example.com. root.example.com. 1 86400 600 259200 86400
example.com.            86400   IN      A       172.17.0.2
example.com.            86400   IN      NS      ns1.example.com.
example.com.            86400   IN      NS      ns2.example.com.
example.com.            86400   IN      MX      10 mail.example.com.

;; ADDITIONAL SECTION:
ns1.example.com.        86400   IN      A       172.17.0.2
ns2.example.com.        86400   IN      A       172.17.0.3
mail.example.com.       86400   IN      A       172.17.0.2

;; Query time: 0 msec
;; SERVER: 172.17.0.2#53(172.17.0.2) (TCP)
;; WHEN: Thu Mar 03 10:22:26 UTC 2022
;; MSG SIZE  rcvd: 230

I can use the server to resolve the *.example.com domains using my own DNS server:

dig @172.17.0.2 www.example.com any +noall +answer
www.example.com.        86400   IN      CNAME   example.com.

dig @172.17.0.2 ftp.example.com any +noall +answer
ftp.example.com.        86400   IN      CNAME   example.com.

dig @172.17.0.2 mail.example.com any +noall +answer
mail.example.com.       86400   IN      A       172.17.0.4

dig @172.17.0.2 ns1.example.com any +noall +answer
ns1.example.com.        86400   IN      A       172.17.0.2

dig @172.17.0.2 ns2.example.com any +noall +answer
ns2.example.com.        86400   IN      A       172.17.0.3