Setting Up a Local DNS Service with Docker on Ubuntu 22.04

mich0w0h

mich0w0h

Posted on March 24, 2024

Setting Up a Local DNS Service with Docker on Ubuntu 22.04

Recently, I've been working on setting up a local DNS service using Docker on Ubuntu 22.04. I've documented my process and thought it might be helpful to share it with others. Here's how I did it.

Note: This article is the final form of these articles

Repository

You can find the complete code in my GitHub repository.

Project Structure

I've organized my project into a directory structure as follows:



local-dns
├── compose.yml
├── .git
├── .dockerignore
├── recursive
│   ├── Dockerfile
│   └── unbound.conf
└── authoritative
    ├── Corefile
    └── zone
        └── db.mich0w0h.house


Enter fullscreen mode Exit fullscreen mode

Networking Overview

Here's the networking overview of this project

networking overview

I assigned an IP address 192.168.10.100 to the host Ubuntu server. If you want to know how to assign a static address to a Ubuntu server, see this post: Configure Static IP in Ubuntu 22.04 - DEV Community

Docker Configuration

I've created a .dockerignore file to exclude unnecessary files from the Docker build context:



**/.git


Enter fullscreen mode Exit fullscreen mode

I've also created a Dockerfile for the resolver service:



FROM ubuntu:22.04

RUN apt-get update && apt-get install -y unbound && rm -rf /var/lib/apt/lists/*

COPY unbound.conf /etc/unbound/unbound.conf

CMD ["/usr/sbin/unbound", "-d", "-c", "/etc/unbound/unbound.conf"]


Enter fullscreen mode Exit fullscreen mode

This Dockerfile uses the Ubuntu 22.04 image, installs Unbound (a DNS resolver), and copies the Unbound configuration file into the container.

The Unbound configuration file (unbound.conf) is as follows:



server:
    interface: 0.0.0.0
    access-control: 0.0.0.0/0 refuse
    access-control: 192.168.1.0/24 allow_snoop
remote-control:
    control-enable: no
stub-zone:
    name: "mich0w0h.house"
    stub-addr: 192.168.1.102
forward-zone:
    name: "."
    forward-addr: 8.8.8.8 # google DNS
    # forward-addr: 192.168.10.1. # ISP provided DNS


Enter fullscreen mode Exit fullscreen mode

Docker Compose

I've used Docker Compose to manage my services. Here's my compose.yml file:



services:
  resolver:
    build: ./resolver
    ports:
      - "53:53/udp"
    networks:
      local-dns:
        ipv4_address: 192.168.1.101
  authoritative:
    image: coredns/coredns
    volumes:
      - "./authoritative:/etc/coredns"
    networks:
      local-dns:
        ipv4_address: 192.168.1.102
    command: -conf /etc/coredns/Corefile
networks:
  local-dns:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24


Enter fullscreen mode Exit fullscreen mode

The service is available from port 53 of the host machine. However, it's necessary to assign IP addresses since unbound.conf only accepts IP addresses to specify the nameserver, and specifying the service name of docker compose doesn't work.

If you've already created a network using the command sudo docker network create --subnet=192.168.1.0/24 local-dns, you can modify the networks section like this:



networks:
  local-dns:
    external: true


Enter fullscreen mode Exit fullscreen mode

Enabling Port Mapping

By default, systemd-resolved is running on port 53 in Ubuntu 22.04. To use port 53 for your Docker container, you'll need to stop and disable systemd-resolved, or change its port. Here's how I did it:



sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved


Enter fullscreen mode Exit fullscreen mode

Next, remove the symlink /etc/resolv.conf and create a new one:



sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf


Enter fullscreen mode Exit fullscreen mode

After this, test your internet connectivity to ensure that disabling systemd-resolved hasn't caused any issues:



$ curl google.com


Enter fullscreen mode Exit fullscreen mode

Running Docker Compose

To start your services, run Docker Compose:



sudo docker compose up -d --build


Enter fullscreen mode Exit fullscreen mode

Testing

Finally, test your setup from another device in your home network:



$ dig @192.168.10.100 www.mich0w0h.house


Enter fullscreen mode Exit fullscreen mode

If everything is set up correctly, you should see a response similar to the following:



; <<>> DiG 9.10.6 <<>> @192.168.10.100 www.mich0w0h.house
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49784
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.mich0w0h.house.        IN  A

;; ANSWER SECTION:
www.mich0w0h.house. 86400   IN  A   192.168.1.103

;; Query time: 49 msec
;; SERVER: 192.168.10.100#53(192.168.10.100)
;; WHEN: Sun Mar 24 05:19:39 JST 2024
;; MSG SIZE  rcvd: 63


Enter fullscreen mode Exit fullscreen mode

That's it! You've now set up a local DNS service with Docker on Ubuntu 22.04.

References

💖 💪 🙅 🚩
mich0w0h
mich0w0h

Posted on March 24, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related