Docker + DNSMasq + Traekif como proxy reverso

Fábio J L Ferreira
4 min readSep 25, 2021

É natural que com o passar do tempo as aplicações necessitem de mais recursos para continuar operando de forma saudável, isso pode ocorrer devido ao aumento no número de requisições, mais usuários utilizando simultaneamente ou até ao lançamento de novas features que demandam maior uso de recursos… Você irá avaliar o cenário/negócio e determinar se irá escalar sua aplicação de forma vertical ou horizontal… Ao longo deste post irei demonstrar uma opção para escala horizontal, sendo assim vem comigo!

❗️Pré-requisitos

Para o pleno aproveitamento desta material é necessário que você tenha familiaridade com as seguintes tecnologias e ferramentas:

  • Docker
  • Docker-compose
  • Linux

Introdução

Vamos direto ao ponto! Esse é o desenho final da solução:

Na proposta acima estou utilizando o DNSMasq como Sistema de Nome de Domínio (DNS) e o Traefik como Proxy Reverso e Balanceador de Carga, ou seja, utilizando essa abordagem eu posso começar minha infra com 1 servidor de aplicação e posteriormente escalar horizontalmente conforme necessidade.

Configurando a infra

Crie um diretório de trabalho e posteriormente acesse o mesmo, por exemplo:

mkdir dev-stack && cd dev-stack

Agora devemos definir as configurações do servidor DNS, para isso crie o arquivo dnsmasq.conf e adicione o seguinte conteúdo a ele:

listen-address=0.0.0.0
interface=eth0
user=root
no-resolv
server=8.8.8.8
server=8.8.4.4
address=/.test/127.0.0.1

Crie o arquivo traefik.yml e adicione este conteúdo a ele:

providers:
docker:
defaultRule: "Host(`{{ trimPrefix `/` .Name }}.test`)"
api:
insecure: true

Para que os containers consigam se comunicar uns com os outros é necessário que eles estejam conectados a mesma rede Docker. Sendo vamos criar essa rede:

docker network create my-network

Você é livre para nomear sua rede como quiser, porém, se tiver utilizado um nome diferente do exemplo acima, você deverá considerar essa alteração nas configurações apresentadas logo abaixo.

Crie o arquivo docker-compose.yml e adicione este conteúdo a ele:

version: "3.3"services:  dnsmasq:
image: andyshinn/dnsmasq
cap_add:
- NET_ADMIN
restart: always
ports:
- "53:53/udp"
- "53:53/tcp"
volumes:
- ./dnsmasq.conf:/etc/dnsmasq.conf
command: --log-facility=-
traefik:
image: "traefik:v2.2"
container_name: "traefik"
restart: always
command:
- "--log.level=ERROR"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik.yml:/etc/traefik/traefik.yml"
networks:
default:
external:
name: my-network

Agora execute:

docker-compose up -d

Pronto, nosso ambiente está online. Você pode acessar o dashboard do Traefik em: http://localhost:8080.

Ah, já ia me esquecendo, você precisa incluir o endereço 127.0.0.1 como DNS primário. Eu pessoalmente recomendo que você inclua esta forma:

Imagem da configuração de DNS no MacOS.

A imagem acima é uma configuração realizada no MacOS, caso tenha dificuldade para efetuar essa alteração no seu sistema operacional, realize uma pesquisa rápida no Google. Além do endereço localhost(127.0.0.1) eu tenho o hábito de incluir outros dois endereços DNS públicos, no caso acima o DNS primário e secundário do Google. Realizo este ajuste pois se meus containers do DNSMasq e Traefik estiverem parados, o sistema irá pegar o próximo endereço DNS da lista.

Para saber mais a respeito do Traefik, acesse: https://doc.traefik.io/traefik/providers/docker/

Subindo nossa aplicação

Vamos criar um novo diretório fora da estrutura criada no tópico anterior, ou seja, esse diretório é uma estrutura totalmente apartada:

mkdir meu-app && cd meu-app

Crie um arquivo src/index.php com o seguinte conteúdo:

<?phpecho gethostname();

Esse código imprime o hostname do container.

E na raiz do diretório meu-app você deverá criar um arquivo chamado docker-compose.yml com o seguinte conteúdo:

version: '3'services:
php:
image: fabiojanio/php:8.0-alpine3.14
labels:
- traefik.http.routers.php.rule=Host(`my-app.test`)
volumes:
- ./src/:/app
working_dir: /app
restart: on-failure
user: www-data
command: >
sh -c "php -S 0.0.0.0:80 index.php"
networks:
default:
external:
name: my-network

Observe que temos uma label do Traefik dentro do docker-compose.yml, ou seja, essa label é um metadado que o Traefik irá utilizar para associar este container ao endereço informado, neste caso my-app.test.

Execute:

docker-compose up -d

E acesse em seu navegador o endereço http://my-app.test.

Para escalar nossa aplicação basta executar:

docker-compose up -d --scale php=3

No exemplo acima fizemos o autoscaling manualmente, porém, este poderia ser realizado automaticamente com base no consumo de CPU, RAM, etc.

A instrução acima orienta o Docker a escalar o serviço PHP para um total de 3 containers. Volte ao navegador e fique aplicando um refresh na página! Notou que o ID apresentado fica variando? Pois então, nosso balanceamento está funcionando perfeitamente, afinal de contas esse ID é o hostname.

--

--

Fábio J L Ferreira

Arquiteto de software, palestrante e um profundo admirador a filosofia do software livre...