Docker Advanced Networking

Uno degli aspetti un po’ “trasparenti” nel mondo Docker è legato alla componente di rete, anche se in realtà ci sono diverse cose utili da dover imparare anche da questo punto di vista.

Come abbiamo già trattato in alcuni articoli precedenti, durante la creazione di un nuovo container, viene associato un indirizzo IP e, quando richiesto, un NAT su una specifica porta. Ma cosa succede quando vogliamo aumentare la sicurezza e personalizzare meglio la nostra infrastruttura Docker?

Non appena finita l’installazione di Docker, all’interno della nostra macchina ci ritroviamo una nuova scheda di rete con un indirizzo 172.17.0.0/12 (172.16.0.0/12 in ambiente Windows). Questo range ci permette di configurare moltissimi container senza doverci preoccupare della cosa per anni ma, come avrete già intuito, tutti quanti gli elementi potranno dialogare tra di loro a livello di rete.

Docker è un sistema sicuro che isola a livello di Kernel e di processi i vari container, ma al suo interno gireranno sempre applicazioni vulnerabili e quindi, in alcuni scenari, si potrebbe prediligere un ulteriore layer di protezione dato appunto dall’isolare una serie di macchine dentro una rete diversa.

I driver disponibili in Docker, per ambienti basati su Windows, sono i seguenti:

  • Network Address Translation – ogni container riceve un IP interno dal range assegnato. Il mapping delle porte sarà gestito dal container host
  • Transparent – ogni container riceve un IP direttamente dal DHCP Server presente in azienda. Ogni container potrà esporre tutte le porte necessarie senza ulteriori operazioni di mapping
  • Overlay – basata sulla tecnologia VXLAN, questo driver è utile quando si vogliono collegare due container facenti parte di due host diversi. Questa rete viene adottata in scenari di Docker Swarm ed utilizzano un IP privato
  • L2 Bridge – ogni container ha un IP statico appartenente alla stessa classe del container host. Il redirect viene effettuato attraverso la gestione a Layer-2

Questi sono i driver disponibili per Linux:

  • Bridge – ogni container riceve un IP interno dal range assegnato. Il mapping delle porte sarà gestito dal container host
  • Overlay – basata sulla tecnologia VXLAN, questo driver è utile quando si vogliono collegare due container facenti parte di due host diversi. Questa rete viene adottata in scenari di Docker Swarm ed utilizzano un IP privato
  • MACVLAN – soluzione simile alla Trasparent ma basato su IP statico e supporto alle VLAN

In questo articolo lavoreremo con la modalità Bridge, che è anche quella più comune per ambienti mono-host. Non ho parlato di NAT perché attualmente Windows Server 2016 non consente di avere più schede di questo tipo, con classi di IP diverse; quindi se volete confinare i vostri container siete costretti ad installare un nuovo container host.

Tuttavia esiste la possibilità di aggirare l’ostacolo, andando a partizionare il range di default (172.16.0.0/12), con questo script:

docker network create -d nat –subnet=172.16.0.0/24 –gateway=172.16.0.1 nat-lan-01

docker network create -d nat –subnet=172.16.1.0/24 –gateway=172.16.1.1 nat-lan-02

NB: Assicuratevi di non avere container creati, perché l’operazione non verrebbe eseguita.

Creazione Network in Linux

Per creare una nuova scheda di rete è necessario eseguire questo comando:

docker network create –driver bridge –subnet 192.168.0.0/24 –gateway 192.168.0.1 –ip-range 192.168.0.128/25 nat-lan-01

Quello che sto facendo è creare una nuova scheda in modalità NAT (bridge), con una subnet a 24bit di tipo 192.168.0.0, il cui gateway (il container host) avrà il primo IP disponibile; tutti i container creati avranno un indirizzo IP che andrà da 192.168.0.128 a 192.168.0.254.

L’elenco delle schede disponibili è visibile tramite il comando docker network ls.

Una volta fatto questo sarà possibile creare un nuovo container utilizzando la seguente sintassi:

docker run –name lab-web02 -p 801:80 –hostname “lab-web02” –network nat-lan-01 ubuntu

Nel caso volesse collegare un container già esistente, si può utilizzare questo comando:

docker network connect nat-lan-01 lab-web01

Come si possono verificare le connessioni stabilite per ogni singola network? Il comando è il seguente:

docker network inspect nat-lan-01

[
    {
        "Name": "nat-lan-01",
        "Id": "288142ee264c96f722be3a7fd60837ea3ce19387a2cfe45efc3f7f6a858bd39c",
        "Created": "2017-03-04T19:04:45.4562786+01:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/24",
                    "IPRange": "192.168.0.128/25",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "ece751a19c8bda066044fa496474f57926fb2c2947c2e962f4d6cede8a53fd08": {
                "Name": "lab-web02",
                "EndpointID": "635f99c86a97a9b03eeb6b37477002ad31cfb62f144ec77b2b5740607d0498b5",
                "MacAddress": "02:42:c0:a8:00:80",
                "IPv4Address": "192.168.0.128/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Isolamento e Sub-Connection

Creare un nuovo indirizzamento può essere utile non solo per mettere in sicurezza la propria infrastruttura, ma anche per avere una connettività dedicata tra una serie di container.

Come si può vedere dalla figura 1, è possibile creare una nuova network che collega due container per aprire un tunnel utilizzato da uno specifico servizio; ad esempio tra un front-end ed un back-end è possibile usare una rete dedicata.

In questo scenario potrebbe essere utile impostare un IP statico, per fare in modo che non ci siano problemi di comunicazione tra i due container. Questa operazione è possibile tramite la seguente sintassi:

docker network create –driver bridge –subnet 192.168.100.0/24 –gateway 192.168.100.1 –ip-range 192.168.100.128/25 net01-sql-lan

docker run –name appsrv01 -p 801:80 –hostname ” appsrv01 ” –network nat-lan-01 ubuntu-apache

docker run –name mysql01 –hostname ” mysql01 ” –network nat-lan-01 ubuntu-mysql

docker network connect net01-sql-lan appsrv01 –ip 192.168.100.130

docker network connect net01-sql-lan mysql01 –ip 192.168.100.128

Specificare un indirizzo IP anche sulla macchina front-end può aiutarci a creare delle regole tali per cui il back-end non sia accessibile da altre macchine, oltre a quelle di management, per potersi collegare.

Conclusioni

Come abbiamo visto, il networking in Docker è una componente importante e si sviluppa in molti modi. Non sono entrato nel dettaglio di ogni aspetto, ma è possibile fare ancora di più (es. creare un alias per taggare la network e collegarla tra le varie macchine).

Se volete approfondire le tematiche, è possibile leggere la documentazione disponibile ai link sottostanti.

Link Utili

Work with network commands

Windows NAT Capabilities and limitations

Windows Container Networking

Docker Network