Cosa fa davvero l'opzione --net = host nel comando Docker?


97

Sono un po 'alle prime armi con Docker. Non sono riuscito a trovare una descrizione chiara di ciò che questa opzione fa nel comando di esecuzione docker in profondità e un po 'confuso al riguardo.

Possiamo usarlo per accedere alle applicazioni in esecuzione sui container Docker senza specificare una porta? Ad esempio, se eseguo una webapp distribuita tramite un'immagine docker nella porta 8080 utilizzando l'opzione -p 8080:8080nel comando docker run, so che dovrò accedervi sulla porta 8080 sui contenitori Docker ip / theWebAppName. Ma non riesco davvero a pensare a come --net=hostfunziona l'opzione.

Risposte:


131

Dopo l'installazione della finestra mobile hai 3 reti per impostazione predefinita:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

Sto cercando di mantenerlo semplice. Quindi, se avvii un container per impostazione predefinita, verrà creato all'interno della rete bridge (docker0).

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

Nel dockerfile di jenkins le porte 8080e 50000sono esposte. Queste porte vengono aperte per il contenitore sulla sua rete bridge. Quindi tutto all'interno di quella rete bridge può accedere al container su porta 8080e 50000. Tutto nella rete bridge è nel range privato di "Subnet": "172.17.0.0/16",Se vuoi accedervi dall'esterno devi mappare le porte con -p 8080:8080. Questo mapperà la porta del tuo container alla porta del tuo real server (la rete host). Quindi accedendo al tuo server su 8080verrà instradato alla tua bridgenetwork sulla porta 8080.

Ora hai anche la tua rete host. Che non containerizza la rete dei contenitori. Quindi, se avvii un contenitore nella rete host, apparirà così (è il primo):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

La differenza è con le porte. Il tuo contenitore è ora all'interno della tua rete host. Quindi, se apri la porta 8080sul tuo host, accederai immediatamente al contenitore.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

Ho aperto la porta 8080nel mio firewall e quando sto accedendo al mio server sulla porta 8080sto accedendo ai miei jenkins. Penso che questo blog sia utile anche per capirlo meglio.


4
È possibile aggiungere l'opzione --net=hostall'interno di un Dockerfile?
AnirbanDebnath

6
@AnirbanDebnath Non credo che sia possibile mettere in un dockerfile ma dal momento finestra mobile V17 si può utilizzare come parametro per la build finestra mobile: docker build --network=host. La rete host specificata per la build docker serve solo per scaricare i pacchetti necessari per la creazione dell'immagine. Quando vuoi eseguire il tuo contenitore sulla rete host, dovrai comunque definire l'opzione --network = host.
lvthillo

Sì @AnirbanDebnath, è consentito in Dockerfile. ad es. In v3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish

1
Questo è un file Docker-Compose che descrive come eseguire il contenitore. Non è un Dockerfile. Ma in effetti, è possibile e fa la stessa cosa di docker run --network = host
lvthillo

32

L' --net=hostopzione viene utilizzata per far sembrare che i programmi all'interno del contenitore Docker siano in esecuzione sull'host stesso, dal punto di vista della rete. Consente al contenitore un accesso alla rete maggiore di quello che può normalmente ottenere.

Normalmente è necessario inoltrare le porte dalla macchina host a un contenitore, ma quando i contenitori condividono la rete dell'host, qualsiasi attività di rete avviene direttamente sulla macchina host, proprio come accadrebbe se il programma fosse in esecuzione localmente sull'host invece che all'interno di un contenitore.

Anche se questo significa che non devi più esporre le porte e mapparle alle porte del contenitore, significa che devi modificare i tuoi Dockerfile per regolare le porte su cui ogni contenitore ascolta, per evitare conflitti poiché non puoi avere due contenitori che operano sullo stesso porta ospite. Tuttavia, il vero motivo di questa opzione è l'esecuzione di app che richiedono un accesso alla rete difficile da inoltrare a un contenitore a livello di porta.

Ad esempio, se si desidera eseguire un server DHCP, è necessario essere in grado di ascoltare il traffico di trasmissione sulla rete ed estrarre l'indirizzo MAC dal pacchetto. Queste informazioni vengono perse durante il processo di port forwarding, quindi l'unico modo per eseguire un server DHCP all'interno di Docker è eseguire il contenitore come file --net=host.

In generale, --net=hostè necessario solo quando si eseguono programmi con esigenze di rete molto specifiche e insolite.

Infine, dal punto di vista della sicurezza, i contenitori Docker possono ascoltare su molte porte, anche se pubblicizzano (espongono) solo una singola porta. Normalmente questo va bene poiché inoltri solo la singola porta prevista, tuttavia se la usi --net=host, otterrai tutte le porte del contenitore in ascolto sull'host, anche quelle che non sono elencate nel Dockerfile. Ciò significa che dovrai controllare attentamente il contenitore (specialmente se non è tuo, ad esempio uno ufficiale fornito da un progetto software) per assicurarti di non esporre inavvertitamente servizi extra sulla macchina.


Quale sarebbe il comportamento se più contenitori vengono avviati con le opzioni "--net = host"? Le richieste verranno inoltrate a un contenitore casuale?
user482594

@ user482594: condivideranno tutti lo stesso stack di rete, proprio come hai eseguito tutti i programmi all'interno dello stesso contenitore. Ad esempio, se esegui due server web dovrai assicurarti che siano in ascolto su porte diverse altrimenti il ​​secondo contenitore riceverà un errore che la porta è in uso dal primo. Il traffico in entrata verrà inoltrato a qualsiasi container lo stia ascoltando (tecnicamente tutti i --net=hostcontainer vedranno il traffico, ma ovviamente solo un programma alla volta può ascoltare su una data porta indipendentemente dal container in cui lo si esegue, in questa configurazione ).
Malvineous

1
  1. puoi creare la tua nuova rete come --net = "anyname"
  2. questo viene fatto per isolare i servizi da diversi contenitori.
  3. supponiamo che lo stesso servizio sia in esecuzione in contenitori diversi, ma la mappatura delle porte rimane la stessa, il primo contenitore si avvia bene, ma lo stesso servizio dal secondo contenitore fallirà. quindi per evitare ciò, modificare le mappature delle porte o creare una rete.

1
Grazie per aver menzionato "2. questo viene fatto per isolare i servizi (di rete) da diversi contenitori". Vedo davvero il valore dell'utilizzo di altre configurazioni di rete docker (diverse da host) se esiste la possibilità di eseguire più contenitori sullo stesso host. In altri casi (dove l'isolamento della rete non è richiesto), preferirei --net=host.
CᴴᴀZ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.