Co naprawdę robi opcja --net = host w poleceniu Docker?

90

Jestem trochę początkujący w Dockerze. Nie mogłem znaleźć żadnego jasnego opisu tego, co robi ta opcja w poleceniu docker run w głębokim i nieco zdezorientowanym.

Czy możemy go użyć, aby uzyskać dostęp do aplikacji działających w kontenerach docker bez określania portu? Na przykład, jeśli uruchomię aplikację internetową wdrożoną za pośrednictwem obrazu dockera na porcie 8080 za pomocą opcji -p 8080:8080w poleceniu docker run, wiem, że będę musiał uzyskać do niej dostęp na porcie 8080 w kontenerach Docker ip / theWebAppName. Ale tak naprawdę nie mogę wymyślić, jak --net=hostdziała opcja.

Ravindu Fernando
źródło

Odpowiedzi:

127

Po instalacji Dockera masz domyślnie 3 sieci:

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

Staram się, żeby to było proste. Jeśli więc domyślnie uruchamiasz kontener, zostanie on utworzony wewnątrz sieci mostka (docker0).

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

W dockerfile z jenkins porty 8080i 50000są odsłonięte. Te porty są otwarte dla kontenera w jego sieci mostowej. Więc wszystko w tej sieci mostu może uzyskać dostęp do kontenera na porcie 8080i 50000. Wszystko w sieci mostka znajduje się w prywatnym zasięgu "Subnet": "172.17.0.0/16",Jeśli chcesz uzyskać do nich dostęp z zewnątrz, musisz zmapować porty -p 8080:8080. Spowoduje to zmapowanie portu kontenera do portu twojego prawdziwego serwera (sieci hosta). Zatem dostęp do twojego serwera 8080będzie kierowany do twojej sieci mostowej na porcie 8080.

Teraz masz także swoją sieć hosta. Co nie umożliwia kontenerowania sieci kontenerów. Jeśli więc uruchomisz kontener w sieci hosta, będzie on wyglądał tak (jest to pierwszy):

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

Różnica dotyczy portów. Twój kontener znajduje się teraz w Twojej sieci hosta. Więc jeśli otworzysz port 8080na swoim hoście, natychmiast uzyskasz dostęp do kontenera.

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

Otworzyłem port 8080w mojej zaporze i kiedy teraz uzyskuję dostęp do mojego serwera na porcie 8080, uzyskuję dostęp do moich Jenkins. Myślę, że ten blog jest również przydatny, aby lepiej to zrozumieć.

lvthillo
źródło
4
Czy można dodać opcję --net=hostw pliku Dockerfile?
AnirbanDebnath,
6
@AnirbanDebnath Nie sądzę, że to możliwe, aby umieścić go w dockerfile ale ponieważ doker V17 można używać go jako parametr dla budowy Döcker: docker build --network=host. Określona sieć hosta dla kompilacji platformy Docker służy tylko do pobierania pakietów, które są niezbędne do zbudowania obrazu. Jeśli chcesz uruchomić kontener w sieci hosta, nadal musisz zdefiniować opcję --network = host.
lvthillo
Tak @AnirbanDebnath, jest to dozwolone w pliku Dockerfile. np. w wersji 3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish
To jest plik Docker-Compose, który opisuje, jak uruchomić kontener. To nie jest plik Dockerfile. Ale rzeczywiście, jest to możliwe i robi to samo, co docker run --network = host
lvthillo
27

Ta --net=hostopcja służy do tego, aby programy wewnątrz kontenera Dockera wyglądały tak, jakby były uruchomione na samym hoście, z perspektywy sieci. Pozwala kontenerowi na większy dostęp do sieci niż normalnie.

Zwykle musisz przekazywać porty z komputera hosta do kontenera, ale gdy kontenery współużytkują sieć hosta, każda aktywność sieciowa ma miejsce bezpośrednio na komputerze-hoście - tak jak gdyby program działał lokalnie na hoście zamiast wewnątrz pojemnik.

Chociaż oznacza to, że nie musisz już ujawniać portów i mapować ich na porty kontenerów, oznacza to, że musisz edytować swoje Dockerfiles, aby dostosować porty, na których nasłuchuje każdy kontener, aby uniknąć konfliktów, ponieważ nie możesz mieć dwóch kontenerów działających na tym samym port hosta. Jednak prawdziwym powodem tej opcji jest uruchamianie aplikacji wymagających dostępu do sieci, który jest trudny do przekazania do kontenera na poziomie portu.

Na przykład, jeśli chcesz uruchomić serwer DHCP, musisz mieć możliwość nasłuchiwania ruchu rozgłoszeniowego w sieci i wyodrębnienia adresu MAC z pakietu. Te informacje są tracone podczas procesu przekierowania portów, więc jedynym sposobem na uruchomienie serwera DHCP wewnątrz platformy Docker jest uruchomienie kontenera jako --net=host.

Ogólnie rzecz biorąc, --net=hostjest potrzebne tylko wtedy, gdy uruchamiasz programy o bardzo specyficznych, nietypowych potrzebach sieciowych.

Wreszcie, z punktu widzenia bezpieczeństwa, kontenery Docker mogą nasłuchiwać na wielu portach, mimo że reklamują (ujawniają) tylko jeden port. Zwykle jest to w porządku, ponieważ przekazujesz tylko jeden oczekiwany port, jednak jeśli użyjesz --net=host, otrzymasz wszystkie porty kontenera nasłuchujące na hoście, nawet te, które nie są wymienione w pliku Dockerfile. Oznacza to, że będziesz musiał dokładnie sprawdzić kontener (zwłaszcza jeśli nie jest twój, np. Oficjalny dostarczony przez projekt oprogramowania), aby upewnić się, że nieumyślnie nie ujawnisz dodatkowych usług na komputerze.

Malvineous
źródło
Jakie byłoby zachowanie, gdyby wiele kontenerów zostało uruchomionych z opcjami „--net = host”? Czy żądania będą przekazywane do losowego kontenera?
user482594
@ user482594: Wszystkie będą współdzielić ten sam stos sieciowy, tak jak uruchomiłeś wszystkie programy w tym samym kontenerze. np. jeśli uruchamiasz dwa serwery sieciowe, musisz upewnić się, że nasłuchują na różnych portach, w przeciwnym razie drugi kontener otrzyma komunikat o błędzie, że port jest używany przez pierwszy. Ruch przychodzący będzie przekazywany do dowolnego kontenera, który go nasłuchuje (technicznie rzecz biorąc, wszystkie --net=hostkontenery będą go widzieć, ale oczywiście tylko jeden program na raz może nasłuchiwać na danym porcie bez względu na to, w którym kontenerze go uruchomisz, w tej konfiguracji ).
Malvineous
1
  1. możesz stworzyć własną nową sieć, taką jak --net = "anyname"
  2. ma to na celu odizolowanie usług z innego kontenera.
  3. załóżmy, że te same usługi działają w różnych kontenerach, ale mapowanie portów pozostaje takie samo, pierwszy kontener uruchamia się dobrze, ale ta sama usługa z drugiego kontenera zakończy się niepowodzeniem. aby tego uniknąć, zmień mapowanie portów lub utwórz sieć.
Abhishek DK
źródło
1
Dziękuję za wspomnienie „2. ma to na celu odizolowanie usług (sieciowych) z innego kontenera”. Naprawdę widzę wartość używania innych konfiguracji sieci docker (innych niż host), jeśli istnieje możliwość uruchomienia wielu kontenerów na tym samym hoście. W innych przypadkach (gdzie izolacja sieci nie jest wymagana), wolałbym --net=host.
CᴴᴀZ