Análisis y comparativas
Eventos GuíasNo hay páginas en esta sección.
No hay páginas en esta sección.
Análisis y comparativas
Eventos GuíasNo hay páginas en esta sección.
No hay páginas en esta sección.
Estas notas sobre Traefik son un refrito de las siguientes fuentes:
Traefik es un edge router (router de borde, router frontera, proxy inverso) Es decir que es el punto de entrada a tu servidor (o plataforma) y se encarga de interceptar cada petición de entrada y de enrutarlas a los servicios correspondientes. Puede hacer el enrutamiento basándose en muchos criterios diferentes (nombre del host, cabeceras, etc.)
Lo normal es que instales Traefik entre tu platafoma de servicios e Internet. De esta forma no tienes que abrir mas que uno o dos puertos hacia la red (tipicamente el 80 y el 443) y atender todas las peticiones a los distintos servicios a través de estos dos puertos.
Plataforma de servicios equivale a un VPS, a una raspi en tu casa, a un servidor dedicado, etc. etc.
Normalmente los edge_router o proxy inversos necesitan un fichero de configuración detallando las reglas para enrutar las peticiones a los servicios. Traefik obtiene las reglas de los propios servicios. Así que en el momento de desplegar un nuevo servicio, un contenedor Docker en lo que respecta a este documento, especificaremos la información que ese servicio debe dar a Traefik para establecer los enrutamientos.
De esta forma cuando se despliega un servicio, Traefik lo detecta y actualiza las reglas en tiempo real. De la misma forma, si el servicio se cae o se para, Traefik elimina las rutas asociadas en tiempo real.
Para descubrir los servicios Traefik usa el API de la plataforma que los alberga, en el lenguaje propio de Traefik usa un Provider. Como nosotros vamos a usar Traefik en Docker vamos a centrarnos en el docker provider.
El siguiente fichero docker-compose contiene una configuración lo más sencilla posible con el docker provider.
Preparamos los ficheros y directorios de trabajo:
mkdir -p ~/work/docker/ejemplo_01/traefik touch ~/work/docker/ejemplo_01/traefik/docker-compose.yml
El contenido del fichero ~/work/docker/ejemplo01/traefik/docker-compose.yml
sería:
version: '3' services: reverse-proxy: # The official v2 Traefik docker image image: traefik # Enables the web UI and tells Traefik to listen to docker command: --api.insecure=true --providers.docker ports: # The HTTP port - "80:80" # The Web UI (enabled by --api.insecure=true) - "8080:8080" volumes: # So that Traefik can listen to the Docker events - /var/run/docker.sock:/var/run/docker.sock
Este fichero docker-compose:
traefik:latest
--api.insecure=true
y --providers.docker
al comando de arranque de la imagen Traefik
¡Cuidado! la opción api.insecure
no debe usarse nunca en producción. Con esta opción estamos dejando el acceso al API de nuestro Traefik abierto y sin protección.
Más adelante veremos opciones para configurar de forma segura el acceso al API.
En cuanto lanzemos nuestro docker-compose:
docker-compose --verbose up -d
Podremos acceder al dashboard de Traefik visitando http://my_server_ip:8080, donde my_server_ip
será la dirección del server donde has lanzado el contenedor o localhost
si estás haciendo las pruebas en tu ordenador personal.
Si estás lanzando el contenedor en un servidor verás que el propio Docker se encarga de abrir el firewall añadiendo las rutas necesarias a las iptables.
Puedes comprobar las reglas iptables para el puerto 8080 con el comando:
iptables-save | grep 8080
Con este Traefik básico que hemos lanzado, ya prodríamos lanzar servicios que conectaran con el mismo. Vamos a añadir unas lineas a nuestro fichero docker-compose, que quedaría así:
version: '3' services: reverse-proxy: # The official v2 Traefik docker image image: traefik # Enables the web UI and tells Traefik to listen to docker command: --api.insecure=true --providers.docker ports: # The HTTP port - "80:80" # The Web UI (enabled by --api.insecure=true) - "8080:8080" volumes: # So that Traefik can listen to the Docker events - /var/run/docker.sock:/var/run/docker.sock # ... whoami: # A container that exposes an API to show its IP address image: traefik/whoami labels: - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
Hemos incluido un nuevo servicio whoami en nuestro fichero docker-compose.yml
. Es un servicio bastante chorras que nos facilita la gente de Traefik para hacer pruebas. Simplemente responde peticiones con algunos datos del servidor whoami
como la dirección IP o el nombre de la máquina. En este caso responderá con datos de la “máquina virtual”, es decir el contenedor whoami
dentro de Docker.
Si levantamos el nuevo servicio con docker-compose up -d whoami
podremos consultar el dashboard de Traefik http://my_server_ip:8080 o directamente el raw api http://my_server_ip:8080/api/rawdata y comprobaremos que Traefik ha detectado el nuevo servicio whoami
y ha configurado la ruta.
Si queremos comprobarlo en la práctica podemos ejecutar una request con curl, con el comando: curl -H Host:whoami.docker.localhost http://my_server_ip
curl -H Host:whoami.docker.localhost http://my_server_ip Hostname: 0e1584c3151f IP: 127.0.0.1 IP: 172.19.0.3 RemoteAddr: 172.19.0.2:55008 GET / HTTP/1.1 Host: whoami.docker.localhost User-Agent: curl/7.68.0 Accept: */* Accept-Encoding: gzip X-Forwarded-For: 192.168.0.154 X-Forwarded-Host: whoami.docker.localhost X-Forwarded-Port: 80 X-Forwarded-Proto: http X-Forwarded-Server: 3b4d7b2f09be X-Real-Ip: 192.168.0.154
¿Qué esta pasando aquí?
Traefik abre dos entry points uno atiende peticiones en el puerto 80 y otro en el 8080 (para acceder al dashboard).
Cuando lanzamos nuestra petición con curl
Traefik la recibe por el puerto 80, comprueba que hay un router que encaja con la cabecera (whoami.docker.localhost
) y, de acuerdo con esa regla, le pasa la petición al contenedor del servicio whoami
.
Este router se configuró automáticamente gracias a la etiqueta traefik.http.routers.whoami.rule=Host('whoami.docker.localhost')
que asociamos al contenedor whoami
en el fichero docker-compose.yml
. Estas etiquetas son procesadas a través del provider Docker para reconfigurar Traefik en tiempo real.
El servicio whoami
atiende la petición y devuelve la respuesta al usuario.
Yo estoy probando Traefik en un servidor en mi intranet, en mi caso un mini-pc, en tu caso podría ser una raspi, o podrías estar haciendo las pruebas en un vps. O también podrías estar haciendo las pruebas en tu propio ordenador.
Si estás haciendo las pruebas en tu propio ordenador, tienes que usar localhost
o 127.0.0.1
en todos los sitios donde he dicho my_server_ip
, si estás usando un servidor de cualquier tipo, pues la ip correspondiente.
El caso es que hemos declarado la ruta para Traefik como si estuvieramos en nuestro ordenador (localhost), así que para hacer la prueba rápida con curl, especificamos la cabecera de nuestra request como whoami.docker.localhost
aunque después encaminamos la request a nuestro servidor con la URL http://my_server_ip
Con esta configuración tan sencilla podemos ver otra funcionalidad muy importante de Traefik, si lanzamos un segundo servidor whoami (un segundo contenedor) con el comando:
docker-compose up -d --scale whoami=2
Traefik se encargará de hacer reparto de carga entre los dos servidores. Si lanzamos el comando curl anterior, veremos como nos van respondiendo los dos contenedores.
Si quieres parar los contenedores ejecuta docker-compose down
Son los agentes capaces de cambiar la configuración dinámica de Traefik hay varios tipos: file, Kubernetes, Docker etc. etc.
En nuestro caso nos vamos a centrar en el docker provider
Los providers son parte de la configuración estática de Traefik.
En Traefik distinguimos entre dos configuraciónes:
Traefik obtiene su configuración dinámica a través de los Providers. En el ejemplo anterior Docker informa a Traefik de las rutas que necesita cada servicio gracias a las etiquetas (Labels) que añadimos en la configuración del servicio (ver referencia). Es un caso de configuración dinámica de Traefik a través del Docker Provider.
Son los componentes principales del “frontend” de nuestro edge router. Básicamente son los puertos de entrada donde se reciben las peticiones de servicio del “exterior”.
Los entry point son parte de la configuración estática.
Traefik puede atender peticiones HTTP o peticiones TCP por qué puede actuar como un router de nivel 7 (HTTP) o de nivel 4 (TCP).
Serían los componentes del “backend”, en nuestro caso serán servicios implementados en contenedores Docker.
Los services son parte de la configuración dinámica.
Son las reglas para pasar peticiones desde el “frontend” al “backend”. Se implementan y reconfiguran por la información recibida por los providers.
Los routers son parte de la configuración dinámica.
Pueden hacer cambios en las peticiones o en las respuestas a peticiones. Hay multitud de middlewares y además se pueden encadenar para acumular cambios.
Los middlewares son parte de la configuración dinámica.
Vamos con un ejemplo un pelín más complejo. Vamos a definir un contenedor de Traefik que simplemente expone su Dashboard, de momento no vamos a definir más contenedores, pero podremos añadirlos a este escenario en el futuro.
La gracia del ejemplo es que Traefik obtendrá los certificados SSL del dominio (p.ej. miDominio.com) automáticamente desde Let’s Encrypt. Y expondrá el dashboard en un subdominio, digamos en https://dashtraefik.miDominio.com.
Preparamos los directorios y los ficheros de trabajo.
mkdir -p ~/work/docker/ejemplo_02/traefik touch ~/work/docker/ejemplo_02/traefik/{traefik.yml,traefik_dynamic.yml,acme.json} chmod 600 ~/work/docker/ejemplo_02/traefik/acme.json
traefik.yml
será el fichero de configuración estática de Traefik.traefik_dynamic.yml
será el fichero de configuración dinámica de Traefikacme.json
es el fichero que almacenará los certificados HTTPS
Primero vamos a definir la configuración estática de nuestro Traefik, es imprescindible tener una. La almacenaremos en el fichero traefik.yml
y más adelante tendremos que hacer que el contenedor Traefik pueda acceder a esa configuración (con un bind mount por ejemplo)
Dentro de esta configuración definiremos:
http
y https
que aceptarán peticiones en los puertos 80 y 443. entryPoints: http: address: :80 https: address: :443
La redirección de puertos se solía hacer con un middleware pero desde la version 2.2 de Traefik podemos definirla en la configuración estática añadiendo unas lineas en la propia definición de los entry points:
entryPoints: http: address: :80 http: redirections: entrypoint: to: https https: address: :443
docker
y otro de tipo file
. entryPoints: http: address: :80 http: redirections: entrypoint: to: https https: address: :443 providers: docker: endpoint: unix:///var/run/docker.sock exposedByDefault: false file: filename: traefik_dynamic.yml
El docker provider de Traefik se comunica con Docker (en la máquina host ) a traves del socket de Docker (en el sistema de ficheros de la máquina _host). Así que necesitaremos que el contenedor Docker pueda acceder al socket con otro bind mount
El parámetro exposedByDefault
por defecto vale true
y hace que todos los contenedores en Docker sean visibles para Traefik. El valor recomendado es justo el contrario: false
, para que Traefik “vea” únicamente los contenedores que tiene que tiene que enrutar.
En este ejemplo concreto el docker provider
no hará nada. Pero como estamos viendo como usar Traefik con Docker es mejor acostumbrarse a definirlo siempre. En cuanto definamos algún contenedor será imprescindible.
Además del provider docker definimos un segundo provider de tipo file. Este segundo provider nos permitirá especificar la configuración dinámica mediante un fichero. En el futuro la configuración dinámica podría ampliarse a través del docker provider si definimos nuevos contenedores.
Podemos definir un provider file especificando un dirname
en lugar de un filename
. En ese caso podríamos tener varios ficheros en el directorio especificado para añadir modificaciones a la configuración dinámica de Traefik
entryPoints: http: address: :80 http: redirections: entrypoint: to: https https: address: :443 providers: docker: endpoint: unix:///var/run/docker.sock exposedByDefault: false file: filename: traefik_dynamic.yml certificatesResolvers: myresolver: acme: email: <my_email@mailprovider.com> storage: acme.json httpChallenge: entryPoint: http
Las lineas añadidas al fichero traefik.yml
definen un certificates resolver llamado myresolver
(es una etiqueta, puedes llamarlo como quieras). Tenemos que especificar un correo electrónico (sólo a efectos de notificaciones) y el fichero (o la ruta) donde Traefik almacenará los certificados obtenidos. Además para el httpChallenge tenemos que usar obligatoriamente el puerto 80, así que especificamos entryPoint: http
que previamente asociamos a ese puerto.
Traefik no va a pedir certificados de dominio por iniciativa propia, tendremos que indicar, en la configuración dinámica, que servicios queremos asegurar con un certificado (en principio todos)
También tenemos que acordarnos de que más adelante tendremos que crear un bind mount para tener fácil acceso al fichero acme.json
.
El agente ACME de Traefik genera una pareja de claves pública-privada para hablar con la autoridad certificadora (CA) de Let’s Encrypt. Después “pregunta” a la CA que debe hacer para probar que controla un dominio determinado.
La CA le planteará un conjunto de posibles “desafíos”. Puede pedirle por ejemplo, que cree un subdominio determinado en el dominio reclamado, o servir un contenido arbitrario en una dirección HTTP del dominio. Junto con los desafíos la CA envia un nonce (un número de un sólo uso)
Si el agente ACME consigue completar alguno de los desafíos planteados. Informa a la CA y le devuelve el nonce firmado con su clave.
La CA comprueba la solución del desafío y que la firma del nonce son válidas. A partir de este punto la pareja de claves asociada al dominio se considera autorizada, y el agente ACME ya puede solicitar certificados y/o revocarlos usando esta pareja de claves.
entryPoints: http: address: :80 http: redirections: entrypoint: to: https https: address: :443 providers: docker: endpoint: unix:///var/run/docker.sock exposedByDefault: false file: filename: traefik_dynamic.yml certificatesResolvers: myresolver: acme: email: <my_email@mailprovider.com> storage: acme.json httpChallenge: entryPoint: http api: dashboard: true
Con esto tendríamos completa la configuración estática de nuestro Traefik. Podríamos incluso arrancar nuestro contenedor Traefik en Docker, teniendo cuidado de mapear los puertos 80 y 443 al host y estableciendo los bind mounts necesarios para que el contenedor lea el fichero de configuración estática y el almacen de claves acme.json
. Por ejemplo podríamos ejecutar:
docker run -d \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $PWD/traefik.yml:/traefik.yml \ -v $PWD/acme.json:/acme.json \ -p 80:80 \ -p 443:443 \ --name traefik \ traefik:v2.4.0
Claro que la configuración dinámica estaría vacía, así que nuestro Traefik sería bastante tonto. Expondría los puertos 80 y 443, pero no sabría que hacer con las peticiones que le llegaran a esos puertos. Además, aunque levantaría el dashboard y su acceso en el puerto 8080 del contenedor, este no sería accesible. Por un lado no hemos añadido la opción insecure: true
y por otro no hemos establecido usuario y password así que no hay manera de consultar el dashboard
(todavía)
Vamos a completar la configuración de nuestro edge router definiendo la parte dinámica de la misma.
La vamos a definir en un fichero, pero igual que la estática no hay por que hacerlo así.
Ya hemos dicho que nuestro router básico solo expondrá el dashboard, así que tenemos que definir la capa de seguridad de acceso al dashboard y una ruta apuntando al servicio.
Para usar el middleware Basic Auth, necesitamos declarar parejas de usurio:password. Las contraseñas deben ser hash MD5, SHA1 o BCrypt.
Para generar las credenciales, es decir la pareja de usuario y password “hasheada” podemos usar distintas herramientas.
Con htpasswd
:
sudo apt install apache-utils echo $(htpasswd -nb <USER> <PASSWORD>)
Con openssl
:
openssl passwd -apr1
Si ejecutas varias veces el comando openssl
con la misma contraseña los resultados serán distintos.
Esto es normal, en cada ejecución se cambia el salt
para que funcione así. Esto impide, por ejemplo, que un atacante detecte si estas reutilizando contraseñas.
Si te fijas en la salida tiene tres campos delimitados por $$
El primer campo es apr1
el tipo de hash que estamos usando.
El segundo campo es el salt
(semilla) utilizado para generar el hash
El tercer campo es el hash propiamente dicho
Por otro lado veréis que en muchos sitios de internet indican que hay que duplicar los símbolos ‘$’ para escaparlos, tipicamente usando algún filtro sed como | sed -E "s:[\$]:\$\$:g"
pero solo aplica cuando usamos labels para configurar los servicios, no en nuestro caso ya que usamos un fichero la configuración dinámica.
Una vez que tenemos nuestra contraseña super segura en formato hash podemos añadir las siguientes lineas a nuestra configuración dinámica, para definir un middleware que llamaremos myauth
:
# Declaring the user list http: middlewares: myauth: basicAuth: users: - "user1:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" - "user2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
Una vez definido nuestro middleware de tipo basicAuth solo nos falta definir el router para nuestro dashboard. Lo llamaremos mydash
:
http: middlewares: myauth: basicAuth: users: - "user1:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" - "user2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" routers: mydash: rule: Host(`dashtraefik.miDominio.com`) middlewares: - myauth service: api@internal # This is the defined name for api. You cannot change it. tls: certresolver: myresolver
Con esto completamos la configuración de nuestro Traefik, antes de poder probar tendríamos que asegurarnos de apuntar el nombre dashtraefik.miDominio.com
a la dirección IP correcta en nuestro gestor del dominio.
Si ya tenemos el DNS correctamente configurado podríamos lanzar la prueba con:
docker run -d \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $PWD/traefik.yml:/traefik.yml \ -v $PWD/traefik_dynamic.yml:/traefik_dynamic.yml \ -v $PWD/acme.json:/acme.json \ -p 80:80 \ -p 443:443 \ --name traefik \ traefik:v2.4.0
Si no hay errores en nuestro DNS ni en la configuración del Traefik comprobaremos que podemos acceder tanto a http://dashtraefik.miDominio.com como https://dashtraefik.miDominio.com (el primero estará redirigido al segundo)
Veremos también que Traefik ha negociado con Let’s Encrypt para obtener los certificados SSL para nuestro dominio. Prueba a hacer un cat acme.json
en el servidor para ver el contenido del fichero.
En caso de problemas, probablemente el primer paso sea comprobar los logs del contenedor Traefik con docker logs traefik
Vamos a ver una configuración sencilla que nos sirva de base para empezar en producción.
Posiblemente quieras crear un usuario específico para mantener el docker en tu servidor.
sudo adduser dockadmin gpasswd -a dockadmin sudo gpasswd -a dockadmin docker
Preparamos los directorios y ficheros de trabajo:
mkdir -p ~/work/docker/ejemplo_03/{portainer,traefik/{configurations,letsencrypt}} touch ~/work/docker/ejemplo_03/{docker-compose.yml,traefik/{traefik.yml,letsencrypt/acme.json,configurations/middlewares.yml}} chmod 600 ~/work/docker/ejemplo03/traefik/letsencrypt/acme.json
Vamos a organizar nuestro Docker con dos networks:
Los contenedores de la red frontend pueden necesitar una conexión adicional con la red backend. Por ejemplo un contenedor Wordpress tiene que estar en la red frontend para publicar las páginas web a través de Traefik pero también en la red backend para comunicarse con el servidor de base de datos.
Creamos las redes en Docker con:
docker network create --subnet 172.20.0.0/16 backend docker network create --subnet 172.21.0.0/16 frontend
Los rangos de direcciones IP son arbitrarios, igual que los nombres (frontend y backend) de las redes. Podríamos usar otros cualquiera.
Ojo en Traefik V1 los términos frontend y backend tienen un significado especial. Nada que ver con las redes definidas en el ejemplo03. Cuando consultes información en internet asegúrate de que referencian la versión actual de Traefik (2.4 cuando escribo esto). Si hablan mucho de definir el frontend y el backend es muy posible que estén hablando de Traefik V1
Vamos a especificar la configuración de Traefik:
traefik.yml
configurations
mediante un provider file, todos los ficheros que pongamos en ese directorio se cargarán como parte de la configuración dinámica. Cualquier modificación en los ficheros o cualquier nuevo fichero se cargará “al vuelo”, sin necesidad de reiniciar Traefik.
En el fichero /configurations/middlewares.yml
vamos a definir middlewares que usaremos con muchos (o todos) nuestros contenedores.
Ya sabemos que en Traefik podemos definir la configuración dinámica de muchas formas, podríamos usar labels asociadas al contenedor Traefik para definir estos middlewares, pero creo que así queda más ordenado.
Definimos los middlewares:
Contenido del fichero middlewares.yml
:
http: middlewares: secureHeaders: headers: frameDeny: true sslRedirect: true forceSTSHeader: true stsIncludeSubdomains: true stsPreload: true stsSeconds: 31536000 local-whitelist: ipWhiteList: sourceRange: - "10.0.0.0/24" - "192.168.0.0/16" - "172.0.0.0/8" user-auth: basicAuth: users: - "user1:$apr1$MTqfVwiE$FKkzT5ERGFqwH9f3uipxA1" - "user2:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" - "user3:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" localsec: chain: middlewares: - local-whitelist - secureHeaders
En el fichero traefik.yml
definimos la configuración estática de Traefik:
htpp
redirigido a https
https
al que aplicamos los middleware con las cabeceras de seguridad y el certresolver apuntando a Let’s Encrypt para generar certificados SSLdocker
imprescindible clarofile
apuntando al directorio /configurations
para cargar ficheros que amplien la configuración dinámica
El contenido del fichero traefik.yml
nos quedaría:
# traefik.yml api: dashboard: true entryPoints: http: address: :80 http: redirections: entryPoint: to: https https: address: :443 http: middlewares: - secureHeaders@file tls: certResolver: letsencrypt providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false file: directory: /configurations certificatesResolvers: letsencrypt: acme: email: youruser@mailprovider.com storage: acme.json httpChallenge: entryPoint: http
Ahora que ya tenemos listos los ficheros de configuración de Traefik vamos a definir el fichero docker-compose.yml
:
:latest
en producción, hay que saber que versión usamos y hacer las actualizaciones con conocimiento de causa.traefik
) para nuestro contenedor, y definimos una política para restarts
security_opt: no-new-privileges
para impedir escaladas de privilegios con setuid
/etc/localtime
para que el contenedor sincronice la hora con el hosttraefik,yml
, el directorio de configuraciones dinámicas /configurations
y el fichero acme.json
para el certresolvertraefik-secure
api@internal
)user-auth
Host(`dashtraefik.yourdomain.com`)
external
ya que la hemos creado previamente.version: '3' services: traefik: image: traefik:v2.4 container_name: traefik restart: unless-stopped security_opt: - no-new-privileges:true networks: - frontend ports: - 80:80 - 443:443 volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/traefik.yml:/traefik.yml:ro - ./traefik/configurations:/configurations:ro - ./traefik/letsencrypt/acme.json:/acme.json labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - "traefik.http.routers.traefik-secure.entrypoints=https" - "traefik.http.routers.traefik-secure.rule=Host(`dashtraefik.yourdomain.com`)" - "traefik.http.routers.traefik-secure.service=api@internal" - "traefik.http.routers.traefik-secure.middlewares=user-auth@file" networks: frontend: external: true
Si ya tenemos nuestro DNS configurado para que el nombre dashtraefik.yourdomain.com
se resuelva correctamente ya podemos arrancar nuestro Traefik:
cd ~/work/docker/ejemplo_03 docker-compose --verbose up -d
Ya tenemos nuestro contenedor Traefik funcionando correctamente. Estamos listos para añadir nuevos servicios a nuestra plataforma.
Vamos a definir nuestro primer servicio conectado por Traefik en el mismo fichero docker-compose.yml
. Añadimos la definición del nuevo servicio en las lineas que van de la 29 a la 47:
version: '3' services: traefik: image: traefik:v2.4 container_name: traefik restart: unless-stopped security_opt: - no-new-privileges:true networks: - frontend ports: - 80:80 - 443:443 volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/traefik.yml:/traefik.yml:ro - ./traefik/configurations:/configurations:ro - ./traefik/letsencrypt/acme.json:/acme.json labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - "traefik.http.routers.traefik-secure.entrypoints=https" - "traefik.http.routers.traefik-secure.rule=Host(`dashtraefik.yourdomain.com`)" - "traefik.http.routers.traefik-secure.service=api@internal" - "traefik.http.routers.traefik-secure.middlewares=user-auth@file" portainer: image: portainer/portainer-ce:2.0.1-alpine container_name: portainer restart: unless-stopped security_opt: - no-new-privileges:true networks: - frontend volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./portainer:/data labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - "traefik.http.routers.portainer-secure.entrypoints=https" - "traefik.http.routers.portainer-secure.rule=Host(`portainer.yourdomain.com`)" - "traefik.http.routers.portainer-secure.service=portainer" - "traefik.http.services.portainer.loadbalancer.server.port=9000" networks: frontend: external: true
Añadimos un nuevo servicio portainer
, con las opciones de rearranque y de seguridad iguales a las de Traefik. Mapeamos también el fichero /etc/localtime
para que el contenedor se ponga en hora con el host; y el socket docker.sock
que Portainer necesita (Portainer es un frontend para Docker)
Añadimos también las etiquetas para informar a Traefik del nuevo servicio:
https
de TraefikHost(`portainer.yourdomain.com`)
Una vez completada la configuración del DNS, podemos levantar nuestro nuevo servicio con:
docker-compose up -d portainer
Portainer implementa su propio sistema de gestión y autenticación de usuarios. Además da problemas si activamos el middleware user-auth
Tendrás que crear un usuario admin
y protegerlo con contraseña tan pronto como lo arranques.