¿Qué hace realmente la opción --net = host en el comando Docker?

90

Soy un poco principiante en Docker. No pude encontrar una descripción clara de lo que hace esta opción en el comando docker run en profundidad y un poco confundido al respecto.

¿Podemos usarlo para acceder a las aplicaciones que se ejecutan en contenedores Docker sin especificar un puerto? Como ejemplo, si ejecuto una aplicación web implementada a través de una imagen -p 8080:8080de Docker en el puerto 8080 usando la opción en el comando Docker Run, sé que tendré que acceder a ella en el puerto 8080 en los contenedores de Docker ip / theWebAppName. Pero realmente no puedo pensar en cómo --net=hostfunciona la opción.

Fernando Ravindu
fuente

Respuestas:

127

Después de la instalación de la ventana acoplable, tiene 3 redes por defecto:

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

Estoy tratando de mantener esto simple. Entonces, si inicia un contenedor de forma predeterminada, se creará dentro de la red del puente (docker0).

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

En el dockerfile de jenkins, los puertos 8080y 50000están expuestos. Estos puertos están abiertos para el contenedor en su red de puentes. Entonces, todo dentro de esa red de puente puede acceder al contenedor en el puerto 8080y 50000. Todo en la red del puente está en el rango privado de. "Subnet": "172.17.0.0/16",Si desea acceder a ellos desde el exterior, debe asignar los puertos con -p 8080:8080. Esto asignará el puerto de su contenedor al puerto de su servidor real (la red de host). Por lo tanto, acceder a su servidor en 8080se enrutará a su red puente en el puerto 8080.

Ahora también tienes tu red de host. Que no contenedoriza la red de contenedores. Entonces, si inicia un contenedor en la red de host, se verá así (es el primero):

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 diferencia está en los puertos. Su contenedor ahora está dentro de su red de host. Entonces, si abre el puerto 8080en su host, accederá al contenedor de inmediato.

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

Abrí un puerto 8080en mi firewall y cuando ahora accedo a mi servidor en el puerto 8080, accedo a mi jenkins. Creo que este blog también es útil para entenderlo mejor.

lvthillo
fuente
4
¿Es posible agregar la opción --net=hostdentro de un Dockerfile?
AnirbanDebnath
6
@AnirbanDebnath No creo que sea posible para ponerlo en un dockerfile pero desde v17 cargador de muelle se puede utilizar como parámetro para su construcción ventana acoplable: docker build --network=host. La red de host especificada para la compilación de Docker es solo para descargar paquetes que son necesarios para compilar la imagen. Cuando desee ejecutar su contenedor en la red de host, aún deberá definir la opción --network = host.
lvthillo
Sí @AnirbanDebnath, está permitido en Dockerfile. por ejemplo, en v3 -network_mode: "host" (ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish
Ese es un archivo Docker-Compose que describe cómo ejecutar el contenedor. No es un Dockerfile. Pero de hecho, allí es posible y hace lo mismo que docker run --network = host
lvthillo
27

La --net=hostopción se usa para hacer que los programas dentro del contenedor de Docker parezcan estar ejecutándose en el propio host, desde la perspectiva de la red. Permite al contenedor un mayor acceso a la red del que normalmente puede obtener.

Normalmente, tiene que reenviar puertos desde la máquina host a un contenedor, pero cuando los contenedores comparten la red del host, cualquier actividad de red ocurre directamente en la máquina host, tal como lo haría si el programa se ejecutara localmente en el host en lugar de dentro de un envase.

Si bien esto significa que ya no tiene que exponer puertos y asignarlos a los puertos del contenedor, significa que debe editar sus Dockerfiles para ajustar los puertos en los que escucha cada contenedor, para evitar conflictos, ya que no puede tener dos contenedores operando en el mismo Puerto host. Sin embargo, la verdadera razón de esta opción es la ejecución de aplicaciones que necesitan acceso a la red y que es difícil de reenviar a un contenedor a nivel de puerto.

Por ejemplo, si desea ejecutar un servidor DHCP, debe poder escuchar el tráfico de transmisión en la red y extraer la dirección MAC del paquete. Esta información se pierde durante el proceso de reenvío de puertos, por lo que la única forma de ejecutar un servidor DHCP dentro de Docker es ejecutar el contenedor como--net=host .

Generalmente hablando, --net=host solo es necesario cuando se ejecutan programas con necesidades de red muy específicas e inusuales.

Por último, desde una perspectiva de seguridad, los contenedores Docker pueden escuchar en muchos puertos, aunque solo anuncian (exponen) un solo puerto. Normalmente, esto está bien, ya que solo reenvía el puerto esperado, sin embargo, si lo usa --net=host, obtendrá todos los puertos del contenedor escuchando en el host, incluso aquellos que no están listados en el Dockerfile. Esto significa que deberá verificar el contenedor de cerca (especialmente si no es suyo, por ejemplo, uno oficial proporcionado por un proyecto de software) para asegurarse de no exponer inadvertidamente servicios adicionales en la máquina.

Malvino
fuente
¿Cuál sería el comportamiento si se inician varios contenedores con las opciones '--net = host'? ¿Se reenviarán las solicitudes a un contenedor aleatorio?
user482594
@ user482594: Todos compartirán la misma pila de red, al igual que usted ejecutó todos los programas dentro del mismo contenedor. Por ejemplo, si ejecuta dos servidores web, deberá asegurarse de que estén escuchando en puertos diferentes, de lo contrario, el segundo contenedor recibirá un error de que el puerto está siendo utilizado por el primero. El tráfico entrante se reenviará a cualquier contenedor que lo esté escuchando (técnicamente, todos los --net=hostcontenedores verán el tráfico, pero, por supuesto, solo un programa a la vez puede escuchar en un puerto determinado sin importar en qué contenedor lo ejecute, en esta configuración ).
Malvineous
1
  1. puede crear su propia red nueva como --net = "anyname"
  2. esto se hace para aislar los servicios de diferentes contenedores.
  3. Supongamos que el mismo servicio se está ejecutando en diferentes contenedores, pero la asignación de puertos sigue siendo la misma, el primer contenedor comienza bien, pero el mismo servicio del segundo contenedor fallará. así que para evitar esto, cambie las asignaciones de puertos o cree una red.
Abhishek DK
fuente
1
Gracias por mencionar "2. esto se hace para aislar los servicios (de red) de diferentes contenedores". Realmente veo el valor de usar otras configuraciones de red Docker (que no sean host) si existe la posibilidad de ejecutar varios contenedores en el mismo host. En otros casos (donde no se requiere aislamiento de red), preferiría --net=host.
CᴴᴀZ