Configuración de Traefik para desarrollo local con soporte HTTPS usando certificados de mkcert.
- Docker y Docker Compose
- mkcert (se instala automáticamente en macOS)
-
Configurar dominios:
Edita el archivo .env y agrega tus dominios separados por comas:
DOMAINS=example.test,clarodrive.test,otrodominio.test
-
Ejecutar script de inicialización:
./init.sh
Este script:
- Instala mkcert si no está disponible (macOS)
- Genera certificados SSL para cada dominio en
.env - Crea el archivo de configuración dinámica
- Crea la red Docker
web
-
Iniciar Traefik:
docker-compose up -d
CRÍTICO: Si tu servicio tiene un healthcheck configurado, asegúrate de que esté verificando el servicio correcto. Un healthcheck mal configurado puede causar que Traefik no detecte automáticamente el contenedor.
Ejemplo de healthcheck correcto para nginx:
healthcheck:
test: [ "CMD", "curl", "-f", "-k", "https://127.0.0.1" ]
interval: 10s
timeout: 3s
retries: 3
start_period: 5sErrores comunes:
- ❌ Verificar el puerto de otro servicio (ej: API en puerto 3000 cuando el contenedor es nginx)
- ❌ No usar
-kcuando nginx usa HTTPS con certificados autofirmados - ✅ Verificar el puerto correcto del servicio en el mismo contenedor
Para que un servicio sea accesible a través de Traefik, agrega estas etiquetas:
services:
mi-app:
image: mi-imagen
labels:
- "traefik.enable=true"
- "traefik.http.routers.mi-app.rule=Host(`mi-app.test`)"
- "traefik.http.routers.mi-app.entrypoints=websecure"
- "traefik.http.routers.mi-app.tls=true"
- "traefik.http.services.mi-app.loadbalancer.server.port=80"
networks:
- webservices:
mi-app-segura:
image: mi-imagen
labels:
- "traefik.enable=true"
- "traefik.http.routers.mi-app.rule=Host(`mi-app.test`)"
- "traefik.http.routers.mi-app.entrypoints=websecure"
- "traefik.http.routers.mi-app.tls=true"
- "traefik.http.services.mi-app.loadbalancer.server.scheme=https"
- "traefik.http.services.mi-app.loadbalancer.server.port=443"
- "traefik.http.services.mi-app.loadbalancer.serversTransport=skip-verify-transport"
networks:
- weblabels:
- "traefik.http.routers.mi-app.rule=Host(`mi-app.test`) || HostRegexp(`{subdomain:[a-z0-9-]+}.mi-app.test`)"-
Agrega el dominio a .env:
DOMAINS=example.test,clarodrive.test,nuevo.test
-
Ejecuta el script de inicialización:
./init.sh
Los cambios se aplicarán automáticamente sin necesidad de reiniciar Traefik.
El dashboard de Traefik está disponible en: http://localhost:8090
Si un servicio no es detectado automáticamente por Traefik después de verificar el healthcheck, puedes configurarlo manualmente creando un archivo en dynamic/.
Casos donde puede ser necesario:
- El healthcheck está correctamente configurado pero Traefik aún no detecta el contenedor (bug conocido en algunas versiones)
- Necesitas configuración más compleja que las etiquetas de Docker no permiten
- Prefieres tener la configuración en archivos para mayor control
Pasos:
-
Copia el archivo de ejemplo desde
examples/adynamic/:cp examples/example.yml dynamic/miservicio.yml
-
Edita el archivo con tu configuración:
# dynamic/miservicio.yml http: routers: miservicio: rule: "Host(`miservicio.test`) || HostRegexp(`{subdomain:[a-z0-9-]+}.miservicio.test`)" entryPoints: - websecure service: miservicio tls: {} services: miservicio: loadBalancer: servers: - url: "https://nombre-contenedor:443" serversTransport: skip-verify-transport
-
Traefik detectará automáticamente el nuevo archivo sin necesidad de reiniciar.
Ver ejemplo completo: examples/example.yml
Asegúrate de tener tus dominios .test configurados en /etc/hosts:
127.0.0.1 example.test
127.0.0.1 clarodrive.test
127.0.0.1 mi-app.test
O usa un DNS local como dnsmasq para resolver automáticamente todos los .test a 127.0.0.1.
.
├── docker-compose.yml # Configuración de Traefik
├── .env # Lista de dominios
├── init.sh # Script de inicialización
├── certs/ # Certificados SSL (generados)
│ ├── example-cert.pem
│ ├── example-key.pem
│ ├── clarodrive-cert.pem
│ └── ...
├── dynamic/ # Configuración dinámica de Traefik
│ ├── certificates.yml # Configuración de certificados (generado)
│ ├── transport.yml # Configuración de transports
│ └── *.yml # Tus configuraciones manuales (opcional)
└── examples/ # Ejemplos de configuración
└── example.yml # Ejemplo de servicio manual
skip-verify-transportdesactiva la verificación de certificados SSL en la comunicación backend- Esto es seguro para desarrollo local, pero NO para producción
- Los certificados de mkcert solo son válidos en tu máquina local
1. Verifica el healthcheck
El problema más común es un healthcheck mal configurado:
# Ver el estado del healthcheck
docker inspect nombre-contenedor | jq '.[].State.Health'
# Ver logs del healthcheck
docker inspect nombre-contenedor | jq '.[].State.Health.Log[-1]'Si el healthcheck está fallando, corrige la configuración (ver sección "Importante: Healthcheck" arriba).
2. Verifica las etiquetas de Traefik
# Ver todas las etiquetas del contenedor
docker inspect nombre-contenedor | jq '.[].Config.Labels'
# Verificar etiquetas específicas de Traefik
docker inspect nombre-contenedor | jq -r '.[].Config.Labels | to_entries[] | select(.key | startswith("traefik")) | "\(.key)=\(.value)"'3. Verifica que el contenedor esté en la red correcta
# Ver redes del contenedor
docker inspect nombre-contenedor | jq '.[].NetworkSettings.Networks | keys'
# Debe incluir "web"4. Si todo lo anterior está correcto
Usa configuración manual en dynamic/ (ver sección "Configuración manual de servicios").
Este error significa que el transport skip-verify-transport no existe. Asegúrate de que existe el archivo dynamic/transport.yml.
# Verifica que mkcert esté instalado y configurado
mkcert -install
# Regenera los certificados
./init.shVerifica que Traefik esté corriendo y el puerto esté mapeado:
docker ps --filter "name=traefik"
curl http://localhost:8090/api/overviewEstos errores son normales durante el reinicio de Traefik y pueden ignorarse. Indican que los puertos se están cerrando durante el shutdown.