How to Set Up a Local DNS Server Using Docker: A Practical Guide for Developers

DNS Server in Docker

Overview

Setting up a local DNS server may sound like something only large-scale IT teams need. But in reality, having your own DNS server locally can speed up development, enable custom domain routing, and improve testing environmentsβ€”especially in microservice setups.

In this tutorial, you’ll learn how to deploy a lightweight DNS server locally using Dockerβ€”without getting tangled in complex configurations.

Why Set Up a Local DNS Server?

Before diving into containers and configs, let’s understand the benefits of running a DNS server locally:

  • πŸ” Custom domain routing (e.g., myapp.local β†’ 127.0.0.1)
  • πŸ§ͺ Isolated testing environments without altering /etc/hosts
  • ⚑ Faster DNS resolution during development
  • 🧩 Service discovery in dev environments

And the best part? With Docker, it’s fully portable, clean, and easy to reset.

Tools We’ll Use

We’ll use the following:

  • Docker (container platform)
  • Bind9 DNS server (in a container)
  • Optional: dig or nslookup for testing DNS queries

Folder Structure

Start by creating a working directory:

$ mkdir docker-local-dns && cd docker-local-dns

Inside, create:

.
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ named.conf
β”œβ”€β”€ db.localhost
└── named.conf.options

🐳 Step 1: Create the Dockerfile

Let’s create a Dockerfile that sets up a Bind9 DNS server:

FROM ubuntu:22.04

RUN apt-get update && \
apt-get install -y bind9 dnsutils && \
mkdir -p /etc/bind/zones

COPY named.conf /etc/bind/named.conf
COPY named.conf.options /etc/bind/named.conf.options
COPY db.localhost /etc/bind/zones/db.localhost

EXPOSE 53/udp
EXPOSE 53/tcp

CMD ["named", "-f", "-u", "bind"]

βš™οΈ Step 2: Configuration Files

named.conf

include "/etc/bind/named.conf.options";

zone "mydomain.local" {
type master;
file "/etc/bind/zones/db.localhost";
};

named.conf.options

options {
directory "/var/cache/bind";

listen-on port 53 { any; };
allow-query { any; };
recursion yes;

forwarders {
8.8.8.8;
1.1.1.1;
};

dnssec-validation no;
};

db.localhost

$TTL    604800
@ IN SOA ns.mydomain.local. admin.mydomain.local. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.mydomain.local.
ns IN A 127.0.0.1
app IN A 127.0.0.1

This sets app.mydomain.local and ns.mydomain.local to resolve to 127.0.0.1.

🧱 Step 3: Build and Run the Docker Container

Now let’s build and run the container:

docker build -t local-dns .
docker run -d --name dns-server \
-p 53:53/udp -p 53:53/tcp \
local-dns

πŸ§ͺ Step 4: Test Your DNS Server

You can now test it using dig:

dig @127.0.0.1 app.mydomain.local

Expected result:

;; ANSWER SECTION:
app.mydomain.local. 604800 IN A 127.0.0.1

If you’re using Linux, you can temporarily set your system to use this DNS:

$ sudo systemd-resolve --set-dns=127.0.0.1 --interface=lo

Or for macOS, go to System Settings β†’ Network β†’ DNS, and add 127.0.0.1.

🎯 Bonus: Add More Records

Want to add more custom domains?

Just edit db.localhost like this:

backend IN A 127.0.0.1
frontend IN A 127.0.0.1

Then restart your container:

$ docker restart dns-server

🧼 Clean Up

To remove everything:

$ docker rm -f dns-server
$ docker rmi local-dns

πŸ” Security Note

This setup is for local/dev use only. Do not expose it to public networks without proper hardening (ACLs, logging, access control).

πŸ“š Conclusion

Using Docker to set up a local DNS server is a powerful and flexible way to manage domain names in your local development environment. It’s faster than editing /etc/hosts, more scalable, and great for working with microservices or container-based systems. If you’re looking to supercharge your dev workflowβ€”this is one of the best hidden gems to try.

For managing reverse proxy easily with a web interface, you can follow our complete guide to Nginx Proxy Manager, which explains installation, configuration, and best practices.

(Visited 1,734 times, 3 visits today)

You may also like