|

Docker + Cloudflare Tunnel: sin puertos, sin drama

Cloudflare Tunnel es un servicio gratuito que crea una conexión saliente encriptada entre tu servidor local y la red edge de Cloudflare, sin necesidad de abrir puertos en el router ni tener IP estática. Con esta guía podés exponer Docker con Cloudflare Tunnel y dominio personalizado en menos de una hora, con HTTPS automático y cero puertos expuestos al mundo.

En 30 segundos

  • Cloudflare Tunnel reemplaza el port forwarding tradicional con una conexión saliente encriptada: tu IP nunca queda expuesta.
  • El servicio es gratuito en el plan Free de Cloudflare y funciona con cualquier aplicación corriendo en Docker.
  • Solo necesitás una cuenta Cloudflare, un dominio con nameservers apuntados a Cloudflare, y tu app en contenedor.
  • La configuración se hace con un docker-compose.yml simple más un archivo config.yml con las reglas de ingress.
  • Los errores más comunes son usar DNS interno de Docker en vez de la IP del contenedor, y redes Docker mal configuradas.

Cloudflare es una plataforma estadounidense de seguridad y rendimiento en la nube que proporciona servicios como CDN, protección contra ataques DDoS, firewall y DNS. Ofrece herramientas como Cloudflare Tunnel para conectar aplicaciones y servidores privados a internet de forma segura.

Por qué el port forwarding tradicional es inseguro

Ponele que tenés una app Django corriendo en tu servidor casero y querés accederla desde afuera. La solución clásica: abrís el puerto 8000 (o el 80) en el router, configurás port forwarding hacia la IP local de tu máquina, y listo. Problema resuelto, ¿no?

No exactamente. Cuando abrís un puerto en tu router, cualquier scanner de internet puede detectarlo. Herramientas como Shodan indexan millones de IPs con puertos abiertos todos los días. Tu dirección IP pública queda asociada a un servicio expuesto, y si ese servicio tiene una vulnerabilidad (un panel de admin sin autenticación, un endpoint mal configurado, una versión desactualizada), el tiempo entre “el scanner lo detecta” y “alguien lo explota” puede ser de minutos.

La situación empeora si usás una IP dinámica, que es lo habitual en conexiones residenciales. Necesitás un servicio de DDNS, certificados SSL que renovar, reglas de firewall para cada servicio… La complejidad se apila rápido.

Cloudflare Tunnel resuelve todo esto de otra manera: en vez de que internet “entre” a tu servidor, es tu servidor el que “sale” hacia Cloudflare. Conexión saliente, sin puertos abiertos, sin exponer tu IP.

Qué es Cloudflare Tunnel y cómo funciona

Cloudflare Tunnel (antes conocido como Argo Tunnel) es un proxy inverso gestionado por Cloudflare. El proceso es así: instalás cloudflared en tu servidor, ese cliente establece una conexión saliente encriptada con los servidores edge de Cloudflare (usando el protocolo QUIC sobre UDP 7844), y a partir de ahí Cloudflare enruta el tráfico que llega a tu dominio hacia esa conexión, sin que nadie en internet necesite saber tu IP real. Relacionado: automatizar el despliegue con GitHub Actions.

La diferencia con una VPN es importante. Una VPN conecta redes o dispositivos para acceso privado. Cloudflare Tunnel conecta un servicio específico con internet de forma pública, pero sin exponer la infraestructura detrás. Para acceso a tu homelab desde vos mismo, una VPN puede ser mejor. Para publicar una app web para que otros la usen, el Tunnel es la opción.

Todo esto es gratis en el plan Free de Cloudflare, sin límites de transferencia ni de tuneles. (Sí, gratis de verdad, no el gratis-que-después-te-cobran-algo.)

Requisitos previos y configuración inicial

Antes de arrancar, necesitás tener esto en orden:

  • Una cuenta gratuita en Cloudflare
  • Un dominio añadido a Cloudflare con nameservers apuntando a los servidores de Cloudflare (te dan dos, del estilo xyz.ns.cloudflare.com)
  • Tu aplicación corriendo dentro de Docker
  • Conocimiento básico de terminal y docker-compose

Para agregar el dominio a Cloudflare: entrás al dashboard, hacés clic en “Add a Site”, ingresás tu dominio y seleccionás el plan Free. Cloudflare escanea los registros DNS existentes automáticamente. Revisás, sacás los que no necesitás, y continuás. Luego vas a tu registrador (donde compraste el dominio) y reemplazás los nameservers actuales por los dos que te da Cloudflare.

Ojo con esto: si vas a usar Cloudflare Tunnel, no necesitás un registro A apuntando a tu IP de servidor. El tunnel crea automáticamente los registros CNAME necesarios. Si dejás un registro A viejo apuntando a tu IP, podés tener conflictos raros después.

Instalación de cloudflared en Docker

La imagen oficial es cloudflare/cloudflared:latest. La forma más limpia de integrarlo es agregarlo como servicio en tu docker-compose.yml existente.

Primero necesitás el token del túnel. Vas a Cloudflare Zero Trust (zero trust.cloudflare.com), navegás a Networks > Tunnels, creás un nuevo túnel con nombre descriptivo, y en la pantalla de configuración te muestra un token. Cópialo, lo vas a necesitar. Más contexto en optimizar SEO para múltiples regiones.

Tu docker-compose.yml queda algo así:

version: '3.8'
services:
 cloudflared:
 image: cloudflare/cloudflared:latest
 restart: unless-stopped
 command: tunnel --no-autoupdate run
 environment:
 - TUNNEL_TOKEN=tu_token_aqui
 networks:
 - app_network

 backend:
 image: tu_imagen_django
 networks:
 - app_network

 frontend:
 image: tu_imagen_nginx
 networks:
 - app_network

networks:
 app_network:
 driver: bridge

El restart: unless-stopped es importante para que el daemon del túnel se recupere solo si el contenedor se cae.

Configurar las reglas de ingress

Acá viene la parte donde más gente se traba. El archivo config.yml del túnel define qué requests van a qué servicio. Si usás el token directamente en la variable de entorno (como en el ejemplo de arriba), Cloudflare toma la configuración desde el dashboard en Zero Trust. Si preferís un archivo local, montás el config.yml como volumen.

Ejemplo de configuración con múltiples rutas:

tunnel: tu-tunnel-id
credentials-file: /etc/cloudflared/creds.json

ingress:
 - hostname: api.tudominio.com
 service: http://backend:8000
 - hostname: tudominio.com
 service: http://frontend:80
 - service: http_status:404

La última línea (http_status:404) es obligatoria: es el catch-all que maneja cualquier request que no matcheó ninguna regla anterior. Sin esa línea, el archivo config no es válido y el túnel no arranca.

Cuando hacés referencia a los servicios internos, usás el nombre del servicio Docker como hostname (como backend o frontend) siempre que estén en la misma red Docker. Si no, tenés que usar la IP del contenedor directamente, lo cual no es lo ideal. Organizá bien tus redes desde el principio.

Exponiendo tu aplicación con dominio personalizado

Con el túnel corriendo, vas a Zero Trust > Networks > Tunnels, seleccionás tu túnel, y en la pestaña “Public Hostname” agregás la ruta. Poné el subdominio o dominio raíz, seleccionás el tipo (HTTP/HTTPS), y ponés la dirección interna del servicio.

Cloudflare crea automáticamente el registro CNAME en el DNS de tu dominio apuntando al UUID del túnel. El HTTPS lo maneja Cloudflare en el edge, sin que vos tengás que configurar nada de Let’s Encrypt ni certificados. El tráfico entre el browser y Cloudflare va encriptado; entre Cloudflare y tu servidor va por el túnel encriptado. Cubrimos ese tema en detalle en proteger tu tienda WooCommerce.

Según la guía publicada en mayo de 2026, el proceso completo para un stack React + Django + Nginx en Docker toma menos de una hora incluyendo la configuración del dominio.

Cloudflare Tunnel vs. alternativas: la comparativa

MétodoPuertos abiertosIP expuestaCostoComplejidadHTTPS automático
Port ForwardingGratisBajaNo
VPN (WireGuard)1 puerto UDPGratisMediaNo
Cloudflare TunnelNoNoGratisMedia
Ngrok (plan free)NoNoGratis/USD 10+Baja
Tailscale FunnelNoNoGratis/USD 6+Baja
exponer docker cloudflare tunnel dominio diagrama explicativo

Para hosting de apps propias o acceso a un homelab desde afuera, Cloudflare Tunnel está en el podio. Según análisis comparativos de la comunidad homelabber, el túnel es la opción preferida cuando el objetivo es publicar servicios web sin comprometer la seguridad de la red local.

Errores comunes y cómo solucionarlos

Usar DNS interno de Docker en el config.yml (y no funciona)

El error más frecuente: ponés service: http://mi-contenedor:8080 en el config.yml, pero cloudflared no puede resolver ese nombre porque está en una red Docker diferente a la del contenedor objetivo. La solución es asegurarte de que todos los servicios estén en la misma red Docker (como en el ejemplo del docker-compose arriba). Si no podés hacer eso por alguna razón, usá la IP del contenedor, que podés ver con docker inspect nombre_contenedor.

El YAML del config.yml no valida

El archivo config.yml es sensible a la indentación. Un tab en vez de espacios, o un espacio de más, y cloudflared se niega a arrancar con un error críptico. Antes de tirarte de los pelos, validá el YAML con cualquier herramienta online. Y acordate: la regla catch-all al final es obligatoria, no opcional.

Puerto UDP 7844 bloqueado por el firewall

cloudflared usa UDP 7844 para conectarse a los servidores de Cloudflare. Si tu proveedor de internet o firewall corporativo bloquea UDP saliente en ese puerto, el túnel no establece la conexión. La documentación oficial de Cloudflare indica que cloudflared cae back a TCP 443 automáticamente en ese caso, pero si tampoco funciona, revisá las reglas de egress de tu firewall. En redes corporativas esto es más común de lo que parece.

El túnel arranca pero el dominio no resuelve

¿El contenedor está corriendo pero el dominio devuelve error? Verificá que el CNAME se creó correctamente en el DNS de Cloudflare (en el dashboard de DNS de tu dominio), que el túnel esté en estado “Healthy” en Zero Trust > Tunnels, y que la ruta del Public Hostname esté configurada. Los logs del contenedor cloudflared son tu mejor amigo acá: docker logs nombre_contenedor_cloudflared te muestra exactamente qué está pasando.

Casos de uso y limitaciones reales

Cloudflare Tunnel tiene sentido en varios escenarios concretos: publicar una app de autoalojamiento (Nextcloud, Gitea, Planka) sin depender de un VPS, exponer herramientas internas de desarrollo para trabajo remoto sin VPN corporativa, o publicar proyectos personales desde un servidor casero con conexión domiciliaria dinámica. Si tenés un servidor en donweb.com y querés también tunelizar servicios locales de desarrollo hacia el mismo dominio, el Tunnel te lo permite con subdominios separados.

Dicho esto, hay casos donde no es la herramienta correcta. Streaming de video de alto ancho de banda genera latencia adicional porque el tráfico pasa por los edge nodes de Cloudflare (que igual están distribuidos globalmente, pero el salto existe). Aplicaciones que requieren IPs de origen reales del cliente tienen que tener en cuenta que recibirán la IP del edge de Cloudflare, no la del usuario final (aunque Cloudflare pasa la IP original en el header CF-Connecting-IP). Y hay una dependencia directa de la disponibilidad de Cloudflare, que históricamente tiene un uptime muy alto pero no es 100%.

¿Y el tema de la privacidad? Cloudflare ve todo el tráfico no encriptado que pasa por el túnel. Para apps internas sensibles, considerá si eso es aceptable para vos. Para la mayoría de casos de uso en desarrollo y homelabs, no es un problema real.

Preguntas Frecuentes

¿Cloudflare Tunnel es mejor que abrir puertos en el router?

Para publicar aplicaciones web, sí. Cloudflare Tunnel no expone tu IP pública, no requiere puertos abiertos en el router, y te da HTTPS automático sin configuración extra. El port forwarding es más simple de entender pero deja tu servidor directamente expuesto a internet. Para juegos online o servicios que necesitan conexión directa (no HTTP/HTTPS), el port forwarding sigue siendo necesario porque el túnel solo maneja tráfico web. Te puede servir nuestra cobertura de integrar Cloudflare con tu sitio.

¿Puedo usar Docker Compose con Cloudflare Tunnel?

Sí, y es la forma recomendada. Agregás cloudflared como un servicio más en tu docker-compose.yml, pasás el token del túnel como variable de entorno, y lo ponés en la misma red Docker que tus otros contenedores. Así podés referenciar los otros servicios por nombre en las reglas de ingress. El token lo generás en Cloudflare Zero Trust al crear el túnel.

¿Cómo configuro Cloudflare Tunnel con múltiples subdominios?

En el archivo config.yml (o en el dashboard de Zero Trust > Tunnels > Public Hostnames) agregás una regla por subdominio, cada una con su hostname y servicio destino. Por ejemplo, api.tudominio.com puede apuntar al contenedor del backend en el puerto 8000, y tudominio.com al Nginx en el puerto 80. Cloudflare crea automáticamente un registro CNAME por cada hostname que configurás, sin que toques el DNS manualmente.

¿Cuánto cuesta Cloudflare Tunnel?

El plan gratuito de Cloudflare incluye Cloudflare Tunnel sin costo y sin límite de transferencia. No hay límite de túneles ni de rutas. Las funcionalidades avanzadas de Zero Trust (autenticación de usuarios, políticas de acceso, etc.) tienen planes pagos desde USD 7 por usuario/mes, pero para exponer aplicaciones públicas el plan Free es suficiente.

¿Qué hago si el túnel no conecta y los logs muestran errores de conexión?

Primero verificá que el puerto UDP 7844 saliente no esté bloqueado (cloudflared cae a TCP 443 automáticamente, pero si también está bloqueado, falla). Después revisá que el token del túnel sea correcto y no tenga espacios extra al copiarlo. Si el túnel figura como “Degraded” en Zero Trust en vez de “Healthy”, revisá que el contenedor tenga acceso a internet (probá un docker exec cloudflared ping 1.1.1.1). La documentación de troubleshooting de Cloudflare cubre los códigos de error más comunes con sus soluciones.

Conclusión

El port forwarding tuvo su momento, pero para publicar aplicaciones Docker en 2026 hay opciones mucho más seguras y sin la complejidad operativa de gestionar certificados, IPs dinámicas y reglas de firewall. Cloudflare Tunnel te da todo eso gratis: sin puertos abiertos, sin exponer tu IP, con HTTPS automático y una configuración que entra en un docker-compose.yml de 20 líneas.

Si ya tenés Docker corriendo y un dominio en Cloudflare, podés tener la primera app publicada en menos de una hora (el paso que más tarda es la propagación de los nameservers, que puede demorar hasta 24 horas aunque generalmente es mucho menos). Para homelabs, desarrollo remoto o autoalojamiento, este setup ya no tiene excusas para no usarse.

Fuentes

Te puede interesar...