Docker komutundaki --net = host seçeneği gerçekte ne yapar?


97

Docker'a biraz acemiyim. Bu seçeneğin docker run komutunda ne yaptığına dair derin ve biraz kafam karışmış net bir açıklama bulamadım.

Bir port belirtmeden docker konteynerlerinde çalışan uygulamalara erişmek için kullanabilir miyiz? Örnek olarak -p 8080:8080, docker run komutundaki seçeneği kullanarak port 8080'de bir docker görüntüsü üzerinden dağıtılan bir web uygulamasını çalıştırırsam, Docker konteynerleri ip / theWebAppName üzerinde 8080 port üzerinden erişmem gerektiğini biliyorum. Ama --net=hostseçeneğin nasıl çalıştığını gerçekten düşünemiyorum .

Yanıtlar:


131

Docker kurulumundan sonra varsayılan olarak 3 ağınız olur:

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

Bunu basit tutmaya çalışıyorum. Dolayısıyla, bir kapsayıcıyı varsayılan olarak başlatırsanız, köprü (docker0) ağı içinde oluşturulacaktır.

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

Jenkins dockerfile'ında portlar 8080ve 50000açığa çıkar. Bu bağlantı noktaları, köprü ağındaki konteyner için açılır. Böylece, bu köprü ağı içindeki her şey konteynere bağlantı noktasından 8080ve 50000. Köprü ağındaki her şey "Subnet": "172.17.0.0/16",, dışardan erişmek istiyorsanız, bağlantı noktalarını eşlemeniz gerekir -p 8080:8080. Bu, konteynerinizin bağlantı noktasını gerçek sunucunuzun bağlantı noktasıyla (ana bilgisayar ağı) eşler. Bu nedenle, sunucunuza erişim 8080, bağlantı noktasındaki köprü ağınıza yönlendirilecektir 8080.

Artık ana ağınız da var. Hangi konteyner ağını kapsayıcı değil. Dolayısıyla, ana bilgisayar ağında bir kapsayıcı başlatırsanız, şöyle görünecektir (bu ilkidir):

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

Aradaki fark, bağlantı noktalarında. Konteynırınız artık ana bilgisayar ağınızın içindedir. Dolayısıyla 8080, ana makinenizde bağlantı noktasını açarsanız , konteynere hemen erişirsiniz.

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

8080Güvenlik duvarımda bağlantı noktasını açtım ve şu anda sunucuma bağlantı noktasından 8080eriştiğimde jenkins'ime erişiyorum. Bu blogun daha iyi anlamak için de faydalı olduğunu düşünüyorum .


4
Bu seçeneği --net=hostbir Dockerfile içine eklemek mümkün mü?
AnirbanDebnath

6
Ben bir dockerfile ama liman işçisi v17 size liman işçisi yapı için bir parametre olarak kullanabilirsiniz beri koymak mümkün olduğunu sanmıyorum @AnirbanDebnath: docker build --network=host. Docker derlemesi için belirtilen ana bilgisayar ağı, yalnızca görüntüyü oluşturmak için gerekli olan paketleri indirmek içindir. Konteynırınızı ana bilgisayar ağında çalıştırmak istediğinizde, yine de --network = host seçeneğini tanımlamanız gerekir.
lvthillo

Evet @AnirbanDebnath, Dockerfile'da buna izin verilir. örn. v3'te - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish

1
Bu, konteynerin nasıl çalıştırılacağını açıklayan bir Docker-Compose dosyasıdır. Dockerfile değil. Ama aslında, bu mümkündür ve docker run --network = host
lvthillo

32

Bu --net=hostseçenek, Docker kapsayıcısının içindeki programları, ağın perspektifinden, ana bilgisayarın kendisinde çalışıyor gibi görünmesini sağlamak için kullanılır. Konteynerin normalde alabileceğinden daha fazla ağ erişimine izin verir.

Normalde, bağlantı noktalarını ana makineden bir kapsayıcıya iletmeniz gerekir, ancak kaplar ana makinenin ağını paylaştığında, herhangi bir ağ etkinliği doğrudan ana makinede gerçekleşir - tıpkı programın bir ana makinenin içinde değil de yerel olarak çalıştırılması gibi. konteyner.

Bu, artık bağlantı noktalarını açığa çıkarmanız ve bunları konteyner bağlantı noktalarına eşlemeniz gerekmediği anlamına gelse de, aynı anda çalışan iki kapsayıcıya sahip olamayacağınız için çakışmaları önlemek için Dockerfile'larınızı her bir kabın dinlediği bağlantı noktalarını ayarlamak için düzenlemeniz gerektiği anlamına gelir. ana bilgisayar bağlantı noktası. Ancak, bu seçeneğin gerçek nedeni, bağlantı noktası düzeyinde bir kapsayıcıya iletilmesi zor olan ağ erişimine ihtiyaç duyan uygulamaları çalıştırmaktır.

Örneğin, bir DHCP sunucusu çalıştırmak istiyorsanız, ağdaki yayın trafiğini dinlemeniz ve paketten MAC adresini çıkarmanız gerekir. Bu bilgiler bağlantı noktası yönlendirme işlemi sırasında kaybolur, bu nedenle Docker içinde bir DHCP sunucusu çalıştırmanın tek yolu, kapsayıcıyı --net=host.

Genel olarak konuşursak, --net=hostyalnızca çok özel, olağandışı ağ gereksinimleri olan programlar çalıştırdığınızda gereklidir.

Son olarak, güvenlik açısından bakıldığında, Docker konteynerleri, yalnızca tek bir bağlantı noktasının reklamını yapsalar (ifşa etseler) bile birçok bağlantı noktasını dinleyebilir. Normalde bu kullanmak eğer sadece bununla birlikte, tek beklenen bağlantı noktasını iletmek olarak gayet --net=hostsonra elde edersiniz tüm ana bilgisayarda dinleme kabın portları, hatta Dockerfile listelenen olmadığını. Bu, makineye yanlışlıkla fazladan hizmet vermediğinizden emin olmak için konteyneri yakından kontrol etmeniz gerektiği anlamına gelir (özellikle sizin değilse, örneğin bir yazılım projesi tarafından sağlanan resmi bir tane).


Birden çok kapsayıcı '--net = host' seçenekleriyle başlatılırsa davranış ne olur? İstekler rastgele bir konteynere iletilecek mi?
user482594

@ user482594: Aynı kapsayıcı içindeki tüm programları çalıştırdığınız gibi, hepsi aynı ağ yığınını paylaşacaklar. Örneğin, iki web sunucusu çalıştırırsanız, farklı bağlantı noktalarında dinlediklerinden emin olmanız gerekir, aksi takdirde ikinci kap, bağlantı noktasının birincisi tarafından kullanıldığına dair bir hata alır. Gelen trafik, onu dinleyen konteynere yönlendirilecektir (teknik olarak tüm --net=hostkonteynerler trafiği görecek, ancak elbette, bu kurulumda hangi konteynerde çalıştırırsanız çalıştırın, belirli bir portta aynı anda sadece bir program dinleyebilir. ).
Malvineous

1
  1. --net = "anyname" gibi kendi yeni ağınızı oluşturabilirsiniz
  2. bu, hizmetleri farklı kapsayıcılardan izole etmek için yapılır.
  3. aynı hizmetin farklı kapsayıcılarda çalıştığını, ancak bağlantı noktası eşlemesinin aynı kaldığını, ilk kapsayıcı iyi bir şekilde başladığını, ancak ikinci kapsayıcıdan aynı hizmetin başarısız olacağını varsayalım. bundan kaçınmak için ya bağlantı noktası eşlemelerini değiştirin ya da bir ağ oluşturun.

1
"2. Bu, (ağ) hizmetlerini farklı kapsayıcılardan izole etmek için yapılır" dediğin için teşekkürler. hostAynı ana bilgisayarda birden fazla kapsayıcı çalıştırma olasılığı varsa, diğer docker ağ yapılandırmalarını (dışında ) kullanmanın değerini gerçekten görüyorum . Diğer durumlarda (ağ izolasyonunun gerekli olmadığı durumlarda) tercih ederim --net=host.
CᴴᴀZ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.