Quando si sviluppano sistemi distribuiti, più applicazioni possono eseguire chiamate per comunicare tra loro. Un esempio molto frequente sono le chiamate tramite API RESTful.
Nella maggior parte dei casi queste chiamate usano localhost
come nome di dominio, poiché l’host è la propria macchina locale.
La risoluzione dei nomi negli ambienti Linux è descritta nel file /etc/nsswitch.conf
. Per impostazione predefinita, ha una voce con file dns, il che significa che controllerà prima il file /etc/hosts
, quindi il server DNS.
Il Domain Name System (DNS) è un servizio che traduce i nomi di dominio in indirizzi IP, e in questo articolo ci sarà una breve panoramica su come eseguire un server DNS in un container Docker.
Docker network
Il primo passo è quello di creare una rete Docker che utilizzeremo per connettere tra loro i nostri container Docker.
Seppur sia possibile utilizzare la rete predefinita creata durante l’installazione, mi sento di sconsigliarne l’utilizzo in quanto non sarebbe possibile assegnare un indirizzo IP statico ai propri container.
Il seguente comando crea una rete arbitraria chiamata bushido-net
con intervallo 172.100.0.0/16
. Questa ci consentirà di eseguire container con IP statici.
sudo docker network create --subnet=172.100.0.0/16 bushido-net
Bind9
Ci sono diversi DNS Server disponibili, ma si è optato per Bind9 per la sua natura Open Source e semplicità configurativa.
Inoltre sul Docker Hub è presente l’immagine ufficiale mantenuta da Canonical: https://hub.docker.com/r/ubuntu/bind9
Creazione dei file configurativi
Ora dobbiamo creare i file per configurare Bind9 e far si che lavori sulla nostra rete Docker bushido-net.
Seguiamo gli step qui sotto per creare tutti i file necessari.
Creazione di named.conf.options
Il primo file da configurare è il named.conf.options
il quale descrive i DNS forwarders, le interfacce su cui deve stare in ascolto e la directory per la cache.
options {
directory "/var/cache/bind";
recursion yes;
listen-on { any; };
forwarders {
8.8.8.8;
8.8.4.4;
};
};
Creazione di named.conf.local
Creaiamo un file denominandolo named.conf.local
file definiamo la zona bushido-foundation.com
e la facciamo puntare al file /etc/bind/zones/db.bushido-foundation.com
.
zone "bushido-foundation.com" {
type master;
file "/etc/bind/zones/db.bushido-foundation.com";
};
Creazione di db.bushido-foundation.com
Come ultimo file creaiamo il db.bushido-foundation.com dove definiamo tutti gli host appartenenti alla nostra network (nel nostro caso saranno i container docker che andremo successivamente a creare).
$TTL 604800
@ IN SOA ns1.bushido-foundation.com. root.bushido-foundation.com. (
3 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
; name servers - NS records
IN NS ns1.bushido-foundation.com.
; name servers - A records
ns1.bushido-foundation.com. IN A 172.100.0.2
host1.bushido-foundation.com. IN A 172.100.0.3
host2.bushido-foundation.com. IN A 172.100.0.4
In questo esempio abbiamo definito un DNS Server denominato ns1.bushido-foundation.com e due host chiamati host1.bushido-foundation.com e host2.bushido-foundation.com.
Creazione dell'immagine Docker
Ora non ci resta che creare l’immagine Docker per il nostro DNS Server. Ci baseremo sull’immagine ufficiale di Bind9 mantenuta da Canonical.
Creazione del Docker file
Creiamo quindi il seguente Docker file.
FROM ubuntu/bind9:latest
RUN apt-get update && apt-get upgrade -y
COPY custom-config/named.conf.options /etc/bind/
COPY custom-config/named.conf.local /etc/bind/
COPY custom-config/db.bushido-foundation.com /etc/bind/zones/
Creazione del docker-compose.yml
Con il seguente docker-compose.yml possiamo eseguire la build dell’immagine Docker ed istanziare un container con questi dettagli:
- Container name: bushido-bind9
- IP: 172.100.0.2
Questo container sarà collegato alla seguente Docker network:
- Network name: bushido-network
- Subnet: 172.100.0.0/24
- Gateway: 172.100.0.1
version: "3.8"
services:
bind9:
build: .
image: bind9:latest
container_name: bushido-bind9
restart: always
privileged: true
networks:
bushido-network:
ipv4_address: 172.100.0.2
networks:
bushido-network:
name: bushido-network
driver: bridge
ipam:
config:
- subnet: 172.100.0.0/24
gateway: 172.100.0.1
Test di funzionalità
Build dell'immagine
Come prima cosa eseguiamo la build dell’immagine Docker e relativo istanziamento del container bushido-bind9. Lanciamo quindi il seguente comando:
sudo docker-compose up --build -d
Lancio di due container host
Ora possiamo lanciare due container host rispettivamente con IP 172.100.0.3 e 172.100.0.4 che fungeranno da test per verificare il corretto funzionamento del nostro DNS Server containerizzato. Lanciamo quindi questi due comandi:
sudo docker run -d --rm --name=host1 --net=bushido-network --ip=172.100.0.3 --dns=172.100.0.2 ubuntu:22.04 /bin/bash -c "while :; do sleep 10; done"
sudo docker run -d --rm --name=host2 --net=bushido-network --ip=172.100.0.4 --dns=172.100.0.2 ubuntu:22.04 /bin/bash -c "while :; do sleep 10; done"
Colleghiamoci quindi al container denominato host1:
sudo docker exec -it host1 /bin/bash
Una volta a bordo della macchina host1 provvediamo ad installare il comando ping
apt update
apt install iputils-ping
Ora siamo pronti per provare a pingare l’host2 e verificare la corretta risoluzione dei nomi da parte del nostro DNS Server
ping host2.bushido-foundation.com
Se otteniamo la seguente risposta, tutto è andato per il verso giusto.
PING host2.bushido-foundation.com (172.100.0.4) 56(84) bytes of data.
64 bytes from f4d843e21c53 (172.100.0.4): icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from f4d843e21c53 (172.100.0.4): icmp_seq=2 ttl=64 time=0.060 ms