Cuando una aplicación corre dentro de un contenedor Docker, está aislada de la red del host. Para acceder a ella desde el navegador o desde otra aplicación hay que abrir un canal explícito entre el puerto del host y el puerto del contenedor. Eso es el mapeo de puertos.
El término «Docker Port» cubre dos cosas distintas que conviene entender por separado: el mapeo de puertos al crear el contenedor (con el flag -p) y el comando docker port para inspeccionar qué puertos tiene mapeados un contenedor ya en ejecución.
Esta guía cubre los dos. Si todavía no tienes claro cómo funciona Docker y su arquitectura de red, el artículo sobre qué es Docker explica los fundamentos antes de entrar en la configuración de puertos.
Cómo funciona el mapeo de puertos en Docker
Los contenedores Docker tienen su propia interfaz de red aislada del host. Una aplicación que escucha en el puerto 3000 del contenedor no es accesible desde fuera del contenedor a menos que ese puerto esté explícitamente mapeado al host.
El mapeo de puertos crea un puente entre los dos entornos: cuando llega tráfico al puerto del host, Docker lo redirige al puerto correspondiente del contenedor. La aplicación dentro del contenedor no necesita saber nada sobre esto: sigue escuchando en su puerto habitual.
La sintaxis es siempre puerto-host:puerto-contenedor:
# Puerto 3000 del host → puerto 3000 del contenedor
docker run -p 3000:3000 miapp
# Accesible en http://localhost:3000
El flag -p: todas las variantes

🔴 ¿Quieres entrar de lleno al mundo DevOps & Cloud Computing? 🔴
Descubre el DevOps & Cloud Computing Full Stack Bootcamp de KeepCoding. La formación más completa del mercado y con empleabilidad garantizada
👉 Prueba gratis el Bootcamp en DevOps & Cloud Computing por una semanaEl flag -p (o --publish) tiene varias formas según las necesidades específicas.
Mapeo básico puerto:puerto
La forma más común. Mapea un puerto específico del host a un puerto del contenedor:
docker run -p 8080:80 nginx
# El servidor Nginx (puerto 80 del contenedor) es accesible en localhost:8080
docker run -p 3000:3000 node-app
# La app Node.js es accesible en localhost:3000
Mapeo con IP específica del host
Si el host tiene múltiples interfaces de red y se quiere restringir el acceso a una sola IP:
# Solo accesible desde localhost, no desde la red
docker run -p 127.0.0.1:3000:3000 miapp
# Solo accesible desde una IP específica del host
docker run -p 192.168.1.100:3000:3000 miapp
# Accesible desde todas las interfaces (comportamiento por defecto)
docker run -p 0.0.0.0:3000:3000 miapp
Esta variante es útil en entornos donde el servidor tiene interfaz pública e interfaz privada y se quiere exponer el servicio solo en la red interna.
Puerto aleatorio del host
Si no se especifica el puerto del host, Docker asigna uno aleatorio disponible:
docker run -p 80 nginx
Para saber qué puerto asignó Docker hay que usar el comando docker port o docker ps.
Múltiples puertos
Para exponer varios puertos del mismo contenedor se usa el flag -p tantas veces como puertos se necesiten:
# App web + API en puertos distintos
docker run -p 3000:3000 -p 4000:4000 miapp
# Servidor web + SSL
docker run -p 80:80 -p 443:443 nginx
# App + panel de debugging
docker run -p 3000:3000 -p 9229:9229 miapp-debug
Puertos UDP
Por defecto Docker mapea puertos TCP. Para mapear puertos UDP se añade el protocolo explícitamente:
# Puerto UDP
docker run -p 5353:5353/udp dns-server
# TCP y UDP en el mismo puerto
docker run -p 53:53/tcp -p 53:53/udp dns-server
EXPOSE vs -p: la diferencia que más confusión genera
Es probablemente la confusión más frecuente cuando se empieza a trabajar con Docker y puertos.
Documenta qué puerto usa la aplicación dentro del contenedor. Es información para el desarrollador y para herramientas como Docker Compose. No publica el puerto al exterior. No hace la aplicación accesible desde fuera del contenedor.
Sí publica el puerto. Crea el mapeo real entre el puerto del host y el del contenedor. Hace la aplicación accesible desde fuera. Necesario siempre, independientemente del EXPOSE del Dockerfile.
En la práctica: un contenedor con EXPOSE 3000 en el Dockerfile pero sin -p 3000:3000 al ejecutarlo no es accesible desde el host. El EXPOSE es documentación. El -p es la acción real.
La instrucción EXPOSE en el Dockerfile es parte de las buenas prácticas de documentación. Para entender todas las instrucciones disponibles, el artículo sobre qué es un Dockerfile las cubre en detalle.
El comando docker port: inspeccionar puertos activos
El comando docker port es la herramienta de diagnóstico para ver qué puertos tiene mapeados un contenedor en ejecución. Es especialmente útil cuando se usó la asignación de puerto aleatorio o cuando se trabaja con contenedores levantados por otros.
# Ver todos los mapeos de puertos del contenedor
docker port nombre-contenedor
# Ver a qué puerto del host está mapeado un puerto específico del contenedor
docker port nombre-contenedor 80
# Salida típica:
# 80/tcp -> 0.0.0.0:8080
# Significa: puerto 80 del contenedor → puerto 8080 de todas las interfaces del host
La salida tiene el formato puerto-contenedor/protocolo -> ip-host:puerto-host. La IP 0.0.0.0 significa que el puerto es accesible desde cualquier interfaz de red del host.
# También visible en docker ps, columna PORTS
docker ps
# Ejemplo de salida en la columna PORTS:
# 0.0.0.0:8080->80/tcp, 0.0.0.0:443->443/tcp
Mapeo de puertos en Docker Compose
En Docker Compose el mapeo de puertos se define en la sección ports de cada servicio. La sintaxis es equivalente al flag -p de docker run:
services:
web:
image: nginx
ports:
- "8080:80" # puerto host:puerto contenedor
- "443:443"
api:
build: .
ports:
- "3000:3000"
- "127.0.0.1:9229:9229" # debug solo en localhost
db:
image: postgres:16-alpine
ports:
- "5432:5432" # exponer en local para herramientas de BD
Una práctica habitual en producción es no exponer los puertos de la base de datos al host (eliminar la sección ports del servicio de BD).
En Docker Compose todos los servicios del mismo archivo comparten una red interna y pueden comunicarse entre sí por nombre de servicio sin necesidad de exponer puertos al host.
Para entender la configuración completa de Docker Compose con redes y dependencias, el artículo sobre qué es Docker Compose cubre el tema en profundidad.
Resolución de problemas con puertos Docker
La mayoría de los problemas con puertos en Docker caen en tres categorías.
Conflicto de puertos: el puerto del host ya está en uso
# Error típico:
# Error response from daemon: driver failed programming external connectivity:
# Bind for 0.0.0.0:3000 failed: port is already allocated
# Diagnóstico: qué proceso usa ese puerto en el host
# Linux/macOS:
lsof -i :3000
# Windows:
netstat -ano | findstr :3000
# Solución: cambiar el puerto del host
docker run -p 3001:3000 miapp
La aplicación no es accesible aunque el contenedor esté en marcha
Verificar que el mapeo de puertos es correcto:
docker port nombre-contenedor
docker ps
Si el mapeo es correcto pero la aplicación no responde, verificar que el proceso dentro del contenedor escucha en 0.0.0.0 (todas las interfaces) y no solo en 127.0.0.1 (localhost del contenedor, no accesible desde fuera).
No se puede cambiar el puerto de un contenedor en ejecución
El mapeo de puertos se define al crear el contenedor y no se puede modificar sin recrearlo. Hay que detener el contenedor, eliminarlo y crear uno nuevo con el mapeo correcto:
docker stop miapp
docker rm miapp
docker run -p 8080:3000 --name miapp miapp:latest
En Docker Compose, cambiar el mapeo de puertos en el docker-compose.yml y ejecutar docker compose up -d recrea automáticamente los contenedores afectados. Para el despliegue completo con gestión del ciclo de vida, el artículo sobre despliegue de aplicaciones locales con Docker cubre el proceso completo.
| Comando / Sintaxis | Función |
|---|---|
docker run -p 8080:80 img |
Mapea puerto 80 del contenedor al 8080 del host |
docker run -p 127.0.0.1:80:80 img |
Solo accesible desde localhost del host |
docker run -p 80 img |
Puerto aleatorio del host → puerto 80 del contenedor |
docker run -p 80/udp img |
Mapeo de puerto UDP |
docker port contenedor |
Lista todos los mapeos activos del contenedor |
docker port contenedor 80 |
Puerto del host al que está mapeado el puerto 80 |
docker ps |
Ver todos los puertos en la columna PORTS |
Rubén trabajaba como ingeniero de aplicaciones cuando decidió dar el salto al ecosistema DevOps. Hizo el Bootcamp DevOps de KeepCoding para entender desde dentro Docker, Kubernetes y Terraform, las herramientas que aparecían en todas las ofertas que le interesaban.
Hoy trabaja como SRE en Red Hat. Gestionar la red de contenedores, los puertos y la conectividad entre servicios es parte del trabajo cotidiano en ese tipo de rol. Lo que más valoró del bootcamp fue pasar directamente a trabajar con herramientas reales en entornos que simulan producción.
Cómo aprender Docker a nivel profesional

El mapeo de puertos es uno de los conceptos más importantes de Docker para entender cómo los contenedores se comunican con el exterior y entre sí. Junto con los volúmenes y las redes, forma la base de la gestión de infraestructura con contenedores.
Lo que hemos comprobado es que la diferencia entre quien entiende Docker de forma superficial y quien lo domina no está en conocer los comandos.
Está en entender qué ocurre realmente en la red del host cuando se mapea un puerto: por qué escuchar en 127.0.0.1 dentro del contenedor rompe el mapeo, qué significa 0.0.0.0 en la salida de docker port y cómo afecta la configuración de red al comportamiento de los contenedores en producción.
Para aprender Docker a nivel profesional con proyectos reales, el DevOps y Cloud Computing Full Stack Bootcamp de KeepCoding cubre el recorrido completo en 6 meses.
Conclusión

El mapeo de puertos es el mecanismo que conecta los servicios que corren dentro de los contenedores con el mundo exterior. Sin él, los contenedores están aislados y son inaccesibles. DevOps y Cloud Computing Full Stack Bootcamp de KeepCoding.
La sintaxis del flag -p es simple pero tiene variantes importantes: mapeo básico, restricción por IP, puertos aleatorios y UDP.
El comando docker port permite inspeccionar en cualquier momento qué puertos tiene activos un contenedor.
Y la diferencia entre EXPOSE (documentación) y -p (publicación real) es fundamental para entender por qué una aplicación es o no accesible desde fuera del contenedor.
La referencia oficial sobre la gestión de puertos y redes en Docker está en docs.docker.com/engine/network/.



