Docker: Enrutamiento HTTPS
Cómo gestionar el enrutamiento HTTP y el cifrado TLS (HTTPS) en tus contenedores Docker
👋 ¡Bienvenido a la documentación de Stackhero!
Stackhero ofrece una solución Docker cloud CaaS (Containers as a Service) lista para usar que proporciona una serie de beneficios, incluyendo:
- Despliega fácilmente tus contenedores en producción con solo un
docker-compose up.- Nombre de dominio personalizable asegurado con HTTPS (por ejemplo, https://api.tu-empresa.com, https://www.tu-empresa.com, https://backoffice.tu-empresa.com).
- Rendimiento óptimo y seguridad robusta gracias a una VM privada y dedicada.
- Actualizaciones sin esfuerzo con solo un clic.
Ahorra tiempo y simplifica tu vida: ¡solo toma 5 minutos probar la solución de alojamiento en la nube Docker CaaS de Stackhero y desplegar tus contenedores en producción!
Cada instancia de Stackhero para Docker incluye un servidor Traefik dedicado y preconfigurado que gestiona el tráfico HTTP y lo cifra automáticamente utilizando certificados TLS. Esta configuración simplificada hace que el enrutamiento sea sencillo y eficiente. Por ejemplo:
- Envía el tráfico de
https://www.my-company.com(con o sin el prefijo www) a tu contenedorfrontend. - Ruta
https://www.my-company.com/documentationsa tu contenedordocumentations. - Dirige
https://api.my-project.ioa tu contenedorapi.
Puedes gestionar un número ilimitado de dominios con creación y renovación automática de certificados TLS. Lo mejor de todo es que puedes configurar todo esto con solo tres líneas.
Configuración básica de Traefik
En todos los ejemplos de configuración siguientes, tendrás que reemplazar
<XXXXXX>.stackhero-network.comcon el nombre de dominio de tu instancia de Stackhero para Docker.
A continuación, se muestra un ejemplo básico de un archivo docker-compose.yml:
services:
test:
image: nginx
labels:
- "traefik.enable=true" # Habilitar Traefik para enrutar el tráfico a este contenedor
- "traefik.http.routers.test.rule=Host(`<XXXXXX>.stackhero-network.com`)" # Definir el host
- "traefik.http.routers.test.tls.certresolver=letsencrypt" # Usar 'letsencrypt' como el resolutor de certificados TLS
En este ejemplo, un contenedor llamado test se ejecuta utilizando la imagen de Nginx. La configuración clave se proporciona en la sección de etiquetas. Simplemente necesitas copiar estas líneas en tu archivo docker-compose.yml y reemplazar <XXXXXX>.stackhero-network.com con tu dominio de servicio.
Puedes desplegar el contenedor usando:
docker context use <XXXXXX>.stackhero-network.com
docker-compose up
Después de que el contenedor se inicie, visita https://<XXXXXX>.stackhero-network.com/ para ver la página "Welcome to nginx!".
Página de bienvenida de Nginx
Si no ves la página de bienvenida de Nginx, verifica el panel de control de Traefik para posibles errores.
Con esta configuración, las solicitudes HTTP enviadas a <XXXXXX>.stackhero-network.com se enrutan a tu contenedor test y Traefik crea y gestiona automáticamente los certificados TLS para HTTPS.
Gestionar dominios personalizados con Traefik
En el ejemplo anterior, utilizamos el dominio predeterminado <XXXXXX>.stackhero-network.com. En la práctica, probablemente usarás tus propios dominios de empresa o proyecto, como www.my-company.com o api.my-project.io. La sección a continuación explica cómo configurar dominios personalizados.
Configurar tu primer dominio con Traefik
En este ejemplo, configurarás el dominio api.my-project.io. Reemplaza my-project.io con un dominio que poseas y api con tu subdominio deseado.
Primero, actualiza la configuración DNS de tu dominio para que api.my-project.io apunte a tu dominio <XXXXXX>.stackhero-network.com.
- Inicia sesión en tu proveedor de dominio y accede a tu configuración DNS.
- Crea una nueva entrada llamada
api(u otro subdominio de tu elección), establece su tipo enCNAMEy establece su destino en<XXXXXX>.stackhero-network.com.
Ejemplo de configuración DNS en la interfaz DNS de Cloudflare
Una vez configurado el DNS, puedes validarlo ejecutando:
host api.my-project.io
Deberías ver una respuesta similar a:
api.my-project.io is an alias for <XXXXXX>.stackhero-network.com
La propagación DNS puede tardar hasta 24 horas dependiendo de tu proveedor. Si el comando
hostno devuelve la respuesta esperada, espera y vuelve a intentarlo más tarde.
A continuación, actualiza tu archivo docker-compose.yml con la siguiente configuración:
services:
api:
image: traefik/whoami
hostname: api
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.my-project.io`)" # Añade tu dominio aquí
- "traefik.http.services.api.loadbalancer.server.port=<PORT>" # Reemplaza "<PORT>" con el puerto en el que tu API está escuchando
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
No olvides reemplazar
api.my-project.iocon tu dominio real en la etiqueta TraefikHost.
Despliega tu contenedor con:
docker-compose up -d
Luego visita https://api.my-project.io. Deberías ver una página de texto que muestra el nombre de host de tu contenedor api.
Prueba de que Traefik está gestionando nuestro tráfico HTTP con cifrado TLS para nuestro nuevo dominio
En la primera creación del contenedor, los certificados TLS pueden tardar unos segundos en generarse. Si encuentras un error TLS, espera unos segundos y actualiza la página para permitir que se generen los certificados.
¡Felicidades, ahora has configurado tu primer dominio personalizado!
Cómo redirigir un subdominio "www" a tu dominio raíz usando Traefik
Al definir una URL de sitio web como my-company.com, es una buena idea configurar también un subdominio "www". Esto asegura que los usuarios que se conecten a través de www.my-company.com sean redirigidos a tu sitio principal y ayuda a evitar problemas de contenido duplicado.
En el ejemplo a continuación, se gestionan tanto my-company.com como www.my-company.com. Los usuarios que acceden a www.my-company.com son redirigidos a my-company.com:
services:
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # Añade ambos dominios aquí
- "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Reemplaza "<PORT>" con el puerto en el que tu frontend está escuchando
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Redirigir 'www.my-company.com' a 'my-company.com':
- 'traefik.http.routers.frontend.middlewares=redirect-www'
- "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
- "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
- "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"
Enrutar un camino a un contenedor específico con Traefik
Supongamos que tienes un contenedor dedicado a tu sitio de documentación. Podrías querer enrutar https://my-company.com/docs a este contenedor mientras envías otras solicitudes, como https://my-company.com/, a tu contenedor frontend. El ejemplo a continuación muestra cómo se logra esto:
services:
documentations:
image: traefik/whoami
hostname: documentations
labels:
- "traefik.enable=true"
- "traefik.http.routers.documentations.rule=Host(`my-company.com`) && PathPrefix(`/docs`)" # Define el prefijo de camino aquí
- "traefik.http.services.documentations.loadbalancer.server.port=<PORT>" # Reemplaza "<PORT>" con el puerto en el que tu contenedor de documentación está escuchando
- "traefik.http.routers.documentations.tls.certresolver=letsencrypt"
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)"
- "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Reemplaza "<PORT>" con el puerto en el que tu frontend está escuchando
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Redirigir 'www.my-company.com' a 'my-company.com':
- 'traefik.http.routers.frontend.middlewares=redirect-www'
- "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
- "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
- "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"
Ahora, al visitar https://my-company.com/docs (o cualquier subruta como https://my-company.com/docs/something) se mostrará contenido del contenedor documentations. Otros caminos, por ejemplo https://my-company.com/help, serán servidos por el contenedor frontend.
Definir un puerto de contenedor personalizado en Traefik
Por defecto, Traefik se conecta al primer puerto expuesto del contenedor. En algunos casos, podrías necesitar especificar un puerto particular. El ejemplo a continuación demuestra cómo definir un puerto personalizado:
services:
frontend:
image: traefik/whoami
hostname: frontend
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`my-company.com`)"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
# Enrutar tráfico de 'https://my-company.com' al contenedor 'frontend' en el puerto 80
- "traefik.http.services.frontend.loadbalancer.server.port=80"
Buenas prácticas de nomenclatura de Traefik y Docker Compose
Al definir un contenedor en tu archivo docker-compose.yml, algunos campos son importantes para una mejor consistencia y facilidad de gestión. Considera usar la siguiente configuración recomendada:
services:
<CONTAINER_NAME>:
image: traefik/whoami
hostname: <CONTAINER_NAME>
container_name: <CONTAINER_NAME>
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.<CONTAINER_NAME>.rule=Host(`my-company.com`)"
- "traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=letsencrypt"
Simplemente reemplaza <CONTAINER_NAME> con el nombre deseado para tu contenedor, por ejemplo frontend.
Error de Let's Encrypt "Domain name contains an invalid character"
Al crear un subdominio, Let's Encrypt sigue las RFC 952 y 1123, que solo permiten caracteres en el conjunto [a-zA-Z0-9-].
Aunque los guiones bajos ('_') están permitidos en los nombres de registros DNS, no son aceptables en los nombres de host. Como resultado, Let's Encrypt rechaza subdominios como "my_subdomain.example.com" y muestra el error "Domain name contains an invalid character".
Para resolver este problema, simplemente elimina cualquier guion bajo de tus subdominios.