Red local (LAN) vs red de Docker: son dos cosas distintas
Red local (LAN) vs red de Docker: son dos cosas distintas
Estás mezclando dos conceptos que se llaman "red" pero no tienen nada que ver. Vamos a separarlos, porque tu intuición es correcta en parte pero apunta al lugar equivocado.
1. Las dos "redes" que están en juego
Red de Docker (laravel)
Es una red virtual interna que Docker crea entre los contenedores. Solo existe dentro del host. Ninguna máquina de tu LAN puede "verla" ni acceder a ella directamente. Sirve para que app hable con db por nombre (db:3306) o nginx con app (app:9000).
Esta red no tiene nada que ver con que tu app sea visible en la LAN. Es un tema puramente interno de Docker.
Red local / LAN (tu router)
Es la red física de tu casa/oficina. Tu PC tiene una IP tipo 192.168.1.50, tu celular 192.168.1.51, etc. Para que otro dispositivo vea tu Laravel, tiene que poder hacer http://192.168.1.50:8000.
Aquí es donde importa el mapeo de puertos del compose, no la red de Docker.
2. El puente entre ambas: ports: en docker-compose.yml
Cuando escribes:
ports:
- "8000:80"Docker hace algo llamado port publishing: abre el puerto 8000 en el host y lo redirige al 80 del contenedor. Por defecto, se abre en 0.0.0.0, es decir, en todas las interfaces del host, incluyendo la IP de tu LAN.
Esto significa que automáticamente:
Tú:
http://localhost:8000✅Otro PC en tu LAN:
http://192.168.1.50:8000✅ (donde 192.168.1.50 es la IP de tu host)
Ya funciona sin que toques nada. No necesitas cambiar la red de Docker.
¿Cuándo NO funcionaría?
Solo si escribieras algo como:
ports:
- "127.0.0.1:8000:80" # <-- solo accesible desde el propio hostEse 127.0.0.1: delante restringe el puerto a localhost. Tú no lo tienes así, así que estás bien.
3. Por qué entonces "no se ven" a veces
Hay tres culpables típicos cuando algo no se ve en la LAN, y ninguno es la red de Docker:
a) El firewall del host
Ubuntu, Windows y macOS traen firewalls que bloquean puertos entrantes por defecto. Si otro PC no puede conectar, revisa:
# Ubuntu
sudo ufw status
sudo ufw allow 8000/tcp
sudo ufw allow 5173/tcpb) VITE_API_URL apunta a localhost
Este es el error más común y el más importante para tu caso. En frontend/.env tienes:
VITE_API_URL=http://localhost:8000/apiCuando otro PC abre http://192.168.1.50:5173, el navegador de ese PC descarga el bundle de React y ejecuta el fetch a http://localhost:8000/api/hello. Pero localhost para ese PC es él mismo, no tu host. Resultado: error de conexión.
Solución: usa la IP de tu host en la LAN:
VITE_API_URL=http://192.168.1.50:8000/apiO mejor, dinámico (funciona desde cualquier máquina):
VITE_API_URL=http://${window.location.hostname}:8000/apiPero eso no funciona en .env porque Vite solo reemplaza variables en build/dev. Lo más práctico:
// frontend/src/App.jsx
const API = import.meta.env.VITE_API_URL || `http://${window.location.hostname}:8000/api`
fetch(`${API}/hello`)Así, si abres desde localhost, usa localhost; si abres desde 192.168.1.50, usa 192.168.1.50. Sin tocar el .env.
c) Vite y su HMR
Vite por defecto sirve en localhost. Ya lo tienes bien configurado con host: '0.0.0.0', pero el HMR (hot reload) usa websockets y a veces necesita saber la IP pública del host. Añade esto a frontend/vite.config.js:
server: {
host: '0.0.0.0',
port: 5173,
strictPort: true,
watch: { usePolling: true },
hmr: {
host: '192.168.1.50', // <-- IP de tu host en la LAN
clientPort: 5173,
},
},O si quieres que funcione sin hardcodear la IP:
hmr: {
clientPort: 5173,
},Suele bastar con clientPort; el navegador remoto usará su propio hostname.
4. La red de Docker laravel no se toca para esto
Recapitulando, para que se vea en la LAN NO necesitas:
Cambiar la red
laravel.Poner los contenedores en
network_mode: host.Crear redes
macvlano cosas raras.
Solo necesitas:
Que los
ports:estén publicados sin127.0.0.1:delante (ya lo están).Abrir esos puertos en el firewall del host.
Que
VITE_API_URLuse la IP del host (o sea dinámico).Configurar el HMR de Vite.
5. ¿Y si quisiera que los contenedores tuvieran IPs de la LAN?
Se puede, con macvlan, pero es una mala idea para desarrollo:
Cada contenedor tendría su propia IP
192.168.1.x.El router tendría que asignar IPs o reservarlas.
Rompe el aislamiento de Docker y complica el DNS interno entre contenedores.
No lo necesitas para nada.
El patrón estándar (y el que ya usas) es: los contenedores viven en su red interna, y publicas los puertos que quieras al host. El host es el único punto de contacto con la LAN. Es más simple, más seguro y más portable.
6. Cómo verificarlo paso a paso
En tu host, averigua su IP LAN:
hostname -I | awk '{print $1}'
# o
ip addr show | grep "inet " | grep -v 127.0.0.1Supongamos 192.168.1.50. Desde otro PC de la LAN:
curl http://192.168.1.50:8000/api/helloSi responde → el port publishing funciona.
Si no → es firewall (paso 3a).
Luego desde el navegador de otro PC:
http://192.168.1.50:5173Si carga la app pero falla el fetch → es VITE_API_URL (paso 3b).
7. Resumen
| Concepto | ¿Sirve para LAN? | Qué hace |
|---|---|---|
Red Docker laravel | ❌ No | Comunicación interna entre contenedores |
ports: "8000:80" | ✅ Sí | Publica el puerto en el host y lo hace accesible desde la LAN |
| Firewall del host | ⚠️ Bloquea si no se abre | Deja pasar el tráfico entrante |
VITE_API_URL | ⚠️ Debe usar la IP LAN | Para que el navegador remoto sepa a dónde llamar |
hmr.host / clientPort | ⚠️ Configurar | Para que el hot reload funcione desde otro PC |
No estás mal en pensar en la red, solo que la red relevante para "que se vea en la LAN" es la del host, no la de Docker. La red laravel es un asunto interno de Docker y no afecta la visibilidad externa
Comentarios
Publicar un comentario