Cómo utilizar Traefik v2 como proxy inverso para contenedores Docker en Ubuntu 20.04

El autor seleccionó a Girls Who Code para recibir una donación como parte del programa Write for DOnations.
Introducción
Docker puede ser una forma eficiente de ejecutar aplicaciones web en producción, pero es posible que desee ejecutar varias aplicaciones en el mismo host de Docker. En esta situación, deberá configurar un proxy inverso. Esto se debe a que solo desea exponer los puertos 80
al 443
resto del mundo.
Traefik es un proxy inverso compatible con Docker que incluye un panel de control de monitoreo. Traefik v1 se ha utilizado ampliamente durante un tiempo y puedes seguir este tutorial anterior para instalar Traefik v1. Pero en este tutorial, instalarás y configurarás Traefik v2, que incluye algunas diferencias.
La mayor diferencia entre Traefik v1 y v2 es que se eliminaron los frontends y backends y su funcionalidad combinada se distribuyó entre enrutadores, middlewares y servicios. Anteriormente, un backend se encargaba de realizar modificaciones a las solicitudes y hacer que esas solicitudes llegaran a lo que se suponía que debía manejarlas. Traefik v2 proporciona una mayor separación de preocupaciones al introducir middlewares que pueden modificar las solicitudes antes de enviarlas a un servicio. Los middlewares facilitan la especificación de un único paso de modificación que puede ser utilizado por muchas rutas diferentes para que puedan reutilizarse (como la autenticación básica HTTP, que verá más adelante). Un enrutador también puede utilizar muchos middlewares diferentes.
En este tutorial, configurará Traefik v2 para enrutar solicitudes a dos contenedores de aplicaciones web diferentes: un contenedor de WordPress y un contenedor de Adminer, cada uno de los cuales se comunica con una base de datos MySQL. Configurará Traefik para que sirva todo a través de HTTPS usando Let's Encrypt.
Prerrequisitos
Para completar este tutorial, necesitará lo siguiente:
- Un servidor Ubuntu 20.04 con un usuario sudo que no sea root y un firewall. Puedes configurarlo siguiendo nuestra guía de configuración inicial del servidor Ubuntu 20.04.
- Docker instalado en su servidor, lo cual puede lograr siguiendo los pasos 1 y 2 de Cómo instalar y usar Docker en Ubuntu 20.04.
- Docker Compose se instaló siguiendo las instrucciones del Paso 1 de Cómo instalar Docker Compose en Ubuntu 20.04.
- Un dominio y tres registros A, , y . Cada uno debe apuntar a la dirección IP de su servidor. Puede aprender a apuntar dominios a Droplets de DigitalOcean leyendo la documentación de Dominios y DNS de DigitalOcean. A lo largo de este tutorial, sustituya su dominio por en los archivos de configuración y los ejemplos.
db-admin.your_domain
blog.your_domain
monitor.your_domain
your_domain
Paso 1: configuración y ejecución de Traefik
El proyecto Traefik tiene una imagen oficial de Docker, por lo que la usará para ejecutar Traefik en un contenedor Docker.
Pero antes de poner en funcionamiento su contenedor Traefik, debe crear un archivo de configuración y configurar una contraseña cifrada para poder acceder al panel de monitoreo.
Usarás la htpasswd
utilidad para crear esta contraseña cifrada. Primero, instala la utilidad, que está incluida en el apache2-utils
paquete:
- sudo apt-get install apache2-utils
Luego, genere la contraseña con htpasswd
. Reemplace secure_password
con la contraseña que desea utilizar para el usuario administrador de Traefik:
- htpasswd -nb admin secure_password
La salida del programa se verá así:
Outputadmin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
Utilizará este resultado en el archivo de configuración de Traefik para configurar la autenticación básica HTTP para el panel de control y verificación de estado de Traefik. Copie la línea de resultado completa para poder pegarla más tarde.
Para configurar el servidor Traefik, creará dos nuevos archivos de configuración llamados traefik.toml
y traefik_dynamic.toml
utilizando el formato TOML. TOML es un lenguaje de configuración similar a los archivos INI, pero estandarizado. Estos archivos nos permiten configurar el servidor Traefik y varias integraciones, o providers
, que desee utilizar. En este tutorial, utilizará tres de los proveedores disponibles de Traefik: api
, docker
y acme
. El último de ellos, acme
, admite certificados TLS mediante Let's Encrypt.
Crea y abre traefik.toml
usando nano
tu editor de texto preferido:
- nano traefik.toml
Primero, debes especificar los puertos en los que Traefik debe escuchar mediante la entryPoints
sección de tu archivo de configuración. Necesitarás dos porque quieres escuchar en el puerto 80
y 443
. Llamemos a estos puertos web
(puerto 80
) y websecure
(puerto 443
).
Agregue las siguientes configuraciones:
traefik.toml
[entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" [entryPoints.websecure] address = ":443"
Tenga en cuenta que también está redirigiendo automáticamente el tráfico para que se gestione a través de TLS.
A continuación, configure Traefik api
, que le dará acceso tanto a la API como a la interfaz del panel de control. El encabezado [api]
es todo lo que necesita porque el panel de control se habilita de forma predeterminada, pero será explícito por el momento.
Añade el siguiente código:
traefik.toml
...[api] dashboard = true
Para terminar de proteger sus solicitudes web, debe utilizar Let's Encrypt para generar certificados TLS válidos. Traefik v2 es compatible con Let's Encrypt de manera predeterminada y puede configurarlo creando un solucionador de certificados del tipo acme
.
Ahora configuremos su solucionador de certificados usando el nombre lets-encrypt
:
traefik.toml
...[certificatesResolvers.lets-encrypt.acme] email = "your_email@your_domain" storage = "acme.json" [certificatesResolvers.lets-encrypt.acme.tlsChallenge]
Esta sección se llama así acme
porque ACME es el nombre del protocolo que se utiliza para comunicarse con Let's Encrypt para administrar los certificados. El servicio Let's Encrypt requiere el registro con una dirección de correo electrónico válida, por lo que para que Traefik genere certificados para sus hosts, configure la email
clave con su dirección de correo electrónico. Luego, especifique que almacenará la información que recibirá de Let's Encrypt en un archivo JSON llamado acme.json
.
La acme.tlsChallenge
sección nos permite especificar cómo Let's Encrypt puede verificar el certificado. Lo estás configurando para que entregue un archivo como parte del desafío a través del puerto 443
.
Por último, debes configurar Traefik para que funcione con Docker.
Agregue las siguientes configuraciones:
traefik.toml
...[providers.docker] watch = true network = "web"
El docker
proveedor permite que Traefik actúe como proxy frente a los contenedores Docker. Ha configurado el proveedor para watch
los nuevos contenedores en la web
red que creará pronto.
Nuestra configuración final utiliza el file
proveedor. Con Traefik v2, las configuraciones estáticas y dinámicas no se pueden combinar. Para solucionar esto, deberá traefik.toml
definir sus configuraciones estáticas y luego guardar sus configuraciones dinámicas en otro archivo, al que llamará traefik_dynamic.toml
. Aquí está utilizando el file
proveedor para indicarle a Traefik que debe leer las configuraciones dinámicas desde un archivo diferente.
Agregue el siguiente file
proveedor:
traefik.toml
- [providers.file]
- filename = "traefik_dynamic.toml"
Tu finalización traefik.toml
se verá así:
traefik.toml
[entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" [entryPoints.websecure] address = ":443"[api] dashboard = true[certificatesResolvers.lets-encrypt.acme] email = "your_email@your_domain" storage = "acme.json" [certificatesResolvers.lets-encrypt.acme.tlsChallenge][providers.docker] watch = true network = "web"[providers.file] filename = "traefik_dynamic.toml"
Guarde y cierre el archivo.
Ahora vamos a crear traefik_dynamic.toml
.
Los valores de configuración dinámica que debes mantener en su propio archivo son los middlewares y los enrutadores. Para poner tu panel de control detrás de una contraseña, debes personalizar el enrutador de la API y configurar un middleware para que gestione la autenticación básica HTTP. Comencemos por configurar el middleware.
El middleware se configura por protocolo y, dado que está trabajando con HTTP, lo especificará como una sección encadenada a http.middlewares
. A continuación, viene el nombre de su middleware para que pueda hacer referencia a él más tarde, seguido del tipo de middleware que es, que en este caso será basicAuth
. Llamemos a su middleware simpleAuth
.
Crea y abre un nuevo archivo llamado traefik_dynamic.toml
:
- nano traefik_dynamic.toml
Agrega el siguiente código. Aquí es donde pegarás el resultado del htpasswd
comando:
traefik_dynamic.toml
[http.middlewares.simpleAuth.basicAuth] users = [ "admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/" ]
Para configurar el enrutador para la API, nuevamente deberá encadenar el nombre del protocolo, pero en lugar de usar http.middlewares
, deberá usar http.routers
seguido del nombre del enrutador. En este caso, api
proporciona su propio enrutador con nombre que puede configurar mediante la [http.routers.api]
sección . Configurará el dominio que planea usar con su panel de control también configurando la rule
clave mediante una coincidencia de host, el punto de entrada que se usará websecure
y los middlewares que se incluirán simpleAuth
.
Agregue las siguientes configuraciones:
traefik_dynamic.toml
...[http.routers.api] rule = "Host(`monitor.your_domain`)" entrypoints = ["websecure"] middlewares = ["simpleAuth"] service = "api@internal" [http.routers.api.tls] certResolver = "lets-encrypt"
El web
punto de entrada maneja el puerto 80
, mientras que el websecure
punto de entrada usa el puerto 443
para TLS/SSL. Redirecciona automáticamente todo el tráfico en el puerto 80
al websecure
punto de entrada para forzar conexiones seguras para todas las solicitudes.
Observe las últimas tres líneas aquí: configure a service, enable tls y configure certResolver
to "lets-encrypt"
. Los servicios son el paso final para determinar dónde se maneja finalmente una solicitud. El api@internal
servicio es un servicio integrado que se encuentra detrás de la API que usted expone. Al igual que los enrutadores y los middlewares, los servicios se pueden configurar en este archivo, pero no necesitará hacerlo para lograr el resultado deseado.
Su traefik_dynamic.toml
archivo completo se verá así:
traefik_dynamic.toml
[http.middlewares.simpleAuth.basicAuth] users = [ "admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/" ][http.routers.api] rule = "Host(`monitor.your_domain`)" entrypoints = ["websecure"] middlewares = ["simpleAuth"] service = "api@internal" [http.routers.api.tls] certResolver = "lets-encrypt"
Guarde el archivo y salga del editor.
Con estas configuraciones establecidas, ahora iniciará Traefik.
Paso 2: Ejecución del contenedor Traefik
En este paso, creará una red Docker para que el proxy la comparta con los contenedores. Luego, accederá al panel de control de Traefik. La red Docker es necesaria para poder usarla con aplicaciones que se ejecutan mediante Docker Compose.
Crea una nueva red Docker llamada web
:
- docker network create web
Cuando se inicia el contenedor de Traefik, lo agregará a esta red. Luego, puede agregar contenedores adicionales a esta red para que Traefik los utilice como proxy.
A continuación, crea un archivo vacío que contendrá tu información de Let's Encrypt. Lo compartirás en el contenedor para que Traefik pueda usarlo:
- touch acme.json
Traefik solo podrá usar este archivo si el usuario root dentro del contenedor tiene acceso exclusivo de lectura y escritura. Para ello, bloquee los permisos de acme.json
modo que solo el propietario del archivo tenga permiso de lectura y escritura.
- chmod 600 acme.json
Una vez que el archivo se pasa a Docker, el propietario cambiará automáticamente al usuario root dentro del contenedor.
Por último, crea el contenedor Traefik con este comando:
- docker run -d
- -v /var/run/docker.sock:/var/run/docker.sock
- -v $PWD/traefik.toml:/traefik.toml
- -v $PWD/traefik_dynamic.toml:/traefik_dynamic.toml
- -v $PWD/acme.json:/acme.json
- -p 80:80
- -p 443:443
- --network web
- --name traefik
- traefik:v2.2
Este comando es un poco largo. Vamos a desglosarlo.
Utiliza el -d
indicador para ejecutar el contenedor en segundo plano como un demonio. Luego, comparte su docker.sock
archivo en el contenedor para que el proceso Traefik pueda escuchar los cambios en los contenedores. También comparte los archivos de configuración traefik.toml
y traefik_dynamic.toml
en el contenedor, así como acme.json
.
A continuación, asigna los puertos :80
y :443
de tu host Docker a los mismos puertos en el contenedor Traefik para que Traefik reciba todo el tráfico HTTP y HTTPS al servidor.
Establece la red del contenedor en web
y nombra el contenedor como traefik
.
Por último, utiliza la traefik:v2.2
imagen de este contenedor para garantizar que no estás ejecutando una versión completamente diferente de aquella para la que está escrito este tutorial.
Una imagen de Docker ENTRYPOINT
es un comando que siempre se ejecuta cuando se crea un contenedor a partir de la imagen. En este caso, el comando es el traefik
binario dentro del contenedor. Puedes pasar argumentos adicionales a ese comando cuando inicias el contenedor, pero has configurado todos los ajustes en el traefik.toml
archivo.
Una vez iniciado el contenedor, ahora tienes un panel al que puedes acceder para ver el estado de tus contenedores. También puedes usar este panel para visualizar los enrutadores, servicios y middlewares que Traefik ha registrado. Puedes intentar acceder al panel de monitoreo apuntando tu navegador a (el seguimiento es obligatorio).https://monitor.your_domain/dashboard/
/
Se le solicitará su nombre de usuario y contraseña, que son admin y la contraseña que configuró en el Paso 1.
Una vez que haya iniciado sesión, verá la interfaz de Traefik:
Notarás que ya hay algunos enrutadores y servicios registrados, pero esos son los que vienen con Traefik y la configuración del enrutador que escribiste para la API.
Ahora tienes el proxy Traefik en funcionamiento y lo has configurado para que funcione con Docker y monitoree otros contenedores. En el siguiente paso, iniciarás algunos contenedores para que Traefik los utilice como proxy.
Paso 3: Registro de contenedores con Traefik
Con el contenedor de Traefik en ejecución, ya está listo para ejecutar aplicaciones detrás de él. Iniciemos los siguientes contenedores detrás de Traefik:
- Un blog que utiliza la imagen oficial de WordPress.
- Un servidor de gestión de bases de datos que utiliza la imagen oficial de Adminer.
Administrarás ambas aplicaciones con Docker Compose usando un docker-compose.yml
archivo.
Crea y abre el docker-compose.yml
archivo en tu editor:
- nano docker-compose.yml
Agregue las siguientes líneas al archivo para especificar la versión y las redes que utilizará:
docker-compose.yml
version: "3"networks: web: external: true internal: external: false
Utiliza la versión de Docker Compose 3
porque es la versión principal más nueva del formato de archivo Compose.
Para que Traefik reconozca sus aplicaciones, deben ser parte de la misma red y, dado que creó la red manualmente, la incorpora especificando el nombre de red web
y configurando external
en true
. Luego, define otra red para poder conectar sus contenedores expuestos a un contenedor de base de datos que no expondrá a través de Traefik. Llamará a esta red internal
.
A continuación, definirás cada uno de tus archivos services
, uno a la vez. Empecemos con el blog
contenedor, que utilizarás como base la imagen oficial de WordPress. Agrega esta configuración al final del archivo:
docker-compose.yml
...services: blog: image: wordpress:4.9.8-apache environment: WORDPRESS_DB_PASSWORD: labels: - traefik.http.routers.blog.rule=Host(`blog.your_domain`) - traefik.http.routers.blog.tls=true - traefik.http.routers.blog.tls.certresolver=lets-encrypt - traefik.port=80 networks: - internal - web depends_on: - mysql
La environment
clave te permite especificar variables de entorno que se configurarán dentro del contenedor. Si no configuras un valor para WORDPRESS_DB_PASSWORD
, le estás indicando a Docker Compose que obtenga el valor de tu shell y lo pase cuando crees el contenedor. Definirás esta variable de entorno en tu shell antes de iniciar los contenedores. De esta manera, no codificarás las contraseñas en el archivo de configuración.
La labels
sección es donde se especifican los valores de configuración para Traefik. Las etiquetas de Docker no hacen nada por sí mismas, pero Traefik las lee para saber cómo tratar los contenedores. Esto es lo que hace cada una de estas etiquetas:
traefik.http.routers.adminer.rule=Host(```
blog.your_domain
```)
crea un nuevo enrutador para su contenedor y luego especifica la regla de enrutamiento utilizada para determinar si una solicitud coincide con este contenedor.traefik.routers.custom_name.tls=true
especifica que este enrutador debe usar TLS.traefik.routers.custom_name.tls.certResolver=lets-encrypt
especifica que el solucionador de certificados que creó anteriormentelets-encrypt
debe usarse para obtener un certificado para esta ruta.traefik.port
especifica el puerto expuesto que Traefik debe usar para enrutar el tráfico a este contenedor.
Con esta configuración, todo el tráfico enviado a su host Docker en el puerto 80
o 443
con el dominio de se enrutará al contenedor.blog.your_domain
blog
Asigna este contenedor a dos redes diferentes para que Traefik pueda encontrarlo a través de la web
red y pueda comunicarse con el contenedor de la base de datos a través de la internal
red.
Por último, la depends_on
clave le indica a Docker Compose que este contenedor debe iniciarse después de que se ejecuten sus dependencias. Dado que WordPress necesita una base de datos para ejecutarse, debe ejecutar su mysql
contenedor antes de iniciarlo blog
.
A continuación, configure el servicio MySQL:
docker-compose.yml
services:... mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: networks: - internal labels: - traefik.enable=false
Estás usando la imagen oficial de MySQL 5.7 para este contenedor. Notarás que estás usando nuevamente un environment
elemento sin un valor. Las variables MYSQL_ROOT_PASSWORD
y WORDPRESS_DB_PASSWORD
deberán configurarse con el mismo valor para asegurarte de que tu contenedor de WordPress pueda comunicarse con MySQL. No quieres exponer el mysql
contenedor a Traefik ni al mundo exterior, por lo que solo estás asignando este contenedor a la internal
red. Dado que Traefik tiene acceso al socket de Docker, el proceso aún expondrá un enrutador para el mysql
contenedor de manera predeterminada, por lo que agregarás la etiqueta traefik.enable=false
para especificar que Traefik no debe exponer este contenedor.
Por último, defina el contenedor Adminer:
docker-compose.yml
services:... adminer: image: adminer:4.6.3-standalone labels: - traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`) - traefik.http.routers.adminer.tls=true - traefik.http.routers.adminer.tls.certresolver=lets-encrypt - traefik.port=8080 networks: - internal - web depends_on: - mysql
Este contenedor se basa en la imagen oficial de Adminer. La configuración network
y depends_on
el tamaño de este contenedor coinciden exactamente con lo que estás usando para blog
él.
La línea le indica a Traefik que examine el host solicitado. Si coincide con el patrón de , Traefik enrutará el tráfico al contenedor a través del puerto .traefik.http.routers.adminer.rule=Host(```
db-admin.your_domain
```)
db-admin.your_domain
adminer
8080
Su docker-compose.yml
archivo completo se verá así:
docker-compose.yml
version: "3"networks: web: external: true internal: external: falseservices: blog: image: wordpress:4.9.8-apache environment: WORDPRESS_DB_PASSWORD: labels: - traefik.http.routers.blog.rule=Host(`blog.your_domain`) - traefik.http.routers.blog.tls=true - traefik.http.routers.blog.tls.certresolver=lets-encrypt - traefik.port=80 networks: - internal - web depends_on: - mysql mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: networks: - internal labels: - traefik.enable=false adminer: image: adminer:4.6.3-standalone labels: labels: - traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`) - traefik.http.routers.adminer.tls=true - traefik.http.routers.adminer.tls.certresolver=lets-encrypt - traefik.port=8080 networks: - internal - web depends_on: - mysql
Guarde el archivo y salga del editor de texto.
A continuación, establezca valores en su shell para las variables WORDPRESS_DB_PASSWORD
y :MYSQL_ROOT_PASSWORD
- export WORDPRESS_DB_PASSWORD=secure_database_password
- export MYSQL_ROOT_PASSWORD=secure_database_password
Sustitúyala secure_database_password
por la contraseña de base de datos que desee. Recuerde utilizar la misma contraseña para WORDPRESS_DB_PASSWORD
y MYSQL_ROOT_PASSWORD
.
Con estas variables configuradas, ejecute los contenedores usando docker-compose
:
- docker-compose up -d
Ahora observe el panel de administración de Traefik mientras se completa.
Si explora la sección Routers encontrará routers habilitados adminer
y blog
configurados con TLS:
Vaya a , sustituyendo por su dominio. Se lo redireccionará a una conexión TLS y ahora podrá completar la configuración de WordPress:blog.your_domain
your_domain
Ahora, acceda a Adminer desde su navegador y, nuevamente, sustituya el nombre de su dominio. El contenedor no está expuesto al mundo exterior, pero tiene acceso a él a través de la red Docker que comparten y usa el nombre del contenedor como nombre de host.db-admin.your_domain
your_domain
mysql
adminer
internal
mysql
En la pantalla de inicio de sesión de administrador, ingrese root
en Nombre de usuario , ingrese mysql
en Servidor e ingrese el valor que estableció MYSQL_ROOT_PASSWORD
en Contraseña . Deje Base de datos vacía. Ahora presione Iniciar sesión .
Una vez que haya iniciado sesión, verá la interfaz de usuario de administrador.
Ambos sitios ya están funcionando y puedes usar el panel de control para vigilar tus aplicaciones.monitor.your_domain
Conclusión
En este tutorial, configuró Traefik v2 para enviar solicitudes a otras aplicaciones en contenedores Docker.
La configuración declarativa de Traefik a nivel de contenedor de aplicaciones facilita la configuración de más servicios y no es necesario reiniciar el traefik
contenedor cuando se agregan nuevas aplicaciones al proxy de tráfico, ya que Traefik nota los cambios inmediatamente a través del archivo de socket de Docker que está monitoreando.
Para obtener más información sobre lo que puede hacer con Traefik v2, consulte la documentación oficial de Traefik.
Deja una respuesta