Docker — это контейнерная платформа, которая приобрела популярность в последние годы. Она широко используется для ускорения процесса разработки и развёртывания, имитируя локальную производственную среду.

The Domain Name System (DNS) — это сервис, который преобразует доменные имена в IP-адреса. В этой статье мы вкратце рассмотрим, как запустить DNS-сервер в контейнере Docker.
Резолвинг имен (The name resolution) в Linux описан в файле /etc/nsswitch.conf. По умолчанию в нем есть запись с files dns, что означает, что сначала будет проверяться файл /etc/hosts, а затем DNS-сервер.
Для DNS-серверов на базе Docker можно рассмотреть следующие варианты:
- BIND9: Очень гибкий и мощный, подходит для сложных настроек DNS.
- dnsmasq: Простой и понятный, идеально подходит для небольших и средних сетей, а также для локальной разработки.
- CoreDNS: современный и расширяемый, часто используется с Kubernetes для обнаружения сервисов.
Установка DNS-сервера BIND9 в Docker
Для начала давайте настроим наш DNS-сервер. Мы будем использовать BIND 9 в качестве DNS-сервера, предоставляемого бесплатно Консорциумом Интернета. Он доступен в виде образа Docker на DockerHub.
Настройка сети Docker
Давайте создадим сеть docker.
docker network create --name dockerhosting --subnet 172.24.0.0/16Для нашей сети мы используем /16 подсеть.
Настройка DNS-сервера
Сначала создайте каталог для хранения конфигурации BIND 9 и новый файл с именем named.conf.options для начала настройки сервера BIND 9.
mkdir -p /opt/bind9/configuration
vim /opt/bind9/configuration/named.conf.options
2. Скопируйте приведенное ниже содержимое в файл.
options {
directory "/var/cache/bind";
recursion yes;
listen-on { any; };
forwarders {
8.8.8.8;
8.8.4.4;
};};Данная настройка гарантирует, что BIND прослушивает все интерфейсы для DNS-запросов, и любые запросы доменных имён, которые не могут быть выполнены сервером BIND (за пределами файла доменной зоны), будут отправлены переадресаторам для резолвинга. Например, google.com, docker.com, и т. д.
3. Далее мы определим зону под названием dockerhosting.lan, которая указывает на /etc/bind/zones/db. файл доменной зоны.
Давайте создадим файл, который будет определять нашу зону.
vim /opt/bind9/configuration/named.conf.local
Скопируйте приведенное ниже содержимое в файл.
zone "dockerhosting.lan" {
type master;
file "/etc/bind/zones/db.dockerhosting.lan";
};Файл зоны под названием db.dockerhosting.lan содержит доменные имена, которыми будет управлять наш DNS-сервер BIND. Мы назначим каждому доменному имени IP-адрес. Указывайте IP-адрес контейнера во время его работы, чтобы доменные имена могли указывать на соответствующие IP-адреса.
Теперь мы добавим несколько доменных имён в наш файл доменной зоны. Создайте файл доменной зоны dockerhosting:
vim /opt/bind9/configuration/db.dockerhosting.lan
4. Скопируйте приведенное ниже содержимое в файл доменной зоны.
$TTL 1d ;
default expiration time (in seconds) of all RRs without their own
TTL value@ IN SOA
ns1.dockerhosting.lan. root.dockerhosting.lan.
( 3 ;
Serial 1d;
Refresh 1h;
Retry 1w;
Expire 1h);
Negative Cache TTL;
name servers - NS records IN NS
ns1.dockerhosting.lan.;
name servers - A records
ns1.dockerhosting.lan. IN A 172.24.0.2
nginx.dockerhosting.lan. IN A 172.24.0.3
httpd.dockerhosting.lan. IN A 172.24.0.4В приведенном выше примере добавлен один сервер имен ns1.dockerhosting.lan и два хоста nginx.dockerhosting.lan и httpd.dockerhosting.lan.
Создание Docker образа
Мы будем использовать официальный образ Docker BIND 9 в качестве базового образа и установим на него некоторые дополнительные зависимости. Наконец, мы скопируем наши файлы конфигурации непосредственно в образ Docker.
- Создайте
Dockerfile.
vim /opt/bind9/Dockerfile.bind9
2. Скопируйте приведенное ниже содержимое в Dockerfile.
#Base Bind9 Image
FROM internetsystemsconsortium/bind9:9.18
#Install required tools and dependencies
RUN apt update && apt install -y \
bind9-doc \
dnsutils \
geoip-bin \
mariadb-server \
net-tools
#Copy configuration files
COPY configuration/named.conf.options /etc/bind/
COPY configuration/named.conf.local /etc/bind/
COPY configuration/db.dockerhosting.lan /etc/bind/zones/
# Expose Ports
EXPOSE 53/tcp
EXPOSE 53/udp
EXPOSE 953/tcp
# Start the Name Service
CMD ["/usr/sbin/named", "-g", "-c", "/etc/bind/named.conf", "-u", "bind"]Содержимое файла Dockerfile образа BIND 9
3. Создайте и пометьте образ BIND с помощью приведенной ниже команды.
docker build -t dns-master . -f Dockerfile.bind9
Запуск контейнер Docker с BIND9
После успешного создания нашего контейнера мы запустим его в нашей сети dockerhosting с указанным IP-адресом.
docker run -d -p 53:53/tcp -p 53:53/udp -p 127.0.0.1:953:953/tcp --rm --name=dns-master --net=dockerhosting --ip=172.24.0.2 internetsystemsconsortium/bind9:9.18
Проверка конфигурации сервера:
docker exec -ti dns-master /bin/bash
named-check
confnamed-checkzone dockerhosting.lan /etc/bind/zones/db.dockerhosting.lan
zone dockerhosting.lan/IN: loaded serial 3
OKДемонстрационная настройка
Теперь мы можем использовать ранее запущенный контейнер DNS в качестве нашего DNS-сервера. Любые службы, для которых нам нужно сопоставление доменов, можно просто перестроить с использованием необходимых доменных имён.
docker run -d --rm --name=nginx --net=dockerhosting --ip=172.24.0.3 --dns=172.24.0.2 nginx:latest
sudo docker run -d --rm --name=httpd --net=dockerhosting --ip=172.24.0.4 --dns=172.24.0.2 httpd:latest
Как вы можете видеть, все контейнеры теперь работают в одной сети.
docker network inspect dockerhosting
[{
"Name": "dockerhosting",
"IPAM":
{
"Config":
[{
"Subnet": "172.24.0.0/16"
}
]},
"Containers":
{ "12hbd7e3b3a033fd643d36fff787c123adlkda485dc5f3d4468212568b8ff4498e776993":
{
"Name": "dns-master",
"IPv4Address": "172.24.0.2/16"
}, "14deb32e260d15ff8543571f2c5fd1d99eeb9ba97042a97c34d9b933525ca8aa":
{
"Name": "service2",
"IPv4Address": "172.24.0.4/16" }, "cb6840cfd76d360dfe4cefc96486a11cd4b73f405d114c2830fd792c4883dd8b":
{
"Name": "service1",
"IPv4Address": "172.24.0.3/16"
}},
}]
Вывод Docker network inspect dockerhosting
Мы можем проверить, правильно ли работает сопоставление доменного имени, выполнив команду nslookup . С помощью команды nslookup мы сможем определить IP-адрес доменного имени и DNS-сервер, предоставляющий нам эти данные.
docker exec -it nginx nslookup httpd.dockerhosting.lan
Server: 127.0.0.11
Address: 127.0.0.11:53
Name: httpd.dockerhosting.lan
Address: 172.24.0.4
Использование nslookup для проверки IP-адреса службы httpd
Чтобы проверить, работает ли переадресация, мы можем выполнить nslookup для домена, например google.com, который находится за пределами нашей внутренней зоны DNS. Если наш запрос будет успешным, мы сможем увидеть IP-адрес домена Google.
docker exec -it nginx nslookup google.com Server: 127.0.0.11
Address: 127.0.0.11:53
Non-authoritative answer:
Name: google.com
Address: 142.250.182.110
Использование nslookup для проверки IP-адреса службы nginx
Как видите, в полученном ответе есть строка Non-authorative. Это означает, что DNS-сервер, предоставивший нам сведения о домене google.com, не находится под нашим контролем. Мы получили такой результат, потому что добавили переадресацию в нашу конфигурацию BIND. Доменное имя, сведения о котором мы запросили, не было доступно в файле локальной зоны, поэтому сервер BIND не смог предоставить его сведения.
Так же BIND9 позволяет управлять DNS записями, а конкретно добавлять и удалять их с помощью API, на GitHub, есть готовая библиотека.
Запуск Webmin + Bind DNS server в Docker
В данном примере упростим задачу управления DNS записями и установим Webmin GUI панель управления сервером в Docker. Для этого будем использовать готовый образ Docker sameersbn/bind:latest.

Создадим каталог для тома
mkdir -p /home/docker_v/bind/data
Создадим и запустим контейнер с Webmin + Bind DNS server
docker run --name bind -d --restart=always \
--publish 53:53/tcp \
--publish 53:53/udp \
--publish 10000:10000/tcp \
-v /etc/localtime:/etc/localtime \
-v /home/docker_v/bind/data/:/data \
--env='WEBMIN_INIT_SSL_ENABLED=false' \
--env='ROOT_PASSWORD=GuoLian@2021' \
sameersbn/bind:latest

Проверим запущенный контейнер:

Перейдем по адресу сервера http://IPсервера:10000

Панель позволяет в настройках установить русский язык интерфейса, но я предпочитаю оставить английский.

Перейдем к настройкам DNS сервера

Создадим главный домен.

Используемые материалы: