DEV Community

mich0w0h
mich0w0h

Posted on • Updated on

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

Top comments (3)

Collapse
 
nansies561 profile image
Ananya Shahi

Thanks for writing this! I’ve been wanting to learn how to use Docker for some time, and this helped

Collapse
 
mich0w0h profile image
mich0w0h

Glad I could be of help! I'm just starting to learn Docker too, so good luck to all of us.

Collapse
 
william20 profile image
Williamsmith

To set up a local DNS service with Docker on Ubuntu, first, install Docker. century link internet service Then, create a Dockerfile defining the DNS service container and a dnsmasq.conf configuration file. Build the Docker image and run the container with port mapping. Configure your system to use the local DNS server. Finally, test DNS resolution. Docker simplifies deployment, making it ideal for local DNS setups on Ubuntu.