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 сервера

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

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