Docker provider
El provider Docker observa el socket, lee labels de contenedores y genera routers/services automaticamente. Es el camino habitual con Compose: cada servicio declara como quiere publicarse y Traefik reacciona al up/down sin tocar un fichero central de rutas.
Activar el provider
Static (traefik.yml o flags):
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: proxy
watch: true| Opcion | Efecto |
|---|---|
exposedByDefault: false | Solo contenedores con traefik.enable=true |
network | Red Docker por defecto para resolver IPs |
endpoint | Socket local o TCP hacia el daemon |
Monta el socket en solo lectura:
volumes:
- /var/run/docker.sock:/var/run/docker.sock:roStack minimo
# docker-compose.yml
services:
traefik:
image: traefik:v3.3
command:
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --entrypoints.web.address=:80
- --api.insecure=true
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxy
whoami:
image: traefik/whoami:v1.10
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.localhost`)
- traefik.http.routers.whoami.entrypoints=web
- traefik.http.services.whoami.loadbalancer.server.port=80
networks:
- proxy
networks:
proxy:
name: proxydocker compose up -d
curl -H 'Host: whoami.localhost' http://127.0.0.1/
docker compose logs traefik --tail 50Mapa de labels
Patron general:
traefik.http.routers.<nombre>.<campo>
traefik.http.services.<nombre>.loadbalancer.<campo>
traefik.http.middlewares.<nombre>.<tipo>.<campo>Ejemplos concretos:
labels:
- traefik.enable=true
- traefik.http.routers.app.rule=Host(`app.example.com`) && PathPrefix(`/`)
- traefik.http.routers.app.entrypoints=websecure
- traefik.http.routers.app.tls=true
- traefik.http.routers.app.tls.certresolver=le
- traefik.http.routers.app.middlewares=app-compress,app-headers
- traefik.http.routers.app.service=app
- traefik.http.services.app.loadbalancer.server.port=3000
- traefik.http.middlewares.app-compress.compress=true
- traefik.http.middlewares.app-headers.headers.stsSeconds=31536000
- traefik.http.middlewares.app-headers.headers.frameDeny=trueSi el contenedor expone un solo puerto, Traefik puede inferirlo. Con varios puertos, loadbalancer.server.port es obligatorio.
Varios routers en un servicio
API y front en el mismo contenedor:
labels:
- traefik.enable=true
- traefik.http.routers.app-web.rule=Host(`app.example.com`)
- traefik.http.routers.app-web.entrypoints=websecure
- traefik.http.routers.app-web.tls.certresolver=le
- traefik.http.routers.app-web.service=app
- traefik.http.routers.app-api.rule=Host(`app.example.com`) && PathPrefix(`/api`)
- traefik.http.routers.app-api.entrypoints=websecure
- traefik.http.routers.app-api.tls.certresolver=le
- traefik.http.routers.app-api.middlewares=strip-api
- traefik.http.routers.app-api.service=app
- traefik.http.routers.app-api.priority=100
- traefik.http.middlewares.strip-api.stripprefix.prefixes=/api
- traefik.http.services.app.loadbalancer.server.port=8080Middlewares compartidos (file + docker)
Define middlewares globales en file provider y referencialos desde labels con el sufijo @file:
dynamic/middlewares.yml:
http:
middlewares:
sec-headers:
headers:
stsSeconds: 31536000
contentTypeNosniff: true
frameDeny: true
auth-admin:
basicAuth:
usersFile: /etc/traefik/users.htpasswdLabel:
- traefik.http.routers.admin.middlewares=sec-headers@file,auth-admin@fileAsi no duplicas headers en cada servicio.
Redes Docker
Traefik debe compartir red con el backend para alcanzar su IP. Patrones:
- Red dedicada
proxy: solo Traefik y servicios publicados. - El backend puede estar en
proxy+internalsi tambien habla con DB.
services:
api:
networks:
- proxy
- internal
labels:
- traefik.docker.network=proxy
db:
networks:
- internal
# sin traefik.enable
networks:
proxy:
internal:traefik.docker.network evita que Traefik elija la IP de una red donde el no esta.
Swarm
En Swarm, labels van en el servicio (no en el contenedor de tarea) y el provider cambia:
providers:
swarm:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: falseConstraint tipico para Traefik en managers (si usas socket):
deploy:
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.example.com`)
- traefik.http.services.whoami.loadbalancer.server.port=80Inspeccionar lo que Traefik ve
curl -s http://127.0.0.1:8080/api/http/routers | jq '.[].name'
curl -s http://127.0.0.1:8080/api/http/services | jq '.[].name'
docker inspect -f '{{json .Config.Labels}}' $(docker compose ps -q whoami) | jqSi el router no aparece: traefik.enable, red compartida, o typo en labels.
Errores habituales
- Contenedor en otra red: Traefik registra el router pero el service apunta a IP inalcanzable (504/Bad Gateway).
- Varios puertos expuestos sin
server.port. exposedByDefault: truey un contenedor de debug queda publico.- Labels en
deploy.labelsen Compose no-Swarm (o al reves): el provider no las lee. - Referencia
middleware@filesin tener el file provider cargado.
Ejercicios
- Publica
whoamicon Hostwhoami.localhosty verifica con curl. - Anade un segundo servicio con PathPrefix
/apiy stripPrefix; confirma el path en la respuesta whoami. - Mueve whoami a una red distinta sin
traefik.docker.networky observa el fallo; corrigelo. - Extrae
sec-headersa un file provider y enlazalo con@filedesde labels.
Siguiente paso
En el capitulo 4 anades certificados Let's Encrypt con certResolver y challenge HTTP o DNS.
