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
- Setting up a CoreDNS Server for Local Custom Domain Management on Ubuntu Using Docker - DEV Community
- Setting Up a Recursive DNS Resolver Using Unbound on Docker - DEV Community
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
Networking Overview
Here's the networking overview of this project
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
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"]
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
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
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
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
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
After this, test your internet connectivity to ensure that disabling systemd-resolved
hasn't caused any issues:
$ curl google.com
Running Docker Compose
To start your services, run Docker Compose:
sudo docker compose up -d --build
Testing
Finally, test your setup from another device in your home network:
$ dig @192.168.10.100 www.mich0w0h.house
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
That's it! You've now set up a local DNS service with Docker on Ubuntu 22.04.
References
- DNSがよくわかる教科書 | SBクリエイティブ
- 開発系エンジニアのためのDocker絵とき入門 - 秀和システム あなたの学びをサポート!
- Configuration — Unbound 1.19.3 documentation
- NLnet Labs Documentation - Unbound - unbound-checkconf.8
- NLnet Labs Documentation - Unbound - unbound.conf.5
- Resolver for Home Networks — Unbound 1.19.3 documentation
- Corefile Explained
- Docker+DNS入門 その1:CoreDNSを用いた権威DNSサーバ構築 #Docker - Qiita
- Docker+DNS入門 その2:Unboundを用いたキャッシュDNSサーバ構築 #Docker - Qiita
Top comments (3)
Thanks for writing this! I’ve been wanting to learn how to use Docker for some time, and this helped
Glad I could be of help! I'm just starting to learn Docker too, so good luck to all of us.
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.