Este post é principalmente para mim: acho a documentação do Traefik difícil de navegar, então, tendo descoberto isso em resposta a uma pergunta no Stack Overflow , estou colocando aqui para ajudá-lo a ficar na minha cabeça.

A questão pergunta essencialmente como executar o roteamento de solicitações para contêineres baseado em porta, de modo que uma solicitação de http://example.comvá para um contêiner enquanto uma solicitação de http://example.com:9090vá para um contêiner diferente.

Criando pontos de entrada

Uma configuração padrão do Traefik já terá um listener na porta 80, mas se quisermos aceitar conexões na porta 9090, precisamos criar um novo listener: o que o Traefik chama de entrypoint . Fazemos isso usando a --entrypoints..addressopção. Por exemplo, --entrypoints.ep1.address=80cria um ponto de entrada chamado ep1na porta 80, enquanto --entrypoints.ep2.address=9090cria um ponto de entrada chamado ep2na porta 9090. Esses nomes são importantes porque os usaremos para mapear contêineres para o ouvinte apropriado mais tarde.

Isso nos dá uma configuração do Traefik que se parece com:

  proxy:
    image: traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --entrypoints.ep1.address=:80
      - --entrypoints.ep2.address=:9090
    ports:
      - "80:80"
      - "127.0.0.1:8080:8080"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Precisamos publicar portas 809090no host para aceitar conexões. A porta 8080 é, por padrão, o painel do Traefik; nesta configuração, eu o tenho vinculado localhostporque não quero fornecer acesso externo ao painel.

Serviços de roteamento

Agora precisamos configurar nossos serviços para que as conexões nas portas 80 e 9090 sejam roteadas para os contêineres apropriados. Fazemos isso usando o traefik.http.routers..entrypointsrótulo. Aqui está um exemplo simples:

app1:
  image: docker.io/alpinelinux/darkhttpd:latest
  labels:
    - traefik.http.routers.app1.entrypoints=ep1
    - traefik.http.routers.app1.rule=Host(`example.com`)

Na configuração acima, estamos usando os seguintes rótulos:

  • traefik.http.routers.app1.entrypoints=ep1

    Isso vincula nosso app1contêiner ao ponto de ep1entrada.

  • traefik.http.routers.app1.rule=Host(`example.com`)

    Isso corresponde a solicitações com Host: example.com.

Então, em combinação, essas duas regras dizem que qualquer solicitação na porta 80 Host: example.comserá roteada para o app1contêiner.

Para obter a porta 9090roteada para um segundo contêiner, adicionamos:

app2:
  image: docker.io/alpinelinux/darkhttpd:latest
  labels:
    - traefik.http.routers.app2.rule=Host(`example.com`)
    - traefik.http.routers.app2.entrypoints=ep2

Isso é a mesma coisa, exceto que usamos entrypoint ep2.

Com tudo rodando, podemos observar os logs docker-compose upe ver que uma requisição na porta 80:

curl -H 'host: example.com' localhost

É atendido por app1:

app1_1   | 172.20.0.2 - - [21/Jun/2022:02:44:11 +0000] "GET / HTTP/1.1" 200 354 "" "curl/7.76.1"

E essa solicitação na porta 9090:

curl -H 'host: example.com' localhost:9090

É atendido por app2:

app2_1   | 172.20.0.2 - - [21/Jun/2022:02:44:39 +0000] "GET / HTTP/1.1" 200 354 "" "curl/7.76.1"

docker-compose.yamlarquivo completo deste post se parece com:

version: "3"

services:
  proxy:
    image: traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --entrypoints.ep1.address=:80
      - --entrypoints.ep2.address=:9090
    ports:
      - "80:80"
      - "8080:8080"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  app1:
    image: docker.io/alpinelinux/darkhttpd:latest
    labels:
      - traefik.http.routers.app1.rule=Host(`example.com`)
      - traefik.http.routers.app1.entrypoints=ep1

  app2:
    image: docker.io/alpinelinux/darkhttpd:latest
    labels:
      - traefik.http.routers.app2.rule=Host(`example.com`)
      - traefik.http.routers.app2.entrypoints=ep2