- Traefik actua com a proxy invers dinàmic i resol certificats TLS, mentre Portainer ofereix una interfície gràfica per gestionar Docker i Swarm.
- La combinació de traefik.yml, dynamic.yml i docker-compose.yml permet definir entrypoints, middlewares de seguretat i enrutat HTTP/HTTPS basat en labels.
- En escenaris Docker standalone o Swarm, només cal unir serveis a la xarxa proxy i etiquetar-los perquè Traefik els descobreixi i exposi de forma segura.
- L'ús de Let's Encrypt, xarxes dedicades i autenticació bàsica al dashboard consolida un entorn robust per desplegar múltiples aplicacions en un sol servidor.
Muntar una pila moderna amb Docker, Traefik i Portainer és, avui dia, una de les formes més còmodes de gestionar contenidors en un únic servidor i exposar múltiples serveis amb HTTPS sense tornar-te boig amb la configuració. La gràcia és que Traefik actua com a proxy invers dinàmic, mentre que Portainer et dóna una interfície web molt senzilla per administrar Docker i, si vols, també Swarm.
En aquest article veuràs com encaixar Traefik com a proxy invers davant de Portainer tant en un escenari Docker “clàssic” (standalone) com en un clúster Docker Swarm, com integrar TLS (autosignat o Let's Encrypt), quins fitxers de configuració entren en joc (traefik.yml, dynamic.yml y docker-compose.yml) i alguns trucs habituals amb middlewares, xarxes i problemes típics d'etiquetes a Traefik.
Quins rols tenen Docker, Traefik i Portainer a l'arquitectura
En aquest tipus de setup, Docker és la capa base on s'executen els contenidors, Traefik fa de proxy invers i balancejador que rep totes les peticions HTTP/HTTPS als ports 80 i 443 i les envia al contenidor adequat, i Portainer proporciona una interfície gràfica per administrar imatges, contenidors, volums.
La idea és tenir un únic host amb Docker on Traefik se situa a la “porta d'entrada”: escolta als entrypoints web (80) i websecure (443), resol certificats TLS (normalment amb Let's Encrypt) i, gràcies a la integració amb el provider Docker, va descobrint automàticament els serveis que exposes afegint labels als contenidors.
D'altra banda, Portainer corre com un contenidor més, però exposat a través de un subdomini específic, per exemple portainer.tudominio.com, protegit per TLS i, si vols, després d'un middleware d'autenticació addicional al login propi de Portainer. Tot això s'orquestra amb un docker-compose que defineix Traefik, Portainer i la xarxa comuna de tipus proxy.
Un avantatge clar d'aquest enfocament és que pots desplegar nous serveis simplement afegint labels als seus contenidors: Traefik detecta el canvi a Docker, crea routers, serveis i middlewares en calent, i en segons tens un nou subdomini o ruta funcionant sense tocar manualment fitxers de configuració estàtica.
Configuració estàtica de Traefik: traefik.yml
La configuració estàtica de Traefik sol anar en un fitxer com traefik.yml, que es munta dins del contenidor. Aquí es defineix el dashboard, els entrypoints, els providers i el resoldre certificats Let's Encrypt, entre d'altres coses.
Una configuració típica a YAML arrenca activant l'API i el tauler de control amb alguna cosa com api: dashboard: true, el que permet accedir a la interfície web on veus routers, serveis i middlewares. Aquest panell, per defecte, no està autenticat, així que més endavant veurem com protegir-lo amb basic auth des de la configuració dinàmica.
Després es defineixen els entrypoints. El més normal és tenir un entrypoint web al port 80 i un altre websecure al 443. Al web se sol configurar una redirecció automàtica a websecure, de manera que qualsevol accés per HTTP es reenviï a HTTPS:
Un esquema típic inclouria una secció http.redirections.entryPoint.to: websecure per forçar aquesta redirecció i centralitzar tot el trànsit xifrat a l'entrypoint segur.
Per a websecure s'indica que heu d'usar TLS i s'enllaça un certResoldre (Per exemple letsencrypt) que serà l'encarregat de gestionar automàticament els certificats. Tot això es recolza en ACME, que és el protocol que utilitza Let's Encrypt per emetre i renovar certificats.
En el bloc proveïdors es configura el provider Docker, apuntant al socket unix:///var/run/docker.sock, amb una opció clau: exposedByDefault: false. Amb això, Traefik no publica per defecte tots els contenidors; només aquells que portin la label traefik.enable=true. També es pot configurar un provider de fitxers (file) per carregar una configuració dinàmica addicional des de, per exemple, /configurations/dynamic.yml.
Finalment, el fitxer estàtic sol incloure la secció certificatesResolvers, on es defineix el resoldre ACME: correu electrònic de registre, fitxer d'emmagatzematge (normalment acme.json), tipus de clau (per exemple EC384) i el mètode de validació (per exemple httpChallenge sobre l'entrypoint web). És important que configuris un email real en aquesta secció perquè Let's Encrypt ho utilitza per a avisos i renovacions; si deixes un valor fictici o mal format pots trobar-te errors en arrencar el contenidor de Traefik.
A més d'aquesta configuració a YAML, hi ha desplegaments que utilitzen format TOML (traefik.toml), però la lògica és la mateixa: seccionen certificats resolts (per exemple [certificatesResolvers.main.acme]), defineixen challenges (com dnsChallenge amb provider = "route53") i afegeixen opcions TLS per defecte, com forçar minVersion = "VersionTLS13" o configurar una llista de cipherSuites permesos.
Configuració dinàmica: middlewares, TLS i seguretat
La part dinàmica de Traefik sol anar en un arxiu com dynamic.yml, carregat pel provider de fitxers. Aquí defineixes middlewares i opcions TLS que es poden modificar sense reiniciar el contenidor de Traefik, la qual cosa va molt bé per ajustar seguretat sobre la marxa.
Un cas típic és crear un middleware de capçaleres, per exemple secureHeaders, que afegeixi polítiques relacionades amb HSTS i l'ús obligatori de HTTPS. A YAML podries trobar paràmetres com sslRedirect: true, forceSTSHeader: true, stsIncludeSubdomains: true, stsPreload: true i un stsSeconds elevat (per exemple un any en segons). Amb això es reforça la seguretat del trànsit des del costat del navegador.
Un altre middleware habitual és un autenticació bàsica, per exemple user-auth de tipus basicAuth, on es declara una llista d'usuaris en format usuario:hash. El hash se sol generar amb htpasswd i s'incrusta al fitxer. Aquest middleware se sol associar al router del dashboard de Traefik perquè, a més de l'accés HTTPS, exigeixi usuari i contrasenya.
Dins de la mateixa configuració dinàmica és freqüent veure un bloc tls.options amb un perfil per defecte (default) on es fixen els xifrats suportats i la versió mínima de TLS, per exemple VersionTLS12. En alguns desplegaments es defineixen diverses opcions (per exemple un perfil anomenat tls12 i un altre default) per adaptar el nivell de seguretat a diferents serveis si fos necessari.
En entorns on es vol fer servir TLS també de forma interna entre Traefik i els serveis backend (com Portainer), pot sorgir el problema que aquests serveis no comptin amb un certificat reconegut per una CA pública. Aquí entra en joc l'opció insecureSkipVerify, que, configurada sota providers.http.tls oa les opcions TLS apropiades, permet que Traefik no validi el certificat del backend. És útil per a entorns de laboratori o certificats autosignats interns, però convé fer-lo servir amb cura perquè relaxa la verificació.
Un detall pràctic: l'arxiu dynamic.yml es pot editar en calent. Traefik recarrega la configuració dinàmica sense necessitat de reinici, així pots afegir o treure middlewares, canviar les capçaleres de seguretat o modificar l'autenticació bàsica sense afectar la disponibilitat del servidor intermediari.
docker-compose amb Traefik i Portainer a Docker standalone
En un escenari Docker “a pèl”, sense Swarm, el més habitual és aixecar Traefik i Portainer amb un únic docker-compose.yml que defineix tots dos serveis i una xarxa compartida de tipus bridge trucada, per exemple, proxy.
El servei Traefik sol fer servir la imatge oficial, per exemple traefik:latest o una versió concreta com traefik:v3.4. Se li mapegen els ports 80 i 443 per al trànsit web i, en alguns exemples, el 8080 per exposar el tauler de control internament. A més, se li afegeix l'opció restart: unless-stopped i es reforça la seguretat amb security_opt: - no-new-privileges:true per reduir riscos d'escalada de privilegis dins del contenidor.
Pel que fa a volums, Traefik necessita muntar el socket de Docker de només lectura (/var/run/docker.sock:/var/run/docker.sock:ro) per descobrir contenidors, l'arxiu estàtic traefik.yml i el directori on guardarà la configuració dinàmica (./traefik-data/configurations:/configurations). També es munta el fitxer acme.json, que és on Traefik emmagatzema els certificats emesos per Let's Encrypt. Aquest fitxer es crea al host i se li posen permisos 600 perquè només el pugui llegir i escriure l'usuari adequat; si ho deixes amb 644, Traefik sol queixar-se.
La clau perquè Traefik faci la seva màgia són les labels del servei. Entre altres, trobaràs: traefik.enable=true (perquè el provider Docker exposi aquest servei), traefik.docker.network=proxy (indica quina xarxa ha de fer servir Traefik per parlar amb el contenidor), i un router com traefik.http.routers.traefik-secure, amb labels que defineixen el seu entrypoint (websecure), la regla de host (per exemple Host(`traefik.tudominio.com`)), el servei associat (api@internal) i el middleware d'autenticació (user-auth@file).
El servei de Portainer en el mateix docker-compose.yml utilitza generalment portainer/portainer-ce:latest (o l'edició Enterprise si tens llicència). Es munten volums similars: el socket de Docker, la carpeta de dades (./portainer-data:/data) i, sovint, també el /etc/localtime perquè hereti la zona horària del host.
Les labels de Portainer ho registren davant Traefik: traefik.enable=true, traefik.docker.network=proxy, un router del tipus traefik.http.routers.portainer-secure amb entrypoint websecure i una regla de host com Host(`portainer.tudominio.com`). A més, es defineix el servei que Traefik ha de fer servir apuntant al port intern de Portainer, per exemple amb traefik.http.services.portainer.loadbalancer.server.port=9000.
Amb tot això en marxa, després de llançar docker compose up -d al directori de l'stack, Traefik descarrega les imatges, crea la xarxa proxy si està declarada com a externa i exposa els dos panells als subdominis configurats, amb HTTPS automàtic gràcies a Let's Encrypt. Des d'aquell moment, afegir nous serveis és qüestió de clonar el vostre projecte, afegir-hi unes quantes labels de Traefik i connectar-lo a la xarxa proxy.
Escenari Docker Swarm: Portainer i Traefik en clúster
Quan actives Docker Swarm la pel·lícula canvia una mica, perquè els serveis es despleguen com a stacks i les xarxes solen ser de tipus overlay. No obstant això, la lògica base amb Traefik i Portainer és molt semblant: Traefik segueix actuant de proxy invers i descobridor dinàmic de serveis, i Portainer pot funcionar tant en mode standalone com en mode Portainer + agent per gestionar nodes remots dins del clúster.
En un desplegament típic Swarm, abans d'aplicar el stack es creen dues xarxes overlay que utilitzarà Traefik per encaminar trànsit entre nodes. A més, es crea un volum per persistir les dades de Portainer (per exemple portainer_data) i, si ho necessites, un per acme.json o el directori on Traefik guarda certificats i configuració.
El docker-compose.yml (que després es desplega amb docker stack deploy usant, per exemple, -c portainer.yml) sol definir dos serveis: Portainer agent, que corre en mode global a tots els nodes Linux, i el servei principal de Portainer (CE o EE), que normalment es queda en mode replicat amb una constraint perquè només s'executi en managers.
El Portainer agent munta el socket de Docker i el directori de volums (/var/lib/docker/volumes) per poder inspeccionar recursos. Es connecta a la xarxa overlay que compartirà amb Traefik, per exemple traefik_public. El servei principal de Portainer es pot configurar per parlar amb l'agent mitjançant TCP (tcp://tasks.agent:9001) i, de fet, en alguns exemples es mostra aquesta ordre amb --tlsskipverify comentat, per ometre la verificació TLS si calgués.
Al mateix stack o en un altre, Traefik s'aixeca amb el provider Docker en mode Swarm (swarmMode = true a TOML o l'opció equivalent en flags), observant els serveis etiquetats. La seva configuració inclou un certificatesResolvers.main.acme per a Let's Encrypt, un dnsChallenge amb proveïdor com Ruta53 si es vol validar certificats per DNS, i un bloc de tls.options on, per exemple, es força minVersion = "VersionTLS13" per al perfil per defecte i es defineix una llista explícita de cipherSuites per a un perfil TLS 1.2.
Les labels de Portainer a Swarm segueixen la mateixa filosofia: traefik.enable=true, un router com traefik.http.routers.portainer amb Host(`portainer.midominio.com`), traefik.http.routers.portainer.entrypoints=https (o websecure segons el naming), i traefik.http.routers.portainer.tls=true per activar TLS en aquest router. A més es pot especificar el certresolver amb traefik.http.routers.portainer.tls.certresolver=main i l'esquema del backend si el servei parla HTTPS internament amb traefik.http.services.portainer.loadbalancer.server.scheme=https.
En els logs de debug de Traefik a Swarm veuràs la configuració generada: routers com api y portainer, serveis descobrits (per exemple portainer en http://10.0.1.12:9000 i un servei traefik apuntant al port 8080 del dashboard), i, si hi ha algun problema amb labels mal definides, missatges de l'estil «Could no defineix service name for the router: too many services», que solen indicar que hi ha conflicte o duplicitat de serveis associats a un router.
Exemple mínim: whoami, rutes i TLS amb Traefik
Abans de ficar Portainer a l'equació, és força pràctic provar Traefik amb un backend molt senzill, com la imatge traefik/whoami, que torna informació sobre la petició. Això us serveix per validar que Traefik està ben configurat i que les regles d'enrutat funcionen.
Un docker-compose.yml bàsic pot incloure el servei traefik amb la imatge traefik:v3.4, muntant el socket Docker i definint els flags d'arrencada com --providers.docker=true, --providers.docker.exposedbydefault=false, --providers.docker.network=proxy i l'entrypoint --entryPoints.web.address=:80. Els ports 80 i 8080 es publiquen al host, i es crea una xarxa proxy que utilitzarà també el contenidor whoami.
El servei whoami s'arrenca a la mateixa xarxa i es marca amb traefik.enable=true. Després es defineix un router amb la label traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`) i s'indica que el seu entrypoint és web. Si fas una petició amb curl -H "Host: whoami.docker.localhost" http://localhost/, veuràs una resposta amb hostname, IPs, capçaleres i altres, la qual cosa confirma que Traefik està encaminant bé.
A partir d'aquí, és senzill afegir routing per paths. Per exemple, podeu crear un altre servei whoami-api amb la mateixa imatge, a la mateixa xarxa, i etiquetar-lo amb una regla del tipus Host(`whoami.docker.localhost`) && PathPrefix(`/api`). Així, l'arrel / anirà al whoami original i les peticions a /api les servirà whoami-api. Pots verificar-ho fent peticions a / ja /api amb el mateix host.
per activar TLS en aquest entorn local, una opció és generar un certificat autosignat per al domini *.docker.localhost amb openssl. Crees un directori certs, generes local.key y local.crt, i després afegeixes un fitxer dinàmic (per exemple dynamic/tls.yml) amb la secció tls: i les rutes certFile y keyFile apuntant aquests fitxers.
Després, actualitzes la definició del servei Traefik a docker-compose.yml per muntar la carpeta ./certs i la carpeta ./dynamic dins del contenidor, actives l'API segura amb --api.dashboard=true, creeu l'entrypoint websecure (--entryPoints.websecure.address=:443) i habilitats TLS aquí amb --entryPoints.websecure.http.tls=true. També etiquetes el router del dashboard i els routers de whoami perquè usin websecure i tinguin tls=true.
Un cop aixecat, podràs accedir a https://whoami.docker.localhost/ i al panell de Traefik amb un certificat autosignat, acceptant l'avís de seguretat del navegador. Aquesta experiència és molt semblant al que després tindràs en producció amb Let's Encrypt, però sense dependre de DNS públics.
Bones pràctiques, desplegament d'apps i resolució de problemes típics
Un patró que es repeteix en tots aquests exemples és que Traefik simplifica moltíssim el desplegament de noves aplicacions. Un cop tens el teu stack base (Traefik + Portainer + xarxa proxy + certificats), afegir un nou servei sol reduir-se a:
Clonar el projecte o copiar-ne el docker-compose.yml al servidor, apuntar un subdomini cap a la IP del host mitjançant un registre A al teu DNS (per exemple app.tudominio.com), i després afegir al servei les labels claus: traefik.enable=true, traefik.docker.network=proxy i un router amb regla de host per a aquest subdomini, especificant l'entrypoint segur websecure i servei amb el port intern correcte.
A molts tutorials es mostraria, per exemple, el desplegament d'una petita app FastAPI separada: s'hi afegeixen quatre labels, s'assegura que s'uneix a la xarxa proxy a la secció networks del docker-compose.yml, i després de fer docker compose up -d l'aplicació apareix sola al dashboard de Traefik amb TLS actiu. L'autodescoberta de Traefik fa que ni tan sols hagis de tocar la configuració estàtica.
Perquè tot vagi fi, és important tenir cura d'alguns detalls: no reutilitzar el mateix identificador de router en diverses apps, revisar que només hi hagi un servei associat a cada router (evitant l'error de too many services), utilitzar noms consistents de xarxes (per exemple, proxy a tots els stacks que vulguis exposar), i, si uses Let's Encrypt, assegurar-te que el acme.json té permisos 600 i que el correu configurat és vàlid.
En entorns Swarm, revisa també que a la configuració de Traefik el provider Docker tingui swarmMode=true y watch=true, i que les constraints dels serveis (per exemple node.role == manager per a Portainer) no entrin en conflicte amb on està desplegat Traefik. Els logs en mode debug són molt verbosos però resulten clau per localitzar problemes d'enrutat o TLS.
En conjunt, combinar Docker, Traefik i Portainer et permet muntar en un sol servidor un entorn complet d'orquestració lleugera, amb panells gràfics, certificats automàtics i un flux de desplegament molt ràpid, on afegir, actualitzar o retirar serveis es redueix a tocar unes poques línies de YAML i deixar que Traefik faci el treball.
