Guía técnica para mapear puertos de contenedores Docker en el host

El mapeo de puertos es esencial para acceder a servicios dentro de contenedores Docker desde el host externo. Este artículo detalla varios métodos y consideraciones clave.

Consideraciones iniciales

  • Un puerto del host solo puede mapearse a un único puerto interno del contenedor. Por ejemplo, al configurar 9000->80, no se puede usar simultáneaemnte 9000->81.
  • Un puerto interno del contenedor puede recibir mapeos desde múltiples puertos del host, como 9000->80 y 9010->80.

Método 1: Mapeo durante la creación del contenedor

La opción -p permite especificar un puerto concreto del host, mientras que -P asigna un puerto aleatorio. Generalmente se prefiere -p para control explícito.

Método 2: Vinculación a una IP específica del host

Es posible restringir el acceso al mapeo a una dirección IP del host, por ejemplo, usando la IP de una interfaz de red particular.

Vincular a la IP del host

sudo docker run -d --name servidor-web2 -p 192.168.1.100:9010:80 nginx:latest

sudo docker ps

Salida muestra los mapeos: 127.0.0.1:9000->80/tcp para servidor-web1 y 192.168.1.100:9010->80/tcp para servidor-web2


Acceder a `http://127.0.0.1:9000` funcionará para servidor-web1, pero intentar `http://192.168.1.100:9000` será rechazado. Análogamente, para servidor-web2 solo se permite acceso vía `http://192.168.1.100:9010`.

</div>### Método 3: Especificación del protocolo de comunicación

Se puede indicar el protocolo (tcp o udp) al realizar el mapeo.

<div>```
# Mapeo TCP explícito
sudo docker run -d --name servicio-tcp -p 9020:80/tcp nginx:latest

# Mapeo UDP
sudo docker run -d --name servicio-udp -p 192.168.1.100:9030:80/udp nginx:latest

sudo docker ps
# servicio-tcp muestra 0.0.0.0:9020->80/tcp
# servicio-udp muestra 192.168.1.100:9030->80/udp

Nota: Un servicio diseñado para TCP (como Nginx) no será accesible mediante un mapeo UDP.

Para inspeccionar los mapeos configurados y la dirección IP interna del contenedor:

Obtener la IP interna del contenedor

sudo docker inspect servicio-tcp | grep IPAddress

Salida incluye "IPAddress": "172.17.0.3" (valor puede variar)


</div>### Método 5: Reenvío NAT con iptables para contenedores sin mapeo inicial

Cuando un contenedor se inicia sin mapeo de puertos, se puede usar iptablse en el host para redirigir tráfico.

<div>```
# Iniciar contenedor sin mapeo
sudo docker run -d --name app-interna nginx:latest

# Obtener su IP interna (ej: 172.17.0.4)
sudo docker inspect app-interna | grep IPAddress

# Configurar iptables para redirigir el puerto 9040 del host al puerto 80 del contenedor
sudo iptables -t nat -A PREROUTING -p tcp --dport 9040 -j DNAT --to-destination 172.17.0.4:80
sudo iptables -t nat -A POSTROUTING -d 172.17.0.4/32 -p tcp --sport 80 -j SNAT --to-source 192.168.1.100
sudo iptables -A INPUT -p tcp --dport 9040 -j ACCEPT

# Persistir las reglas (en sistemas basados en systemd)
sudo sh -c "iptables-save > /etc/iptables.rules"

# Reiniciar iptables o recargar reglas según el sistema
sudo systemctl restart iptables

Importante: En algunas distribuciones, asegurarse de que las reglas de rechazo ICMP en la cadena INPUT estén comentadas para evitar conflictos.

Si al iniciar un contenedor con mapeo se produce un error relacionaod con iptables (por ejemplo, "No chain/target/match by that name"), se puede solucionar reiniciando el servicio Docker y luego los contenedores.

Reiniciar todos los contenedores existentes

sudo docker start $(sudo docker ps -a -q)


Esto restablece la configuración de red de Docker y permite que los mapeos se establezcan correctamente.

</div>

Etiquetas: Docker iptables redes contenedores puertos

Publicado el 6-11 22:37