Traefik: Proxy inverso y balanceador de carga para Docker
Traefik es un proxy inverso y balanceador de carga que se integra nativamente con Docker y Kubernetes, así como con otras tecnologías de cluster como Mesos o Amazon ECS.
En este post vamos a utilizar Traefik como proxy inverso hasta una instalación de WordPress realizada mediante Docker y docker-compose . Utilizaremos el dominio canonigos.me que apuntará mediante un wildcard DNS a una instancia EC2 en AWS.
Índice de contenidos
Prerrequisitos
Partimos de una instancia con direccionamiento público y sistema operativo Debian 10 64bits.
Instalación de [crayon-673f52c8128a2569439312-i/] y [crayon-673f52c8128a4338366843-i/]
Vamos a instalar Docker y la herramienta docker-compose en nuestro host:
1 2 3 4 |
# Actualizamos los paquetes del sistema e instalamos la key del repositorio de docker sudo apt update sudo apt -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Agregamos repositorio de docker para Debian y actualizamos fuentes. sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/debian \ $(lsb_release -cs) \ stable" sudo apt update # Instalamos docker-ce y agregamos nuestro usuario al grupo docker. # De esta forma no necesitaremos ejecutar el comando docker mediante sudo. sudo apt install docker-ce sudo usermod -aG docker ${USER} # Podemos comprobar tras cerrar sesión y volver a entrar que ya tenemos docker instalado. admin@ip-10-0-3-96:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # Descargamos docker-compose y lo hacemos ejecutable sudo curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose # Comprobamos la versión instalada admin@ip-10-0-3-96:~$ docker-compose --version docker-compose version 1.27.4, build 40524192 |
Configurando Traefik por primera vez: Accediendo al Dashboard
Una vez tenemos el entorno preparado para instalar contenedores docker, vamos a configurar una carpeta en nuestro directorio de usuario para poder desplegar Traefik.
1 2 3 4 5 6 7 8 9 10 11 |
# Creamos el directorio que albegará las configuraciones de Traefik y el docker-compose.yml mkdir ~/traefik && cd traefik mkdir -p data/configurations touch docker-compose.yml # Creamos el fichero de configuración estática touch data/traefik.yml # Creamos el fichero de configuración dinámica. touch data/configurations/dynamic.yml # Creamos el fichero que albergará las respuestas de Let's Encrypt touch data/acme.json chmod 600 data/acme.json |
El siguiente paso será editar el fichero docker-compose.yml . En él definiremos la versión del contenedor a utilizar, en este caso la etiqueta será latest . También definiremos que los puertos que expondrá serán 80 y 443 . Definiremos volúmenes y ficheros a importar dentro del contenedor (configuración estática, dinámica y fichero para letsencrypt). También usaremos una red llamada proxy que daremos de alta más adelante para usarla con los contenedores.
Por último, una parte importante son las etiquetas con las que configuraremos este despliegue. Éstas definirán el dominio a usar ( traefik.canonigos.me ), el entrypoint que hemos llamado websecure y que irá dirigido contra el Dashboard de Traefik ( service=api@internal ) y la red que tendrá agregada el contenedor ( proxy ).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# docker-compose.yml version: '3.7' services: traefik: image: traefik:latest container_name: traefik restart: always security_opt: - no-new-privileges:true ports: - 80:80 - 443:443 volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./data/traefik.yml:/traefik.yml:ro - ./data/acme.json:/acme.json - ./data/configurations:/configurations networks: - proxy labels: - "traefik.enable=true" - "traefik.docker.network=proxy" - "traefik.http.routers.traefik-secure.entrypoints=websecure" - "traefik.http.routers.traefik-secure.rule=Host(`traefik.canonigos.me`)" - "traefik.http.routers.traefik-secure.middlewares=user-auth@file" - "traefik.http.routers.traefik-secure.service=api@internal" networks: proxy: external: true |
Una vez configurado el fichero docker-compose.yml , pasamos a editar la configuración estática de Traefik:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# data/traefik.yml api: dashboard: true # Definición de los entrypoints entryPoints: web: address: :80 http: redirections: entryPoint: to: websecure websecure: address: :443 http: middlewares: - secureHeaders@file tls: certResolver: letsencrypt # Proveedores: Docker y configuración dinámica mediante provider de tipo file. providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false file: filename: /configurations/dynamic.yml # Configuración Let's Encrypt que usaremos en el entrypoint websecure certificatesResolvers: letsencrypt: acme: email: admin@canonigos.me storage: acme.json keyType: EC384 httpChallenge: entryPoint: web |
Y, por último, editaremos la configuración dinámica. En ella, definiremos las cabeceras por defecto para las conexiones SSL hasta nuestro middleware, la capa de autenticación mediante basic-auth y los ciphers, así como la versión que usará nuestra capa TLS.
Para la autenticación hemos utilizado el paquete apache2-utils , solicitando una clave de la siguiente forma:
1 2 |
htpasswd -nb admin PasswordSuperSegura admin:$apr1$NQlSR6h1$lQnllz9cQhXHK8gFdP0yf0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# data/configurations/dynamic.yml http: middlewares: secureHeaders: headers: sslRedirect: true forceSTSHeader: true stsIncludeSubdomains: true stsPreload: true stsSeconds: 31536000 user-auth: basicAuth: users: - "admin:$apr1$NQlSR6h1$lQnllz9cQhXHK8gFdP0yf0" tls: options: default: cipherSuites: - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 minVersion: VersionTLS12 |
Antes de terminar, debemos recordar crear la red proxy que hemos definido en los distintos ficheros de configuración:
1 2 |
admin@ip-10-0-3-96:~/traefik$ docker network create proxy bfcdd1d7fd978120d2f1589102704f944f856027ddf9995dd985b92754ff9481 |
Arrancando Traefik por primera vez
Y llegó el momento esperado, vamos a levantar Traefik mediante docker-compose . En nuestro caso hemos configurado un Wildcard DNS para que cualquier host del dominio canonigos.me vaya a la IP de nuestra instancia EC2 en Amazon.
También hemos habilitado Let’s Encrypt y Traefik se encargará mediante los resolvers configurados de generar un certificado válido de forma automática para el hostname elegido, en nuestro caso traefik.canonigos.me .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Ejecutamos el stack de docker-compose creado admin@ip-10-0-3-96:~/traefik$ docker-compose up -d Pulling traefik (traefik:latest)... latest: Pulling from library/traefik 0a6724ff3fcd: Pull complete 64d0c2f48fed: Pull complete ce56bf94d075: Pull complete 4de49a0677f6: Pull complete Digest: sha256:dec15c406c554e6319a497003f2428f06146e15c7a08016c4565dc5a1711ecdb Status: Downloaded newer image for traefik:latest Creating traefik ... done # Verificamos que está corriendo admin@ip-10-0-3-96:~/traefik$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 807285307a14 traefik:latest "/entrypoint.sh trae…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp traefik |
Para comprobar el buen funcionamiento de nuestra configuración, si accedemos a http://traefik.canonigos.me debería redirigirnos a la url asegurada mediante el certificado. De igual forma, nos solicitará el par usuario/contraseña configurado mediante el basic-auth.
Para comprobarlo en consola, usaremos mi querido amigo httpie :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# Consultamos la url traefik.canonigos.me sin https, obtenemos solo cabeceras # Vemos el 301 hasta https://traefik.canonigos.me admin@ip-10-0-3-96:~/traefik$ http -h traefik.canonigos.me HTTP/1.1 301 Moved Permanently Content-Length: 17 Content-Type: text/plain; charset=utf-8 Date: Mon, 28 Dec 2020 19:30:13 GMT Location: https://traefik.canonigos.me/ # Consultamos la url asegurada con certificado # Nos devuelve un 401 Unauthorized admin@ip-10-0-3-96:~/traefik$ http -h https://traefik.canonigos.me HTTP/1.1 401 Unauthorized Content-Length: 17 Content-Type: text/plain Date: Mon, 28 Dec 2020 19:30:20 GMT Strict-Transport-Security: max-age=31536000; includeSubDomains; preload Www-Authenticate: Basic realm="traefik" # Consultamos la url asegurada en el path del DashBoard utilizando las credenciales de autenticación basic-auth configuradas # Obtenemos un 200 - Bingo admin@ip-10-0-3-96:~/traefik$ http -h -a admin:PasswordSuperSegura https://traefik.canonigos.me/dashboard/ HTTP/1.1 200 OK Accept-Ranges: bytes Content-Length: 3026 Content-Type: text/html; charset=utf-8 Date: Mon, 28 Dec 2020 19:37:56 GMT Last-Modified: Thu, 17 Dec 2020 16:34:23 GMT Strict-Transport-Security: max-age=31536000; includeSubDomains; preload |
Por si no te lo crees, aquí te dejo una captura del Dashboard de nuestro Traefik recién instalado.
En el siguiente post desplegaremos un WordPress mediante Docker y lo enrutaremos automáticamente mediante labels a través de Traefik, dotándolo de certificado de seguridad Let’s Encrypt.
Deja una respuesta